--- ** [tickets:#332] Cortex M DHCSR.C_MASKINTS may be handled incorrectly** **Status:** new **Milestone:** 0.11.0 **Created:** Mon Jan 10, 2022 11:40 AM UTC by Pavel Kirienko **Last Updated:** Mon Jan 10, 2022 11:40 AM UTC **Owner:** nobody **Attachments:** - [148230572-af6bf5c4-c5ec-4140-9d48-1fbf253d337e.png](https://sourceforge.net/p/openocd/tickets/332/attachment/148230572-af6bf5c4-c5ec-4140-9d48-1fbf253d337e.png) (77.0 kB; image/png) - [148230589-1ddf5878-fb70-4e4a-920d-fc3f866e08cf.png](https://sourceforge.net/p/openocd/tickets/332/attachment/148230589-1ddf5878-fb70-4e4a-920d-fc3f866e08cf.png) (67.1 kB; image/png) I encountered the same problem with Black Magic Probe and OpenOCD. The problem has since been fixed in Black Magic, but it still exists in OpenOCD, hence this is basically a [cross-post from Black Magic's issue tracker](https://github.com/blacksphere/blackmagic/issues/968) with some edits. I am working on a baremetal application based on STM32F446 that heavily relies on semihosting (it is actually a unit testing suite, not that it matters here). Everything was functioning normally until I had to add a peripheral interrupt handler to the application, whereupon I discovered that under some mysterious circumstances the handler might not be invoked despite the appropriate pending/enable flags being set in the NVIC registers. I was never able to find a robust way of reproducing this problem: sometimes it would work reliably across power cycling and software resets, sometimes it would fail. Fast forward a few days, the culprit has been tracked down to `DHCSR.C_MASKINTS`. The versions involved are: - OpenOCD: v0.11 or the current master (reproducible in both) - GDB: `GNU gdb (GNU Arm Embedded Toolchain 10.3-2021.10) 10.2.90.20210621-git` My OpenOCD config is quite standard: ```tcl #!/usr/bin/env -S openocd -f source [find interface/stlink.cfg] transport select hla_swd source [find target/stm32f4x.cfg] gdb_memory_map enable gdb_flash_program enable debug_level 1 ``` First, I power on the board, upload and launch the application: ```gdb target extended-remote :3333 monitor arm semihosting enable monitor arm semihosting_fileio enable set mem inaccessible-by-default off set remote system-call-allowed 1 set confirm off load run ``` The original state of DHCSR after a power-on reset before the application is started is reliably observed as 0x30003, which makes sense, and the first run after power-on always succeeds (interrupts are not masked). However, when the next `run` is executed, occasionally you might observe the original state of DHCSR to be not 0x30003 (where C_MASKINTS is reset) but 0x3000B (where C_MASKINTS is set but C_STEP is not). Executing `run` does not reset C_MASKINTS in this case, which as I understand is not the correct behavior (certainly not the expected behavior). The problem could perhaps be related to incorrect handling of the special modification sequences required for DHCSR, as shown in the attached excerpts from the armv7 tech ref manual. While googling around I stumbled upon this random tweet that may or may not be relevant: https://mobile.twitter.com/azonenberg/status/1162402192793358341 As a tentative workaround, I made a script that resets this bit at every opportinity -- it appears to be effective: ```gdb define clear_dhcsr_c_maskints set {unsigned}0xE000EDF0 = 0xA05F0000 | ({unsigned}0xE000EDF0 & 0b1111111111110111) p/x {unsigned}0xE000EDF0 end catch signal all commands clear_dhcsr_c_maskints end define hook-run clear_dhcsr_c_maskints end define hook-continue clear_dhcsr_c_maskints end ``` --- Sent from sourceforge.net because openocd-devel@lists.sourceforge.net is subscribed to https://sourceforge.net/p/openocd/tickets/ To unsubscribe from further messages, a project admin can change settings at https://sourceforge.net/p/openocd/admin/tickets/options. Or, if this is a mailing list, you can unsubscribe from the mailing list.