Electronic – Load and store CPU registers in application context

cortex-m3cpustm32

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").

Related Topic