Print registers, stack & other details on unhandled exception #1026

Open
alastairpatrick wants to merge 3 commits from alastairpatrick/fatal-exception into develop
alastairpatrick commented 2022-09-14 18:42:52 -05:00 (Migrated from github.com)

This partially fixes issue #228.

If (and only if) pico_debug is linked with a target, when an unhandled exception occurs, before executing BKPT #0, dump some useful state to stdout. This information includes the processor core number, the exception type, most ARM registers and the top few words of the stack, as they were before entry to the exception.

Probably the most useful information is in the PC register, which indicates which function was executing when the exception happened. The hex value can be looked up in the generated .elf.map files. Although most people are probably using GDB for that kind of thing, GDB isn't always possible.

It is RTOS friendly in that it checks whether a process stack is being used or not and doesn't make any assumptions about the location of the stack.

The exception handler still eventually does BKPT #0, so it works well with or without a debugger attached.

Example output:

-----------------------------------------------------------
Unhandled SVCall exception on core 0
-----------------------------------------------------------
  R0: 00000001   R1: 00000000   R2: 00000000   R3: d0000144
  R4: 1000026c   R5: 20041f01   R6: 18000000   R7: 00000000
  R8: ffffffff   R9: ffffffff  R10: ffffffff  R11: ffffffff
 R12: 00000000   SP: 20041ff8   LR: 100003af   PC: 100003b4
                MSP: 20041ff8  PSP: fffffffc XPSR: 21000000
         EXC_RETURN: fffffff9             PRIMASK: 00000000
-----------------------------------------------------------
20041ff8: 1000026c 1000022b
20042008:
20042018:
20042028:
20042038:
20042048:
20042058:
20042068:

In the stack memory dump above, white space is output for locations that do not fall in static RAM.

This partially fixes issue #228. If (and only if) pico_debug is linked with a target, when an unhandled exception occurs, before executing BKPT #0, dump some useful state to stdout. This information includes the processor core number, the exception type, most ARM registers and the top few words of the stack, as they were before entry to the exception. Probably the most useful information is in the PC register, which indicates which function was executing when the exception happened. The hex value can be looked up in the generated .elf.map files. Although most people are probably using GDB for that kind of thing, GDB isn't always possible. It is RTOS friendly in that it checks whether a process stack is being used or not and doesn't make any assumptions about the location of the stack. The exception handler still eventually does BKPT #0, so it works well with or without a debugger attached. Example output: ``` ----------------------------------------------------------- Unhandled SVCall exception on core 0 ----------------------------------------------------------- R0: 00000001 R1: 00000000 R2: 00000000 R3: d0000144 R4: 1000026c R5: 20041f01 R6: 18000000 R7: 00000000 R8: ffffffff R9: ffffffff R10: ffffffff R11: ffffffff R12: 00000000 SP: 20041ff8 LR: 100003af PC: 100003b4 MSP: 20041ff8 PSP: fffffffc XPSR: 21000000 EXC_RETURN: fffffff9 PRIMASK: 00000000 ----------------------------------------------------------- 20041ff8: 1000026c 1000022b 20042008: 20042018: 20042028: 20042038: 20042048: 20042058: 20042068: ``` In the stack memory dump above, white space is output for locations that do not fall in static RAM.
alastairpatrick commented 2022-09-15 12:06:19 -05:00 (Migrated from github.com)

Some more thoughts. I initially thought that, since the default exception handler symbols such as isr_hardfault are weak, I could simply provide alternate definitions of those symbols. It seemed no modifications to crt0.s would be needed and this module needn't even be part of the SDK; it could be a separate library.

Unfortunately that didn't work. If an alternate definition of isr_hardfault is provided, it will indeed be called when a hard fault exception occurs. However, for the purposes of the logic in exception_is_compile_time_default() and similar, it will not be the default exception handler, which is important. The reason it won't be the default exception handler is because that must fall in the range __default_isrs_start to __default_isrs_end. As things stand, it isn't possible to provide an alternate isr_hardfault that falls in that range, despite the symbol being weak.

Perhaps a better thing to do would be to rework things in crt0.s, exception.c & irq.c to add these new SDK functions:

void exception_set_default_handler(exception_handler_t);
void irq_set_default_handler(irq_handler_t);

This would need to be done without impacting the ability to replace weak handler symbols in crt0.s, since there is likely existing software that does that.

Then the debug exception handler could be built on top of that and it needn't be part of the SDK. It could go in pico-extras or a third party library. Actually, it would be awesome if it was in the boot ROM so that it worked regardless of whether flash RAM was accessible.

Some more thoughts. I initially thought that, since the default exception handler symbols such as `isr_hardfault` are weak, I could simply provide alternate definitions of those symbols. It seemed no modifications to crt0.s would be needed and this module needn't even be part of the SDK; it could be a separate library. Unfortunately that didn't work. If an alternate definition of `isr_hardfault` is provided, it will indeed be called when a hard fault exception occurs. However, for the purposes of the logic in `exception_is_compile_time_default()` and similar, it will not be the _default_ exception handler, which is important. The reason it won't be the default exception handler is because that must fall in the range `__default_isrs_start` to `__default_isrs_end`. As things stand, it isn't possible to provide an alternate `isr_hardfault` that falls in that range, despite the symbol being weak. Perhaps a better thing to do would be to rework things in crt0.s, exception.c & irq.c to add these new SDK functions: ```c void exception_set_default_handler(exception_handler_t); void irq_set_default_handler(irq_handler_t); ``` This would need to be done without impacting the ability to replace weak handler symbols in crt0.s, since there is likely existing software that does that. Then the debug exception handler could be built on top of that and it needn't be part of the SDK. It could go in pico-extras or a third party library. Actually, it would be awesome if it was in the boot ROM so that it worked regardless of whether flash RAM was accessible.
This pull request has changes conflicting with the target branch.
  • src/rp2_common/CMakeLists.txt
  • src/rp2_common/pico_standard_link/crt0.S
View command line instructions

Manual merge helper

Use this merge commit message when completing the merge manually.

Checkout

From your project repository, check out a new branch and test the changes.
git fetch -u origin 'alastairpatrick/fatal-exception:alastairpatrick/fatal-exception'
git switch 'alastairpatrick/fatal-exception'

Merge

Merge the changes and update on Forgejo.

Warning: The "Autodetect manual merge" setting is not enabled for this repository, you will have to mark this pull request as manually merged afterwards.

git switch 'develop'
git merge --no-ff 'alastairpatrick/fatal-exception'
git switch 'alastairpatrick/fatal-exception'
git rebase 'develop'
git switch 'develop'
git merge --ff-only 'alastairpatrick/fatal-exception'
git switch 'alastairpatrick/fatal-exception'
git rebase 'develop'
git switch 'develop'
git merge --no-ff 'alastairpatrick/fatal-exception'
git switch 'develop'
git merge --squash 'alastairpatrick/fatal-exception'
git switch 'develop'
git merge --ff-only 'alastairpatrick/fatal-exception'
git switch 'develop'
git merge 'alastairpatrick/fatal-exception'
git push origin 'develop'
Sign in to join this conversation.
No reviewers
No milestone
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
gh-raspberrypi/pico-sdk!1026
No description provided.