Quality RTOS & Embedded Software

 Real time embedded FreeRTOS RSS feed 
Quick Start Supported MCUs PDF Books Trace Tools Ecosystem


Loading

GDB debugging and FreeRTOS

Posted by Christopher Piggott on May 30, 2007
What sorts of things would make it so that FreeRTOS runs stand-alone just fine but it gets aborts when you run it with the debugger? For example, I wrote a small app with one task (plus of course the idle task) that blinks a few LEDs. If I run it without the debugger (i.e. just turn it on or push the reset button) it works fine, but if I run it through gdb it does nothing. When I eventually abort it I get:

Program received signal SIGINT, Interrupt.
data_abort () at src/startup.S:83
83 b data_abort
1: /x $pc = 0x8b0

(gdb) print/x $lr
$1 = 0xc0c

It's fairly consistent about stopping in that same spot, which is in the middle of vPreemptiveTick() as it calls the macro portRESTORE_CONTEXT():


/* The critical nesting depth is the first item on the stack. */
/* Load it into the ulCriticalNesting variable. */
"LDR R0, =ulCriticalNesting
--> "LDMFD LR!, {R1} BLOWS UP HERE
"STR R1, [R0]


(this is based on the LPC2106 GCC port, though mine is an LPC2129).




RE: GDB debugging and FreeRTOS

Posted by Richard on May 31, 2007
Hmm. Don't know. Are you using exactly the same build for the debug and non debug versions? I presume you set the linker script to be correct when converting the LPC2106 demo to run on the LPC2129?

Regards.

RE: GDB debugging and FreeRTOS

Posted by Christopher Piggott on May 31, 2007
>I presume you set the linker script to be correct when converting the LPC2106 demo to run on the LPC2129?

Yep.

>Are you using exactly the same build for the debug and non debug versions?
Yes.

Maybe what I will do is examine vPreemptiveTick on some other ports and see if that helps me figure out what is happening with this one.

RE: GDB debugging and FreeRTOS

Posted by Christopher Piggott on June 1, 2007

My GDB still bombs out in vPreemptiveTick. I am trying to trace through it ...when I enter vPreemptiveTick the CPU is in IRQ mode (which makes sense, as it was called from the timer).

portSAVE_CONTEXT() is executed.

vTaskIncrementTick() is executed.

vTaskSwitchContext() is executed, after which pxCurrentTCB is set to the IDLE task:

(gdb) print *pxCurrentTCB
$4 = {pxTopOfStack = 0x400005d8, xGenericListItem = {xItemValue = 0, pxNext = 0x40002244, pxPrevious = 0x40000214,
pvOwner = 0x400003ec, pvContainer = 0x4000223c}, xEventListItem = {xItemValue = 5, pxNext = 0x0, pxPrevious = 0x0,
pvOwner = 0x400003ec, pvContainer = 0x0}, uxPriority = 0, pxStack = 0x40000438, uxTCBNumber = 1,
pcTaskName = "IDLE", '\0' <repeats 11 times>, usStackDepth = 128}


Next it begins portRESTORE_CONTEXT().


LDR R0, =pxCurrentTCB
LDR R0, [R0]
LDR LR, [R0]

LR now contains 0x40003bf8


LDR R0, =ulCriticalNesting
LDMFD LR!, {R1}
STR R1, [R0]

After this, r1 contains 0x00000000, which seems right, and LR is 0x40003fbc, which means the stack pointer is going up, consistent with things being popped. Good so far.


/* Get the SPSR from the stack. */
LDMFD LR!, {R0}

LR is now 0x40003fc0 and r0 is now 0x60000013. This would correspond to mode b10111 which is ABORT. Why is that?

MSR SPSR, R0

It does what it was supposed to do; $spsr_irq is now 0x60000013.


LDMFD LR, {R0-R14}^
NOP


After the registers are restored, things generally look to me like they make sense.


