Im developing a "operating system" on ARM. My context switching code for swapping between tasks is not working.
I have a function demo() which I am calling in main. In this I am creating a "fake context" for my task, consisting of 16 empty register values which will be swapped into the cpu registers when I load the task. Once I do so, I call a supervisor call which enters the PendSV handler, and in this handler i have the assembler code for loading/unloading registers. The printertask() will repeatedly load itself and deload itself by calling the PendSV code.
My code is able to Load the printertask() task context and run it once, but it has trouble loading it back after saving it. I suspect something is going wrong during the saving process. The program hardfaults currently after trying to load the program after it ran once
void printertask() {
printf("Printing some text here\r\n");
__set_PSP(THREAD_SPACE_START); // set PSP to the top of the stack location
__asm("SVC #10"); // My custom SVC which redirects to PendSV
}
void switchTest() {
printf("Switch test, TSP %p %ld\r\n", THREAD_SPACE_START, *THREAD_SPACE_START);
__set_PSP(THREAD_SPACE_START - 15); // set psp to stack head
}
// stack grows down from MSP Init val
void demo() {
uint32_t* MSP_INIT_VAL = *(uint32_t**)0x0;
THREAD_SPACE_START = (uint32_t)MSP_INIT_VAL - MAIN_STACK_SIZE;
// make fake context and set psp
uint32_t* stack_ptr = THREAD_SPACE_START;
*(stack_ptr) = 1 << 24;
*(--stack_ptr) = (uint32_t)printertask;
for (int i = 0; i < 14; i++)
{
*(--stack_ptr) = 0xA;
}
__set_PSP(stack_ptr - 17); // set psp to some garbage value for deloading stack into
// examine
stack_ptr = THREAD_SPACE_START;
for (int i = 0; i < 16; i++) {
printf("%p: %ld\r\n", stack_ptr, *stack_ptr);
stack_ptr--;
}
// deload registers, load fake context, then run task
__asm("SVC #3");
}
Logs:
BEGIN
(these next lines show the fake register values as loaded into memory from demo())
0x20017c00: 16777216
0x20017bfc: 134219281 (start of printer function in instruction memory)
0x20017bf8: 10 (0xA)
0x20017bf4: 10
0x20017bf0: 10
0x20017bec: 10
0x20017be8: 10
0x20017be4: 10
0x20017be0: 10
0x20017bdc: 10
0x20017bd8: 10
0x20017bd4: 10
0x20017bd0: 10
0x20017bcc: 10
0x20017bc8: 10
0x20017bc4: 10
svc_number 3
Switch test, TSP 0x20017c00 16777216
Printer
svc_number 3
Switch test, TSP 0x20017c00 10
(hardfaults here)
Is this a problem with my understanding of LDMIA? I have a -15 offset so it starts loading from the bottom of the task stack in memory (or at least thats what im trying to do). From my understanding the BX LR to the magic number will restore the 8 saved special registers. In the switchTest() log it seems that PSP is set properly to the top of the stack on the second load and the value matches. So i think it is a problem with my command usage somehow.
