FreeRTOS Support Archive
The FreeRTOS support forum is used to obtain active support directly from Real
Time Engineers Ltd. In return for using our top quality software and services for
free, we request you play fair and do your bit to help others too! Sign up
to receive notifications of new support topics then help where you can.
This is a read only archive of threads posted to the FreeRTOS support forum.
The archive is updated every week, so will not always contain the very latest posts.
Use these archive pages to search previous posts. Use the Live FreeRTOS Forum
link to reply to a post, or start a new support thread.
[FreeRTOS Home] [Live FreeRTOS Forum] [FAQ] [Archive Top] [May 2007 Threads] GDB debugging and FreeRTOSPosted 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 FreeRTOSPosted 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 FreeRTOSPosted 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 FreeRTOSPosted 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 FreeRTOSPosted 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 FreeRTOSPosted 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 FreeRTOSPosted 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 FreeRTOSPosted 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.
Copyright (C) Amazon Web Services, Inc. or its affiliates. All rights reserved.
|