/* Restore the return address. */
LDR LR, [LR, #+60]

lr now contains 0x944 ... oops that's bad. That's in _start, i.e. the startup routine (pre-main).

SUBS PC, LR, #4

Indeed, it jumps to clear_bss (in the middle of _start) and $cpsr is 0x60000013 i.e. it is in abort mode.


What's happening here?




RE: GDB debugging and FreeRTOS

Posted by embeddedc on June 1, 2007
You said previously that it was ok when not running the debugger. In the past I have experienced two problems when stepping through this part of the code, neither time with GDB though so I don't know if it is relevant. The first was where stepping the debugger temporarily allowed interrupts to execute even when interrupts were globally disabled. This can corrupt your data structures. The second was where the timer that generated the interrupt was not halted when the debugger hit a break point, but kept running.

If neither of these are the problem then I would suggest a simple test. Write a task that sets all the registers to a known value, then calls yield, then checks to ensure the registers still contain the same values. Create two of these tasks, with each task setting the registers to a different known value. Then run the scheduler is cooperative mode. This way you know which value should be in each register of both of the two tasks and can step through the saving and restoring of each when yield is called, to see where the problem occurs.

There are some examples of this technique in the FreeRTOS download, but I cannot find one for the ARM7. Take a look at the function prvSetAndCheckRegisters() in Demo\CORTEX_LM3S102_GCC\Demo1\main.c, or vRegisterTest() in the PIC24 or microblaze main() files.

RE: GDB debugging and FreeRTOS

Posted by Christopher Piggott on June 1, 2007
>The first was where stepping the debugger temporarily allowed interrupts to execute even when interrupts were globally disabled. This can corrupt your data structures. The second was where the timer that generated the interrupt was not halted when the debugger hit a break point, but kept running.

I read a note about this in the source for the 2106 port and was worried about it. Check my logic here, but the reason I don't think that is happening here is that the problem occurs without single stepping.

(gdb) break maintask
Breakpoint 1 at 0x728: file src/led.c, line 47.
(gdb) go

where "go" is a macro defined as:

set $pc = 0
continue


The program starts running but never hits the breakpoint, i.e. my main (first) task never gets called. Eventually, I get bored and hit ^C to see what it is doing:

Program received signal SIGINT, Interrupt.
data_abort () at src/startup.S:83
83 b data_abort
1: /x $pc = 0x964
(gdb) print/x $lr
$1 = 0xcc0



This makes me wonder ... maybe this gets all screwed up because just setting the pc to the reset vector then "continuing." The gdb "run" command doesn't seem to work:

(gdb) run
The program being debugged has been started already.
Start it from the beginning? (y or n) y
Starting program: /home/chrisp/work/arm/led/led.elf
Don't know how to run.

but, just executing from 0x00000000 is not quite the same as a reset, even considering that I put all of the registers I think I care about in a state I want regardless of their reset default.


Does that make sense?


I will try your suggestions now and see what happens.


RE: GDB debugging and FreeRTOS

Posted by Christopher Piggott on June 1, 2007
You know what part of it is ... setting the $pc to 0 isn't enough, because depending on where you were when you last stopped you might not even be in supervisor mode.

I tried this:

define go
set $cpsr = 0x13
set $pc = 0
continue
end



and it behaves DIFFERENTLY. Not correctly, but differently. (At least so far). I will pursue this a little, because there may be more that I have to do.


RE: GDB debugging and FreeRTOS

Posted by sotd on June 1, 2007
I don't think setting the program counter to 0 without first a reset is guaranteed to work. The VIS will still be configured, as will all the peripherals. This means interrupts firing during the C startup code execution are likely to cause data aborts.


[ Back to the top ]    [ About FreeRTOS ]    [ Privacy ]    [ Sitemap ]    [ ]


Copyright (C) Amazon Web Services, Inc. or its affiliates. All rights reserved.

Latest News

NXP tweet showing LPC5500 (ARMv8-M Cortex-M33) running FreeRTOS.

Meet Richard Barry and learn about running FreeRTOS on RISC-V at FOSDEM 2019

Version 10.1.1 of the FreeRTOS kernel is available for immediate download. MIT licensed.

View a recording of the "OTA Update Security and Reliability" webinar, presented by TI and AWS.


Careers

FreeRTOS and other embedded software careers at AWS.



FreeRTOS Partners

ARM Connected RTOS partner for all ARM microcontroller cores

Espressif ESP32

IAR Partner

Microchip Premier RTOS Partner

RTOS partner of NXP for all NXP ARM microcontrollers

Renesas

STMicro RTOS partner supporting ARM7, ARM Cortex-M3, ARM Cortex-M4 and ARM Cortex-M0

Texas Instruments MCU Developer Network RTOS partner for ARM and MSP430 microcontrollers

OpenRTOS and SafeRTOS

Xilinx Microblaze and Zynq partner