5 years, 6 months ago.

Save program state in flash including Registers , Stack and Variables

Hi,

I am using STM32 Nucleo board L152RE. I am new to all this stuff Mbed OS, Nucleo Board etc. I am writing program on Eclipse ARM GCC. I want to store all general purpose registers and stack state on flash. I know the idea that push all General Purpose Registers (GPRs) on to stack and then save whole stack on Flash.

The code to write on the flash is some what looks like

HAL_FLASH_Unlock(); status=HAL_FLASHEx_HalfPageProgram(0x0807FF00,data); HAL_FLASH_Lock();

But i am unable to understand how to interact with GPRs and Stack in mbed ? How to calculate stack frame to store into flash . Any help will be appreciated. Any pointer?

Best Regards

1 Answer

5 years, 6 months ago.

Hi Mustansar,

It's not clear why you must save the internal registers, but we'll demonstrate how they can be accessed. You can use the CMSIS-Core library to access some of the internal registers as shown here:

However, with the exception of the SP (at R13... already accessible as MSP/PSP via CMSIS-CORE) the internal register file is not accessible via CMSIS and you will have to drop down to assembly language to access these registers.

Below is an example showing how to do this and make use of CMSIS-Core to read the two stack pointers. This code builds with gcc.

Please note that this example doesn't store R0 (as it would be a self-destructing store) nor does it store R15/PC (as the instruction set doesn't support this). You could still push R0 to the stack however so we have added an example of that. The PC can't be pushed to the stack, but you could first use MOV to take it to another register and then do a STR or PUSH. Naturally you'll then be saving a stale copy of the PC.

For help with the v7-M Instruction Set, please see the Arm Reference Manual:

Regards,

Ralph, Team Mbed

#include "mbed.h"

#define NUM_REG 16

void SaveRegisterFile (unsigned int *buf)
{
  
    // store out what we can... missing r0/pc 
    asm("str r1, [r0], #4");
    asm("str r2, [r0], #4");
    asm("str r3, [r0], #4");
    asm("str r4, [r0], #4");
    asm("str r5, [r0], #4");
    asm("str r6, [r0], #4");
    asm("str r7, [r0], #4");
    asm("str r8, [r0], #4");
    asm("str r9, [r0], #4");
    asm("str r10, [r0], #4");
    asm("str r11, [r0], #4");
    asm("str r12, [r0], #4");
    asm("str sp, [r0], #4");
    asm("str lr, [r0], #4");
    
    // demonstrate how to push and pop
    asm ("push {r0}");
    asm ("pop {r0}");
    
}

int main()
{

    unsigned int gp_registers[NUM_REG];
    printf("\r\n*****Example reading registers....\n");
    
    SaveRegisterFile(gp_registers);    
    printf("Registers we saved are:\r\n");
    for (int i=0; i<NUM_REG; i++) {
        printf ("0x%08x\r\n", gp_registers[i]);
    }

    printf ("MSP is 0x%08x\r\n", (unsigned int) __get_MSP()); 
    printf ("PSP is 0x%08x\r\n", (unsigned int) __get_PSP()); 
}

Thanks for the reply.

While running your code, I am experiencing the following compile time error:

Error: Variable "R1" is used before its value is set in "main.cpp", Line: 86, Col: 11

Line:86 is following:

asm("str r1, [r0], #4");

Can you please help me out what is this error?

posted by Mustansar Saeed 28 Oct 2018