topic_solved How to use "software reset code" and "stack" (M122)
I happened to come across an unexpected reset already quite a while ago.
M122gave the following output
Last software reset at 2019-06-05 09:21, reason: Stuck in spin loop, spinning module GCodes, available RAM 8000 bytes (slot 1) Software reset code 0x4043 HFSR 0x00000000 CFSR 0x00000000 ICSR 0x0041f80f BFAR 0xe000ed38 SP 0x2000322c Task 0x454c4449 Stack: 00449ed1 0044a232 61000000 a5a5a5a5 00449ed1 a5a5a5a5 2000324c 200030f4 200048cc 0001ef60 2000177c 200062f4 2000324c 200062ec 00000004 20001790 200030cc 2000324c 200030c4 00000001 200032a4 4e49414d 00000000
Since I am hacking in the firmware anyway I wanted to ask how to use the give information to debug what was happening or actually where it was stuck?
I use the map file from the linker and the assembler output files from the compiler to see where the crash occurred.
@dc42 I found the assembler files but where can I find the linker map? I have to admit though being a professional software developer debugging ARM/embedded code is something I never done before.
So if you have the time to elaborate a bit more on the process that would really help me getting started.
EDIT: just found the linker map file. See what I can figure with that one.
EDIT2: OK, contents of the map file don't help me without further knowledge about the basic process.
The stack from the software reset data tells you what code was being executed at the time. Normally the second entry is the address where the exception occurred. The first entry is the Link Register, which is usually the return address of the current function call. The exception address should be an even number. All the function return addresses should be odd numbers.
The map file includes a section listing the function symbols. You can use this to see what function the exception address and each return address is in, and the offset from the start of that function. Then you can go to the assembly listing of that function, and from the offset you can identify the precise instruction.
@dc42 I think this definitely gets me a step further. Let's see if I got it right:
Note that I don't have the actual build files from that build anymore (I now know to backup them) this might not give me a real position anymore but I think to use something close is good enough to see if I understood it.
In the above example with
Stack: 00449ed1 0044a232 61000000 a5a5a5a5 00449ed1 a5a5a5a5 2000324c 200030f4 200048cc 0001ef60 2000177c 200062f4 2000324c 200062ec 00000004 20001790 200030cc 2000324c 200030c4 00000001 200032a4 4e49414d 00000000
Then I would take
0044a232and look for an address
<= 0044a232in the map file. In my case the following two lines are "surrounding" that value
.text.prvIdleTask 0x000000000044a1f8 0x60 /home/manuel/github/FreeRTOS/SAM4E/libFreeRTOS.a(tasks.o) .text.prvResetNextTaskUnblockTime.part.0 0x000000000044a258 0x18 /home/manuel/github/FreeRTOS/SAM4E/libFreeRTOS.a(tasks.o)
and I could derive from that that the error happened at libFreeRTOS in function
prvIdleTask. The offset inside the corresponding
tasks.sfile then would be
In this example the error seems to have finally been thrown in FreeRTOS so this would not give me too much information. I would then go up the stack until I reach something with meaning for me, right? Just as in usual debugging: go back out of any libraries until you reach your own code.
Or is there a limit on how far going back makes sense? Or how do I identify relevant parts?
The offset of 3A is from the start of prvIdleTask in tasks.s (conveniently, the listing for each function starts at 0), but otherwise that's all correct. However, the only other return address on the stack trace that you listed is 00449ed1 (once in the LR and once on the stack), so you won't be able to go back very far.