vxKernel/board/fxcg50/initialize.c

130 lines
4.4 KiB
C

//---
// fxcg50:initialize - Kernel initialization and C runtime
//---
#include "vhex/hardware.h"
#include "vhex/kernel.h"
#include <stdint.h>
#include <stdlib.h>
#include <setjmp.h>
/* Constructor and destructor arrays */
extern void (*bctors)(void), (*ectors)(void);
extern void (*bdtors)(void), (*edtors)(void);
/* User-provided main() function */
extern int main(void);
/* Jumping there will properly unwind and leave the kernel */
jmp_buf vhex_exitbuf;
/* Return value of main() */
int vhex_exitcode;
/* callarray(): Call an array of functions (constructors or destructors) */
static void callarray(void (**f)(void), void (**l)(void))
{
while(f < l) (*(*f++))();
}
/* initialize() : Where it all starts
We are currently in a RAM location at a non-constant address due to the
relocalization performed by the bootloader. Moreover, we are in privileged
mode with one golden rule:
Do not disturb the operating system
Why we should keep this rule in mind? Because, on this particular device,
none of all hardware and software information are documented. Vhex will
therefore involve Casio's syscall to perform some interaction, especially
concerning file manipulation.
Note that we don't need to change the stack, the kernel will use the one
given by Casio because it's big enough to store the user-application
(mainly the vxOS) and the kernel code. However, we need to keep in mind
that for this device, a lot of hardware supposition will be performed here,
chiefly concerning the memory discovery.
+---------------+
| |
| |
| Reserved Area |
| |
| |
+ - - - - - - - + <-- virtually mapped at 0x0810000
| _vxKernel |
| + |
| _vxOS |
+ - - - - - - - + <-- Provided by the vxKernel (variable)
| |
| Stack |
| |
+ - - - - - - - + <-- end of the TLB information (variable)
| |
| |
| |
| |
| kmalloc() |
| |
| |
| |
| |
| |
| |
+---------------+ <-- variable
We know that the "user RAM" is *constantly* mapped at 0x08100000 and all the
memory reserved for the user is completely loaded and all of this information
is stored at the end of the UTLB. Moreover, the stack provided by Casio start
at the end of the "user RAM". So, the memory layout is a bit exotic and look
like above. */
void initialize(void)
{
/* Detect hardware information : This part is important because it will
tell us if we are running in an emulator or on a real device. */
hw_detect();
/* Install Vhex, switch VBR and initialize drivers */
kinit();
//TODO: add area for the kmalloc() ?
/* We are now running on our own in kernel mode. Since we have taken
control of interrupts, pretty much any interaction with the system
will break it. We'll limit our use of syscalls and do device driving
ourselves. (Hopefully we can add cool features in the process!) */
/* Now that we have initialized the kernel, we are ready to start the
hosted user application, which has its own constructors and
destructors to work with. */
/* Here, we use exit() to allow the standard library to do
what it wants in exit() after main() finishes executing */
if(!setjmp(vhex_exitbuf)) {
callarray(&bctors, &ectors);
exit(main());
}
else {
callarray(&bdtors, &edtors);
}
/* Before leaving the kernel (which will return to the bootloader menu),
we need to clean everything we changed to hardware settings and
peripheral modules. The OS is bound to be confused (and hang, or
crash, or any other kind of giving up) if we don't restore them. */
/* Unload vhex and give back control to the system. Driver settings
will be restored while interrupts are disabled */
kquit();
//TODO: involve manualy the Casio's OS-menu
}