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.
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:
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?
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:
/* 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
STR R2, [R0]
Get maximum stack usage:
extern uint32_t __StackTop;
extern uint32_t __StackLimit;
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 )
stack_usage = ((uint32_t)&__StackTop - (uint32_t)&__StackLimit) - offset;
That's the way I currently also do it (and I also filling the heap with a different pattern).
Actually, I'm far away from having stack usage problems. But If one occours, I think by producing a hardfault, there might be a way to identify a bit of callstack.