mikaeljanssonbe wrote on Thursday, April 09, 2015:
Hi again,
Nothing special about RAM bank 1. We’ve historically used bank 0 for other data.
I changed these parameters:
- include/not include __malloc_lock()/__malloc_unlock()
- SRAM bank 0 instead of bank 1
- Set configUSE_NEWLIB_REENTRANT to 0 and 1.
There was no difference. I do have a GDB session that clearly shows the problem I’m seeing:
Start at rtos_main(), the first thing called after setting up the data segment, clearing BSS etc.:
..., rtos_main () at rtos.c:724
(gdb) mon regs
R0 = 00000000, R1 = 00000003, R2 = 05FA0200, R3 = 00000000
R4 = 3456ABCD, R5 = 3456ABCD, R6 = 12345678, R7 = 10007FC8
R8 = A5A5A5A5, R9 = A5A5A5A5, R10= A5A5A5A5, R11= A5A5A5A5
R12= A5A5A5A5, R13= 10007FC0, MSP= 10007FC0, PSP= 2007C1A0
R14(LR) = 00001737, R15(PC) = 00001136
XPSR 01000000, APSR 00000000, EPSR 01000000, IPSR 00000000
Note the value of PSP at this point.
Break again at task_uart - started as a task by xTaskCreate() and vStartScheduler(). But PSP here is (almost) the same as before FreeRTOS started, and definitely not within pxStack-pxTopOfStackRange:
Breakpoint 1, task_uart (blob=0x0 <tosBasicVectors>) at application.c:97
97 ;
(gdb) mon regs
R0 = 00000000, R1 = 00000114, R2 = 00000000, R3 = 2007C1C4
R4 = A5A5A5A5, R5 = A5A5A5A5, R6 = A5A5A5A5, R7 = 2007C1C0
R8 = A5A5A5A5, R9 = A5A5A5A5, R10= A5A5A5A5, R11= A5A5A5A5
R12= A5A5A5A5, R13= 2007C1C0, MSP= 10007FC0, PSP= 2007C1C0
R14(LR) = 00000E9B, R15(PC) = 0000030A
XPSR 01000000, APSR 00000000, EPSR 01000000, IPSR 00000000
CFBP 02000000, CONTROL 2000000, FAULTMASK 00, BASEPRI 00, PRIMASK 00
(gdb) p pxCurrentTCB.pxTopOfStack
$1 = (volatile StackType_t *) 0x2007c5a8
(gdb) p pxCurrentTCB.pxStack
$2 = (StackType_t *) 0x2007c4f0
Stop at the next interrupt called and check regs (PSP in particular) vs. pxTopOfStack:
(gdb) b xPortSysTickHandler
Breakpoint 2 at 0x1b48: file port.c, line 474.
(gdb) disable 1
(gdb) c
Continuing.
Breakpoint 2, xPortSysTickHandler () at port.c:474
474 {
(gdb) mon regs
R0 = 00000000, R1 = 00000114, R2 = 00000000, R3 = 2007C1C4
R4 = A5A5A5A5, R5 = A5A5A5A5, R6 = A5A5A5A5, R7 = 2007C1C0
R8 = A5A5A5A5, R9 = A5A5A5A5, R10= A5A5A5A5, R11= A5A5A5A5
R12= A5A5A5A5, R13= 10007FC0, MSP= 10007FC0, PSP= 2007C1A0
R14(LR) = FFFFFFFD, R15(PC) = 00001B48
XPSR 0100000F, APSR 00000000, EPSR 01000000, IPSR 0000000F
CFBP 00000000, CONTROL 00, FAULTMASK 00, BASEPRI 00, PRIMASK 00
(gdb) p pxCurrentTCB.pxTopOfStack
$1 = (volatile StackType_t *) 0x2007c5a8
Everything in order. Continue to xPortPendSVHandler invoked by systick IRQ and verify pxTopOfStack is correct:
(gdb) b vTaskSwitchContext
Breakpoint 3 at 0x2452: file tasks.c, line 2116.
(gdb) b xPortPendSVHandler
Breakpoint 4 at ...
(gdb) c
Continuing.
Breakpoint 4, xPortPendSVHandler () at port.c:440
440 __asm volatile
(gdb) p pxCurrentTCB.pxTopOfStack
$5 = (volatile StackType_t *) 0x2007c5a8
Step through the handler:
(gdb) layout asm
(gdb) # si a few times
B+ |0x1b04 <xPortPendSVHandler> mrs r0, PSP
|0x1b08 <xPortPendSVHandler+4> isb sy
|0x1b0c <xPortPendSVHandler+8> ldr r3, [pc, #52]
|0x1b0e <xPortPendSVHandler+10> ldr r2, [r3, #0]
|0x1b10 <xPortPendSVHandler+12> stmdb r0!, {r4, r5, r6, r7, r8, r9, r10, r11}
>|0x1b14 <xPortPendSVHandler+16> str r0, [r2, #0]
Here, r0 contains PSP and we’re just about to write r0 to [r2], which is pxCurrentTCB:
(gdb) mon regs
R0 = 2007C180, R1 = 10000C3C, R2 = 2007C498, R3 = 10000C38
R4 = A5A5A5A5, R5 = A5A5A5A5, R6 = A5A5A5A5, R7 = 2007C1C0
R8 = A5A5A5A5, R9 = A5A5A5A5, R10= A5A5A5A5, R11= A5A5A5A5
R12= A5A5A5A5, R13= 10007FC0, MSP= 10007FC0, PSP= 2007C1A0
R14(LR) = FFFFFFFD, R15(PC) = 00001B14
XPSR 2100000E, APSR 20000000, EPSR 01000000, IPSR 0000000E
(gdb) p pxCurrentTCB.pxTopOfStack
$6 = (volatile StackType_t *) 0x2007c5a8
Do the store:
(gdb) si
(gdb) p pxCurrentTCB.pxTopOfStack
$7 = (volatile StackType_t *) 0x2007c180
(gdb)
Presto! pxTopOfStack overwritten by PSP. Which probably is what the code is supposed to do, but since PSP is never updated to match pxTopOfStack, it’s the same as it was before FreeRTOS started.