2019-12-02 16:48:36 +01:00
|
|
|
#include <stdint.h>
|
|
|
|
#include <stddef.h>
|
2020-01-14 18:41:28 +01:00
|
|
|
#include <kernel/types.h>
|
2019-12-16 16:25:13 +01:00
|
|
|
#include <kernel/context.h>
|
|
|
|
#include <kernel/atomic.h>
|
2019-12-29 16:39:30 +01:00
|
|
|
#include <kernel/process.h>
|
2019-12-30 16:31:03 +01:00
|
|
|
#include <kernel/syscall.h>
|
2020-01-14 18:41:28 +01:00
|
|
|
#include <kernel/scheduler.h>
|
2019-12-30 16:31:03 +01:00
|
|
|
#include <kernel/util.h>
|
2020-01-05 09:00:43 +01:00
|
|
|
#include <kernel/fs/vfs.h>
|
|
|
|
#include <kernel/fs/stat.h>
|
|
|
|
#include <kernel/util.h>
|
2019-12-30 16:31:03 +01:00
|
|
|
|
|
|
|
//TODO: remove me !
|
2020-01-05 09:00:43 +01:00
|
|
|
#include <kernel/fs/smemfs.h>
|
|
|
|
#include <kernel/fs/gladfs.h>
|
2019-12-30 16:31:03 +01:00
|
|
|
#include <kernel/loader.h>
|
2020-01-05 09:00:43 +01:00
|
|
|
#include <kernel/devices/tty.h>
|
2019-12-02 16:48:36 +01:00
|
|
|
|
|
|
|
// Internal symbols
|
|
|
|
mpu_t current_mpu = MPU_UNKNOWN;
|
|
|
|
|
2019-12-16 16:25:13 +01:00
|
|
|
// Internal hardware context.
|
|
|
|
fx9860_context_t casio_context;
|
|
|
|
fx9860_context_t vhex_context;
|
|
|
|
|
2019-12-02 16:48:36 +01:00
|
|
|
// Symbols defined by the linker
|
|
|
|
extern uint32_t bbss;
|
|
|
|
extern uint32_t sbss;
|
|
|
|
extern uint32_t bdata_ram;
|
|
|
|
extern uint32_t bdata_rom;
|
|
|
|
extern uint32_t sdata;
|
|
|
|
extern uint32_t bvhex_ram;
|
|
|
|
extern uint32_t bvhex_rom;
|
|
|
|
extern uint32_t svhex;
|
2019-12-09 15:57:06 +01:00
|
|
|
extern uint32_t bubc_ram;
|
|
|
|
extern uint32_t bubc_rom;
|
|
|
|
extern uint32_t subc;
|
2019-12-16 16:25:13 +01:00
|
|
|
extern uint32_t brom;
|
|
|
|
extern uint32_t srom;
|
|
|
|
extern uint32_t bctors;
|
|
|
|
extern uint32_t ectors;
|
|
|
|
extern uint32_t bdtors;
|
|
|
|
extern uint32_t edtors;
|
2019-12-02 16:48:36 +01:00
|
|
|
|
|
|
|
// Internal functions.
|
2019-12-16 16:25:13 +01:00
|
|
|
extern void vhex_context_set(void);
|
2019-12-29 16:39:30 +01:00
|
|
|
extern void kernel_switch(common_context_t *context);
|
2019-12-09 15:57:06 +01:00
|
|
|
extern mpu_t mpu_get(void);
|
2019-12-02 16:48:36 +01:00
|
|
|
extern int main(void);
|
|
|
|
|
2020-01-05 09:00:43 +01:00
|
|
|
// Internal object
|
|
|
|
extern struct file_system_type gladfs_filesystem;
|
|
|
|
extern struct file_system_type smemfs_filesystem;
|
|
|
|
|
2019-12-09 15:57:06 +01:00
|
|
|
|
2019-12-20 11:31:34 +01:00
|
|
|
//
|
|
|
|
// rom_explore() - explore all add-in ROM part.
|
|
|
|
// @note:
|
|
|
|
// For now, we can not use the MMU so we can
|
|
|
|
// not handle TLB miss. Casio load only the first 4ko
|
|
|
|
// of the add-in. To avoid TLB miss we explore all
|
|
|
|
// add-in binary to force Casio to generate all pages
|
|
|
|
// into the TLB.
|
|
|
|
//
|
2019-12-16 16:25:13 +01:00
|
|
|
static void rom_explore(volatile void *rom, int32_t size)
|
2019-12-06 23:45:04 +01:00
|
|
|
{
|
2019-12-16 16:25:13 +01:00
|
|
|
uint8_t unused;
|
2019-12-06 23:45:04 +01:00
|
|
|
|
2019-12-16 16:25:13 +01:00
|
|
|
(void)unused;
|
|
|
|
while (size >= 0)
|
2019-12-09 15:57:06 +01:00
|
|
|
{
|
2019-12-16 16:25:13 +01:00
|
|
|
unused = *(volatile uint8_t*)rom;
|
|
|
|
rom = (void*)((uint32_t)rom + 1024);
|
|
|
|
size = size - 1024;
|
2019-12-09 15:57:06 +01:00
|
|
|
}
|
2019-12-16 16:25:13 +01:00
|
|
|
}
|
2019-12-09 15:57:06 +01:00
|
|
|
|
2019-12-20 11:31:34 +01:00
|
|
|
/* section_execute() - Used to execute contructors and destructors */
|
2019-12-16 16:25:13 +01:00
|
|
|
static void section_execute(void *bsection, void *esection)
|
|
|
|
{
|
|
|
|
while ((uint32_t)bsection < (uint32_t)esection)
|
2019-12-06 23:45:04 +01:00
|
|
|
{
|
2019-12-16 16:25:13 +01:00
|
|
|
((void (*)(void))*((uint32_t*)bsection))();
|
|
|
|
bsection = (void*)((uint32_t)bsection + 4);
|
2019-12-06 23:45:04 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-01-06 20:25:06 +01:00
|
|
|
|
2019-12-20 11:31:34 +01:00
|
|
|
/* start() - Kernel entry point */
|
2019-12-02 16:48:36 +01:00
|
|
|
__attribute__((section(".pretext")))
|
|
|
|
int start(void)
|
|
|
|
{
|
2019-12-30 16:31:03 +01:00
|
|
|
extern uint32_t vram[256];
|
2019-12-02 16:48:36 +01:00
|
|
|
int error;
|
|
|
|
|
2020-01-12 15:58:35 +01:00
|
|
|
//--
|
|
|
|
// Bootstrap part !
|
|
|
|
//--
|
|
|
|
|
2019-12-02 16:48:36 +01:00
|
|
|
// Wipe .bss section and dump .data / Vhex sections
|
2019-12-16 16:25:13 +01:00
|
|
|
memset(&bbss, 0x00, (size_t)&sbss);
|
|
|
|
memcpy(&bdata_ram, &bdata_rom, (size_t)&sdata);
|
2019-12-02 16:48:36 +01:00
|
|
|
|
|
|
|
// Check MPU hardware.
|
|
|
|
current_mpu = mpu_get();
|
|
|
|
if (current_mpu != MPU_SH7305)
|
|
|
|
{
|
|
|
|
return (0);
|
|
|
|
}
|
|
|
|
|
2019-12-16 16:25:13 +01:00
|
|
|
// Execute constructor.
|
|
|
|
section_execute(&bctors, &ectors);
|
|
|
|
|
|
|
|
// Load UBC / VBR space.
|
|
|
|
memcpy(&bubc_ram, &bubc_rom, (size_t)&subc);
|
|
|
|
memcpy(&bvhex_ram, &bvhex_rom, (size_t)&svhex);
|
|
|
|
|
|
|
|
// Casio do not load all add-in
|
|
|
|
// page. So we need to "force" update TLB
|
|
|
|
// before switching the VBR.
|
|
|
|
rom_explore(&brom, (int32_t)&srom);
|
|
|
|
|
2019-12-20 11:31:34 +01:00
|
|
|
// Save Casio's hardware context and set
|
2019-12-16 16:25:13 +01:00
|
|
|
// Vhex hardware context.
|
|
|
|
// @note:
|
|
|
|
// This operation should be atomic
|
|
|
|
// because if an interruption or exception
|
|
|
|
// occur during the hardware context change
|
|
|
|
// the calculator will crash.
|
2019-12-20 11:31:34 +01:00
|
|
|
// And this is why between each `atomic_start`
|
2019-12-16 16:25:13 +01:00
|
|
|
// and `atomic_end()` the code *SHOULD* be
|
|
|
|
// exception safe.
|
2019-12-02 16:48:36 +01:00
|
|
|
atomic_start();
|
|
|
|
fx9860_context_save(&casio_context);
|
|
|
|
vhex_context_set();
|
2020-01-08 10:14:11 +01:00
|
|
|
atomic_stop();
|
2019-12-02 16:48:36 +01:00
|
|
|
|
2020-01-12 15:58:35 +01:00
|
|
|
//---
|
|
|
|
// File System part !
|
|
|
|
//---
|
|
|
|
|
2020-01-05 09:00:43 +01:00
|
|
|
// Internal FS init !
|
|
|
|
gladfs_initialize();
|
|
|
|
smemfs_initialize();
|
|
|
|
|
|
|
|
// Initilize Virtual File System
|
|
|
|
vfs_register_filesystem(&gladfs_filesystem);
|
|
|
|
vfs_register_filesystem(&smemfs_filesystem);
|
|
|
|
|
|
|
|
// Creat initial file tree
|
|
|
|
vfs_mount(NULL, NULL, "gladfs", VFS_MOUNT_ROOT, NULL);
|
|
|
|
vfs_mkdir("/dev", S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH);
|
2020-01-10 17:21:44 +01:00
|
|
|
vfs_mkdir("/home", S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH);
|
2020-01-05 09:00:43 +01:00
|
|
|
vfs_mkdir("/mnt", S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH);
|
2020-01-05 10:35:44 +01:00
|
|
|
vfs_mkdir("/mnt/smemfs", S_IRUSR | S_IXUSR | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH);
|
2020-01-05 09:00:43 +01:00
|
|
|
vfs_mount(NULL, "/mnt/smemfs", "smemfs", /*MS_RDONLY*/0, NULL);
|
2020-01-06 20:25:06 +01:00
|
|
|
|
|
|
|
// Add devices
|
|
|
|
vfs_mknod("/dev/tty", S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH,
|
|
|
|
dev_make_major(TTY_DEV_MAJOR));
|
|
|
|
|
2020-01-12 15:58:35 +01:00
|
|
|
|
|
|
|
// Test mode !
|
2020-01-14 18:41:28 +01:00
|
|
|
//extern void kernel_test(void);
|
2020-01-12 15:58:35 +01:00
|
|
|
//kernel_test();
|
|
|
|
|
|
|
|
//---
|
|
|
|
// Start first process !
|
|
|
|
//---
|
2020-01-05 09:00:43 +01:00
|
|
|
|
2019-12-29 16:39:30 +01:00
|
|
|
// Create first process: Vhex.
|
2020-01-12 15:58:35 +01:00
|
|
|
struct process *vhex_process = process_create("Vhex");
|
|
|
|
if (vhex_process == NULL)
|
|
|
|
{
|
|
|
|
kvram_clear();
|
2020-02-05 21:09:39 +01:00
|
|
|
printk(0, 0, "Vhex fatal error !");
|
|
|
|
printk(0, 1, "First process error !");
|
|
|
|
printk(0, 2, "Wait manual reset...");
|
2020-01-12 15:58:35 +01:00
|
|
|
kvram_display();
|
|
|
|
while (1) { __asm__ volatile ("sleep"); }
|
|
|
|
}
|
2019-12-30 16:31:03 +01:00
|
|
|
|
|
|
|
// Load programe.
|
2020-01-12 15:58:35 +01:00
|
|
|
//vhex_process->context.spc = (uint32_t)&kernel_test;
|
|
|
|
vhex_process->context.spc = (uint32_t)loader("/mnt/smemfs/VHEX/shell.elf", vhex_process);
|
2019-12-30 16:31:03 +01:00
|
|
|
if (vhex_process->context.spc == 0x00000000)
|
|
|
|
{
|
|
|
|
// Display message.
|
|
|
|
kvram_clear();
|
2020-02-05 21:09:39 +01:00
|
|
|
printk(0, 0, "Vhex fatal error !");
|
|
|
|
printk(0, 1, "File \"VHEX/shell.elf\" not found !");
|
|
|
|
printk(0, 2, "Press [MENU key]...");
|
2019-12-30 16:31:03 +01:00
|
|
|
kvram_display();
|
|
|
|
|
|
|
|
// Restore Casio context.
|
|
|
|
fx9860_context_restore(&casio_context);
|
2020-01-08 10:14:11 +01:00
|
|
|
atomic_stop();
|
2019-12-30 16:31:03 +01:00
|
|
|
|
|
|
|
// Casio VRAM workaround
|
2020-01-12 15:58:35 +01:00
|
|
|
// @note: GetKey will call Bdisp_PutDD_VRAM(),
|
|
|
|
// so save the current internal Video RAM data into
|
|
|
|
// Casio's VRAM.
|
2019-12-30 16:31:03 +01:00
|
|
|
memcpy(casio_Bdisp_GetVRAM(), vram, 1024);
|
|
|
|
|
|
|
|
// Wait MENU key.
|
|
|
|
unsigned int key;
|
|
|
|
while (1)
|
|
|
|
{
|
|
|
|
casio_GetKey(&key);
|
|
|
|
}
|
|
|
|
}
|
2020-01-12 15:58:35 +01:00
|
|
|
|
2020-01-14 18:41:28 +01:00
|
|
|
// DEBUG !
|
|
|
|
kvram_clear();
|
|
|
|
printk(0, 0, "Initialize scheduler !");
|
|
|
|
printk(0, 1, "Try to start sceduler...");
|
|
|
|
kvram_display();
|
|
|
|
DBG_WAIT;
|
2020-01-05 10:35:44 +01:00
|
|
|
|
2020-01-14 18:41:28 +01:00
|
|
|
// Initialize sheduler !!
|
|
|
|
sched_initialize();
|
|
|
|
sched_add_task(vhex_process);
|
|
|
|
sched_start();
|
2019-12-02 16:48:36 +01:00
|
|
|
|
2020-01-14 18:41:28 +01:00
|
|
|
// normally the kernel SHOULD / CAN not arrive here.
|
2020-01-01 14:19:18 +01:00
|
|
|
kvram_clear();
|
2020-02-05 21:09:39 +01:00
|
|
|
printk(0, 0, "Kernel job fini !");
|
2020-01-01 14:19:18 +01:00
|
|
|
kvram_display();
|
2019-12-29 16:39:30 +01:00
|
|
|
while (1)
|
|
|
|
{
|
|
|
|
__asm__ volatile ("sleep");
|
|
|
|
}
|
2019-12-16 16:25:13 +01:00
|
|
|
}
|