This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts

nRF51822 - Exception on Stack Overflow

Using:

  • nRF51822
  • GCC 4.8.4
  • Nordic Sdk 5.2.0
  • pure-gcc setup (Ole Morten)
  • newlib-nano and -flto

See also this question.

I'd defined some stack size within startup_nrf51.s and want to be informed if the stackpointer passes __StackLimit.

Might there be a way to generate something like a hardfault or something else? The stack overflow condition should be detected regardless if the device is in debugging environment or not.

Edit 2014-08-28

BTW: For the heap / malloc issue, I see a different approach using a custom _sbrk() implementation. I'll post it as soon as I got a solution.

Trying out the RLENR0 based approach as suggested by RK.

My ram memory layout is currently like this:

__data_start__ = 20002000
__data_end__   = 20002088
__bss_start__  = 20002090
__bss_end__    = 20002DC4
__HeapBase     = 20002DC8
__HeapLimit    = 200031C8
__StackLimit   = 20003400
__StackTop     = 20004000
__stack        = 20004000

Dump of current RLENR0 and CLENR0 values:

NRF_MPU->RLENR0  = 00002000
NRF_UICR->CLENR0 = 00014000
NRF_FICR->CLENR0 = FFFFFFFF

I'm using the Sdk 5.2 bootloader which performs a check to NRF_UICR->CLENR0

// This check ensures that the defined fields in the bootloader corresponds with actual setting in the nRF51 chip.
APP_ERROR_CHECK_BOOL(NRF_UICR->CLENR0 == CODE_REGION_1_START);

so I'm a bit afraid from changing CLENR0 register.

Now I stuck for finding the correct RLENR0 value and write that into NRF_MPU->RLENR0. I'd try it from within code (tried both startup asm and very start of main). By trying out some random values:

  • Info: At the time when changing NRF_MPU->RLENR0 within main, my stackpointer is at 0x20003EF0 (determined by calling __get_MSP()).
  • For values like 0x20003400, my application stops immediately. Don't know if my hardfault handler was called - if so, then he was unable to write something via uart.
  • For values above 0x2140, I earn a immediate hardfault however.
  • All values from 0x0000 up to 0x2140, my application runs like before.

For the last case, I see my changed value in NRF_MPU->RLENR0, but when calling softdevice_handler_init() the value will be restored to 0x2000. When I now try to change NRF_MPU->RLENR0 again, a hardfault is raised - regardless which value I try to set.

Could you help me to find the right value for NRF_MPU->RLENR0 and how to write it into?

Parents
  • I don't know how to do it with generating hardfault, but I just periodically check whether the stack overflowed or not and generate error if it is.

    For this I fill stack with 0xDEADBEEF in startup file and periodically check maximum stack usage.

    In reset handler:

    Reset_Handler:
        .fnstart
    
    /* Make sure ALL RAM banks are powered on */
        LDR     R0, =NRF_POWER_RAMON_ADDRESS
        LDR     R2, [R0]
        MOVS    R1, #NRF_POWER_RAMON_RAMxON_ONMODE_Msk
        ORRS    R2, R1
        STR     R2, [R0]
    
                     LDR     R0, =__StackTop
                     LDR     R1, =Stack_Size
                     LDR     R2, =0xDEADBEEF
    .Fill:
                     SUBS    R0,#4
                     STR     R2, [R0]
                     SUBS    R1,#4
                     BNE     .Fill
    

    Get maximum stack usage:

    extern uint32_t __StackTop;
    extern uint32_t __StackLimit;
    uint32_t stack_overflow_debug(void)
    {
        uint32_t stack_usage = 0;
        uint32_t offset = 0;
        uint32_t * value_addr = (uint32_t *) &__StackLimit;
    
        for (; offset <  ((uint32_t)&__StackTop - (uint32_t)&__StackLimit); offset=offset+4)
        {
            uint32_t new_val = *(value_addr + offset);
            if (new_val != 0xDEADBEEF )
            {
                break;
            }
        }
        stack_usage = ((uint32_t)&__StackTop - (uint32_t)&__StackLimit) - offset;
    
        return stack_usage;
    }
    
Reply
  • I don't know how to do it with generating hardfault, but I just periodically check whether the stack overflowed or not and generate error if it is.

    For this I fill stack with 0xDEADBEEF in startup file and periodically check maximum stack usage.

    In reset handler:

    Reset_Handler:
        .fnstart
    
    /* Make sure ALL RAM banks are powered on */
        LDR     R0, =NRF_POWER_RAMON_ADDRESS
        LDR     R2, [R0]
        MOVS    R1, #NRF_POWER_RAMON_RAMxON_ONMODE_Msk
        ORRS    R2, R1
        STR     R2, [R0]
    
                     LDR     R0, =__StackTop
                     LDR     R1, =Stack_Size
                     LDR     R2, =0xDEADBEEF
    .Fill:
                     SUBS    R0,#4
                     STR     R2, [R0]
                     SUBS    R1,#4
                     BNE     .Fill
    

    Get maximum stack usage:

    extern uint32_t __StackTop;
    extern uint32_t __StackLimit;
    uint32_t stack_overflow_debug(void)
    {
        uint32_t stack_usage = 0;
        uint32_t offset = 0;
        uint32_t * value_addr = (uint32_t *) &__StackLimit;
    
        for (; offset <  ((uint32_t)&__StackTop - (uint32_t)&__StackLimit); offset=offset+4)
        {
            uint32_t new_val = *(value_addr + offset);
            if (new_val != 0xDEADBEEF )
            {
                break;
            }
        }
        stack_usage = ((uint32_t)&__StackTop - (uint32_t)&__StackLimit) - offset;
    
        return stack_usage;
    }
    
Children
Related