2019-12-02 16:48:36 +01:00
|
|
|
#include <stdint.h>
|
|
|
|
#include <stddef.h>
|
2019-12-16 16:25:13 +01:00
|
|
|
#include <kernel/context.h>
|
|
|
|
#include <kernel/atomic.h>
|
2019-12-02 16:48:36 +01:00
|
|
|
#include <kernel/types.h>
|
|
|
|
#include <lib/display.h>
|
2019-12-16 16:25:13 +01:00
|
|
|
#include <kernel/syscall.h>
|
2019-12-02 16:48:36 +01:00
|
|
|
#include <lib/string.h>
|
|
|
|
|
|
|
|
// 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-09 15:57:06 +01:00
|
|
|
extern mpu_t mpu_get(void);
|
2019-12-02 16:48:36 +01:00
|
|
|
extern int main(void);
|
|
|
|
|
2019-12-09 15:57:06 +01:00
|
|
|
|
2019-12-16 16:25:13 +01:00
|
|
|
/* TODO: explain !! */
|
|
|
|
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-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
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-12-02 16:48:36 +01:00
|
|
|
__attribute__((section(".pretext")))
|
|
|
|
int start(void)
|
|
|
|
{
|
2019-12-16 16:25:13 +01:00
|
|
|
unsigned int key;
|
2019-12-02 16:48:36 +01:00
|
|
|
int error;
|
|
|
|
|
|
|
|
// 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);
|
|
|
|
|
|
|
|
// Get Casio's hardware context and set
|
|
|
|
// 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.
|
|
|
|
// And this is why between each `atomic_start`
|
|
|
|
// 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();
|
|
|
|
atomic_end();
|
|
|
|
|
2019-12-16 16:25:13 +01:00
|
|
|
// Call high level abstraction
|
2019-12-02 16:48:36 +01:00
|
|
|
error = main();
|
|
|
|
|
2019-12-16 16:25:13 +01:00
|
|
|
// Restore Casio's context.
|
2019-12-02 16:48:36 +01:00
|
|
|
atomic_start();
|
|
|
|
fx9860_context_restore(&casio_context);
|
|
|
|
atomic_end();
|
|
|
|
|
2019-12-16 16:25:13 +01:00
|
|
|
// Execute destructor.
|
|
|
|
section_execute(&bdtors, &edtors);
|
2019-12-02 16:48:36 +01:00
|
|
|
|
2019-12-16 16:25:13 +01:00
|
|
|
// Return properly
|
|
|
|
// TODO: involve main menu ?
|
|
|
|
return (error);
|
|
|
|
}
|