---

** [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.


Reply via email to