I just recently started working with a bare STM32F103C8T6 (an ARM Cortex M3) and ran into some difficulties.
I have set up a SysTick_Handler
to switch the current context of the application. The handler invokes a PendSV_Handler
in which I want to save the registers of the CPU to a datastructure. This is the simplified code:
typedef struct Registers {
int r0, r1, r2, r3, r4, r5, r6, r7, r8, r9, r10, r11, r12;
int sp, lr, pc, xPSR;
} Registers;
void PendSV_Handler()
{
Registers reg;
register int r0 asm("r0");
reg.r0 = r0;
/* and so on with all other registers */
}
However while testing the inline asm I ran across an issue. I adapted my handler like this:
void PendSV_Handler()
{
asm volatile(
"movw r0 100" // This should store the integer 100 in register r0
);
register int temp asm("r0"); // This should store the value in
// register r0 into temp
toggleLED(); // Toggles an LED to visualise the behavior
delay_ms(temp); // Delays the execution by [temp] ms, known to work
toggleLED();
}
Now the problem is that the LED to be toggled only switches on once and then stays stuck. Also in the SysTick_Handler
another LED is toggled with SysTick-frequency, which also stops toggling after the first PendSV
call. I know that they have the same priority, which is why I conclude, that the Tick-LED is stuck, because the delay is way too long and this lets me conclude, that the value from the register is not stored correctly. Did I miss out on how to store data from CPU registers or is there another flaw in my conclusions?
Best Answer
I am not sure if you are aware the logic already stores the state of the machine during an event/interrupt. If you want to use this to task switch you need to remove/re-build the stack to account for the switch. You may want to pull that information and save it for the switch back sure.
Take a look at Atomthreads or FreeRTOS or others to see how to do a complete task switch in a Cortex-M (it is not like other processors where you take control of the registers and change the return address. For starters, the "return address" in LR from an event/interrupt is not a valid address -- "Cortex-M3 Devices Generic User Guide: Exception entry and return").