-
-
Notifications
You must be signed in to change notification settings - Fork 784
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Feature: Non-hanging semihosting #1507
base: main
Are you sure you want to change the base?
Conversation
* Provide a naked hard_fault_handler in GCC inline assembly * Provide a C handler to detect failed semihosting breakpoints * Spoof the one RDI_SYS_OPEN call in case the Angel is missing
It seems like a cleaner approach is to ensure that no IRQs are enabled at priority 0. A hard fault implies a serious programming error, and making a nontrivial handler for it seems unwise. I don't currently experience hard faults or lockups with debug output enabled on my native BMP (hardware 2.3), even without my |
I saw it on Note that a) I could not buy a real
There are a few clever applications for HardFault handler, which are definitely not a serious programming error. Some notable ones include trapping access to unmapped external memory as if it's mapped (see https://github.com/yocto-8/yocto-8/blob/main/doc/extmem.md but they use MemManage) and emulating instructions missing from ISA (UsageFault) (see series of blogposts, shorter one describing mechanism https://dmitry.gr/?r=05.Projects&proj=27.%20m0FaultDispatch , longer one describing application https://dmitry.gr/?r=05.Projects&proj=27.%20rePalm )
As far as BMF is concerned, there are no current problems with interrupt/exception priority selection or inversion. Timer-based Manchester capture driver for SWO (in streaming mode to USB bulk pipe endpoint) has to be the highest urgency for reasons better discussed separately. This PR is not fully obsolete, either: note that in-tree F072-IF platform is a Cortex-M0, and cannot vector to DebugMon which is absent from ARMv6-M. (future possible rp2040 ports out-of-tree cannot either). Trapping breakpoint insns, checking for C_DEBUG_EN and handing them over to a "fake" I have other plans for |
Detailed description
BMP firmware already implements a debugging mode: when building via
make PROBE_HOST=native ENABLE_DEBUG=1
,the corresponding newlib/libgloss rdimon (rdimon_nano) is linked, routing many syscalls to an ARM RDI Monitor (Angel SWI).
In presence of an upstream debugging adapter, the developer should issue a
monitor semihosting enable
in the relevant gdbserver implementation (OpenOCD, JLinkGDBServer, or even another Blackmagic) to start debugging the BMP firmware itself.However, on ARMv7-M cores, the
initialise_monitor_handles
function issues a 0xAB breakpoint inusb_serial_set_config()
. In absence of upstream debugger this escalates to a HardFault immediately.libopencm3
has a defaultblocking_handler
as a weak symbol forhard_fault_handler
. This leads to the probe firmware hanging until reset.The rest of possible operations actually use a 0xBEAB (T16 breakpoint), too. Only Cortex-A/R MPUs and older ARM9 cores can use a
swi
software interrupt, henceAngelSWI
. Whether SVCall (svc
) is available and codegen-able in supported libc implementations for ARMv6-M/v7-M is a valid discussion topic. Note that libopencm3 requires gcc-6.hard_fault_handler
which allows detecting semihosting breakpoints and skipping over them in case the firmware was built with debugging enabled, but no external debugger was attached..text
increase is ~200 bytes, and none of this code was required in release builds.Your checklist for this pull request
make PROBE_HOST=native
)make PROBE_HOST=hosted
)I tested builds with a GNU Tools for STM32 10.3-2021 from STM32CubeIDE 1.10 package, as well as Ubuntu/jammy gcc-10.3-2021 (insufficient newlib optimization). For
native
I had to drop like 5 targets from the Makefile to fit info ROM space.I wanted to not have dual debuggers on my desk just to tinker with adding target support while working off a
blackpill-f411ce
.This PR should be a draft before proper testing for debug-enabled platforms, the closest to native hardware I have is a bluepill/stm32f103cbt6. I'd like to move the semihosting and ARM interrupt handling stuff into a separate file, as it does not really belong to usb_serial.c apart from
_write
callingdebug_serial_debug_write()
. A far simpler solution would be to decouple serial traces from semihosting.Actual semihosting, when enabled, should not break. A probe platform MCU from reset used to either quickly reach a hardfault, or break into the already connected upstream debugger.
Code inspiration from McuOnEclipse, uOS++ IIIe, NuttX and maybe SEGGER wiki.