Unable to read link register using __ASM("lr");

Additional details:

  • IDE: Keil uVision 5.17.00
    • C Compiler: V5.06 update 1 (build 61)
    • Assembler: V5.06 update 1 (build 61)
  • Custom board (This shouldn't make a difference)
  • SoftDevice: s140_nrf52_6.1.0
  • SDK: 15.2

Hello.

I am attempting to read the link register LR the same way that the PSP and MSP are read in all Nordic example projects. See __get_PSP() and __get_MSP() for reference. I have implemented the following to mimic __get_MSP():

__STATIC_INLINE uint32_t __get_LR(void)
{
  register uint32_t __regLR  __ASM("lr");
  return(__regLR);
}

void MemoryManagement_Handler(void)
{
   static volatile uint32_t lr;
   lr = __get_LR();
   
   if(lr & 0x4)
   {
      // Do something useful
   }
   else
   {
      // Do something useful
   }
}

// Trigger a MemManage fault from main;

main(void)
{
   typedef void (*fn_t)();
   fn_t func = (fn_t)((char*) 0xFFFFFFFF);
   func();
}

However, the link register value returned does not match what is shown in the Keil uVision registers window as seen below.

Note that I have no trouble reading the PSP or MSP. But for some reason I cannot read the link register,. Replacing __ASM("lr") with __ASM("r14") resulted in the same behavior. Oddly enough, when I hover my mouse over __ASM("lr"), it shows the correct value as seen in the register window. Lastly, looking at the HardFault_Handler() implementation in the Nordic examples as found in hardfault_handler_keil.c, it looks like the link register LR is checked using "tst lr, #4".

Any idea as to why I cannot read the link register using ASM("lr")? The same code works on a STM MCU in Keil uVision, but Nordic does not work.

Thanks!

Derek

Parents
  • Hey  ,

    I don't think it's a Keil debugger window issue because of the following code:

    void MemoryManagement_Handler(void)
    {
        static volatile uint32_t lr;
        lr = __get_LR();
       
        unsigned * stkPtr;
        if (lr & 0x4)
        {
           stkPtr = (unsigned * )__get_PSP();
        }
        else
        {
           stkPtr = (unsigned * ) __get_MSP();
        }
        dumpStack(lr);
    }

    'stkPtr' always gets assigned the MSP even though LR has a value of 0xFFFFFFFD in the register window. The expression (0xFFFFFFFD & 0x4) should evaluate to true and __get_PSP() should be called, but this if() statement always evaluates to false because the local variable 'lr' has a value of 0x10. I have tried changing the local variable name from 'lr' to something else and it doesn't make a difference.

    0xD = 1101 , So (0xD & 0x4) should evaluate to true but it doesn't. 

    I will test this on a nRF52840 devkit using SES as this is the only other IDE / debugger I have and can get easily running, but I don't think the IDE is the issue because of the if() statement always evaluating to false.

    Thanks,

    Derek

Reply
  • Hey  ,

    I don't think it's a Keil debugger window issue because of the following code:

    void MemoryManagement_Handler(void)
    {
        static volatile uint32_t lr;
        lr = __get_LR();
       
        unsigned * stkPtr;
        if (lr & 0x4)
        {
           stkPtr = (unsigned * )__get_PSP();
        }
        else
        {
           stkPtr = (unsigned * ) __get_MSP();
        }
        dumpStack(lr);
    }

    'stkPtr' always gets assigned the MSP even though LR has a value of 0xFFFFFFFD in the register window. The expression (0xFFFFFFFD & 0x4) should evaluate to true and __get_PSP() should be called, but this if() statement always evaluates to false because the local variable 'lr' has a value of 0x10. I have tried changing the local variable name from 'lr' to something else and it doesn't make a difference.

    0xD = 1101 , So (0xD & 0x4) should evaluate to true but it doesn't. 

    I will test this on a nRF52840 devkit using SES as this is the only other IDE / debugger I have and can get easily running, but I don't think the IDE is the issue because of the if() statement always evaluating to false.

    Thanks,

    Derek

Children
No Data
Related