Hang Starting nRF52840 Feather Express Under Segger Debugger

I’m trying to use the Segger debugger on an adafruit_feather_nrf52840 board under Platformio. I’m not sure if this and an Adafruit problem or a Platformio problem so I also posted it on the Adafruit forum.

Even in athe most trivial project the debugger repeatedly stops during initialization at NVIC_SetPriority and will not proceed beyond this point. This is my project:

#include <Arduino.h>
void setup()
{
  Serial.println("setup test");
  // put your setup code here, to run once:
}
void loop() {
  // put your main code here, to run repeatedly:
  Serial.println("loop test");
}

Platformio.ini:

[env:adafruit_feather_nrf52840]
platform = nordicnrf52
board = adafruit_feather_nrf52840
framework = arduino

To replicate the problem:

  • Click the “Run and Debug” button on the left in Platformio to enter the debugging panel.

  • Click the “Start Debugging” button at the top.

  • After a moment the program stops at main() in main.cpp:
    // \brief Main entry point of Arduino application
    int main( void )

  • Press F5 to continue. The program halts in core_cm4.h here:

    __STATIC_INLINE void NVIC_SetPriority(IRQn_Type IRQn, uint32_t priority)
    {
    if ((int32_t)(IRQn) < 0)
    {
    SCB->SHP[(((uint32_t)(int32_t)IRQn) & 0xFUL)-4UL] = (uint8_t)((priority << (8U - __NVIC_PRIO_BITS)) & (uint32_t)0xFFUL);
    }
    else
    {
    NVIC->IP[((uint32_t)(int32_t)IRQn)] = (uint8_t)((priority << (8U - __NVIC_PRIO_BITS)) & (uint32_t)0xFFUL); //Halts here
    }
    }

  • Now every time F5 is pressed to continue the program halts in the same place.

  • It’s impossible to debug using the hardware debugger.

However if the program is started without the debugger it runs normally and prints its messages to the serial monitor.

I’m running on a Macbook pro 2015 with the the Feather board plugged into one USB port and the Segger debugger plugged into the other port.

How can I avoid the halting?

Well that’s wrong.

  • Do you get a GDB console when you go into the Debug console? What’s the result of info breakpoints?
  • A screenshot of VSCode, especially regarding the section “Breakpoints”?

Below is the content of the debug console after the following actions:

Build, proceed at main(), halt at NVIC_SetPriority, and an attempt to proceed and another halt at halt at NVIC_SetPriority
At the end of the listing is the reply to “info breakpoints” (says there are no breakpoints).
The PIO Breakpoints section is empty.

Debug console output:

Processing adafruit_feather_nrf52840 (platform: nordicnrf52; board: adafruit_feather_nrf52840; framework: arduino)
--------------------------------------------------------------------------------
Verbose mode can be enabled via `-v, --verbose` option
CONFIGURATION: https:/ /docs.platformio.org/page/boards/nordicnrf52/adafruit_feather_nrf52840.html
PLATFORM: Nordic nRF52 4.0.0 > Adafruit Feather nRF52840 Express
HARDWARE: NRF52840 64MHz, 243KB RAM, 796KB Flash
DEBUG: Current (jlink) External (jlink, stlink)
PACKAGES:
 - framework-arduinoadafruitnrf52 1.1405.191023 (14.5)
 - tool-sreccat 1.164.0 (1.64)
 - toolchain-gccarmnoneeabi 1.70201.0 (7.2.1)
LDF: Library Dependency Finder -> http:/ /bit.ly/configure-pio-ldf
LDF Modes: Finder ~ chain, Compatibility ~ soft
Found 12 compatible libraries
Scanning dependencies...
No dependencies
Building in debug mode
Checking size .pio/build/adafruit_feather_nrf52840/firmware.elf
Advanced Memory Usage is available via "PlatformIO Home > Project Inspect"
RAM:   [          ]   2.4% (used 5976 bytes from 248832 bytes)
Flash: [          ]   4.2% (used 34164 bytes from 815104 bytes)
========================= [SUCCESS] Took 1.16 seconds =========================
SEGGER J-Link GDB Server V6.52 Command Line Version
JLinkARM.dll V6.52 (DLL compiled Sep 27 2019 17:51:01)

Command line: -singlerun -if SWD -select USB -device nRF52840_xxAA -port 2331
-----GDB Server start settings-----
GDBInit file:                  none
GDB Server Listening port:     2331
SWO raw output listening port: 2332
Terminal I/O port:             2333
Accept remote connection:      yes
Generate logfile:              off
Verify download:               off
Init regs on start:            off
Silent mode:                   off
Single run mode:               on
Target connection timeout:     0 ms
------J-Link related settings------
J-Link Host interface:         USB
J-Link script:                 none
J-Link settings file:          none
------Target related settings------
Target device:                 nRF52840_xxAA
Target interface:              SWD
Target interface speed:        4000kHz
Target endian:                 little
Connecting to J-Link...
Reading symbols from /Users/chrisgr/Documents/PlatformIO/Projects/Test Jtag/.pio/build/adafruit_feather_nrf52840/firmware.elf...
done.
PlatformIO Unified Debugger -> http:/ /bit.ly/pio-debug
PlatformIO: debug_tool = jlink
PlatformIO: Initializing remote target...
J-Link is connected.
Firmware: J-Link V10 compiled Aug 27 2019 09:24:55
Hardware: V10.10
S/N: 260117951
OEM: SEGGER-EDU
Feature(s): FlashBP, GDB
Checking target voltage...
Target voltage: 3.31 V
Listening on TCP/IP port 2331
Connecting to target...
Connected to target
Waiting for GDB connection...
Connected to 127.0.0.1
Reading all registers
Read 4 bytes @ address 0x0002A04C (Data = 0x3D04F84D)
0x0002a04c in PendSV_Handler () at /Users/chrisgr/.platformio/packages/framework-arduinoadafruitnrf52/cores/nRF5/freertos/portable/GCC/nrf52/port.c:104
104    __asm volatile
Received monitor command: clrbp
Received monitor command: speed auto
Select auto target interface speed (2000 kHz)
Select auto target interface speed (2000 kHz)
Received monitor command: reset
Resetting target
Resetting target
Received monitor command: halt
Halting target CPU...
...Target halted (PC = 0x00000A80)
Loading section .text, size 0x832c lma 0x26000
Downloading 16032 bytes @ address 0x00026000
Downloading 15984 bytes @ address 0x00029EA0
Downloading 1564 bytes @ address 0x0002DD10
Loading section .ARM.exidx, size 0x8 lma 0x2e32c
Downloading 8 bytes @ address 0x0002E32C
Loading section .data, size 0x240 lma 0x2e334
Downloading 576 bytes @ address 0x0002E334
Start address 0x262b8, load size 34164
Writing register (PC = 0x   262b8)
Transfer rate: 16681 KB/sec, 6832 bytes/write.
Read 4 bytes @ address 0x000262B8 (Data = 0x4A0B490A)
Read 2 bytes @ address 0x000262B8 (Data = 0x490A)
Read 2 bytes @ address 0x00026334 (Data = 0xB500)
Temporary breakpoint 1 at 0x26334: file /Users/chrisgr/.platformio/packages/framework-arduinoadafruitnrf52/cores/nRF5/main.cpp, line 69.
PlatformIO: Initialization completed
PlatformIO: Resume the execution to `debug_init_break = tbreak main`
PlatformIO: More configuration options -> http:/ /bit.ly/pio-debug
Setting breakpoint @ address 0x00026334, Size = 2, BPHandle = 0x0001
Starting target CPU...
...Breakpoint reached @ address 0x00026334
Reading all registers
Removing breakpoint @ address 0x00026334, Size = 2
Read 4 bytes @ address 0x00026334 (Data = 0xB083B500)

Temporary breakpoint 1, main () at /Users/chrisgr/.platformio/packages/framework-arduinoadafruitnrf52/cores/nRF5/main.cpp:69
69 {
info breakpoints
No breakpoints or watchpoints.
{"token":17,"outOfBandRecord":[],"resultRecords":{"resultClass":"done","results":[]}}

So when press F5 to forward execution and it halts at the “breakpoint”, what is printed in the GDB console? It should print something like “SIG<…> target halted / breakpoint hit”

It’s not a real breakpoint. It says:

Starting target CPU…
…Target halted (DBGRQ, PC = 0x00000A64)
Reading all registers

Program
received signal SIGTRAP, Trace/breakpoint trap.
Read 4 bytes @ address 0x00000A64 (Data = 0x471868DB)
Read 2 bytes @ address 0x00000A64 (Data = 0x68DB)
0x00000a64 in ?? ()
Read 4 bytes @ address 0x2003FFAC (Data = 0x21000010)
Reading 64 bytes @ address 0x2003FF80
Read 4 bytes @ address 0x00000760 (Data = 0x47085809)
Read 2 bytes @ address 0x00000760 (Data = 0x5809)
Read 4 bytes @ address 0x2003FFCC (Data = 0x61000000)
Reading 64 bytes @ address 0x2003FFC0
Read 4 bytes @ address 0x0002A486 (Data = 0xF8832240)
Read 4 bytes @ address 0x0002A4E2 (Data = 0xFF0BF7FD)
Read 4 bytes @ address 0x00029EDC (Data = 0x93014B0E)

Also the halt happens with both of the Adafruit Express nRF52480 boards that I have. It also remains if I reboot my Mac.

It’s like it’s hitting an error condition such as an erroneous instruction, invalid memory accessed or an infinite loop caused by changing interrupt priority. However it’s in the default code. I added nothing to this project.

Well it’s hit a debugrequest / SIGTRAP at an very low program counter value. Per memory map the flash starts at 0x00000000, so 0xA64 is just 2660 bytes into the firmware.

Can you start another debugging session, let it halt at the weird NVIC_SetPriority “breakpoint” and then execute these commands

i r
where
x/10i $pc

in the GDB debug terminal? What’s the output?

1 Like

Here is the complete output from those commands:

i r
r0             0x2003ffd0
	537133008

r1             0x239a
	9114

r2             0x380
	896

r3             0xe000e100
	3758153984

r4             0x2000439c
	536888220

r5             0x0
	0

r6             0x0
	0

r7             0x0
	0

r8             0x0
	0

r9             0x0
	0

r10            0x20030000
	537067520

r11            0x0
	0

r12            0x80
	128

sp             0x2003ffd0
	0x2003ffd0

lr             0x2a321
	172833

pc             0x2a322
	0x2a322 <usb_hardware_init()+34>

xpsr           0x61000000
	1627389952

msp            0x2003ff90
	537132944

psp            0x0
	0

primask        0x0
	0

basepri        0x0
	0

faultmask      0x0
	0

control        0x0
	0

{"token":30,"outOfBandRecord":[],"resultRecords":{"resultClass":"done","results":[]}}
where
#0  0x00000a64 in ?? ()
#1  <signal handler called>
#2  0x00000760 in ?? ()
#3  <signal handler called>
#4  0x0002a322 in NVIC_SetPriority (priority=2, IRQn=USBD_IRQn) at /Users/chrisgr/.platformio/packages/framework-arduinoadafruitnrf52/cores/nRF5/cmsis/include/core_cm4.h:1706
#5  usb_hardware_init () at /Users/chrisgr/.platformio/packages/framework-arduinoadafruitnrf52/cores/nRF5/Adafruit_TinyUSB_Core/Adafruit_TinyUSB_Core.cpp:72
#6  0x0002a37e in Adafruit_TinyUSB_Core_init () at /Users/chrisgr/.platformio/packages/framework-arduinoadafruitnrf52/cores/nRF5/Adafruit_TinyUSB_Core/Adafruit_TinyUSB_Core.cpp:88
#7  0x00029d78 in main () at /Users/chrisgr/.platformio/packages/framework-arduinoadafruitnrf52/cores/nRF5/main.cpp:74
Read 4 bytes @ address 0x0002628E (Data = 0xF949F006)
Reading 64 bytes @ address 0x00026240
Read 4 bytes @ address 0x00026298 (Data = 0x20040000)
Read 4 bytes @ address 0x00026296 (Data = 0x00000008)
Read 4 bytes @ address 0x000262A4 (Data = 0x20003650)
Read 4 bytes @ address 0x000262AA (Data = 0x00002000)
{"token":35,"outOfBandRecord":[],"resultRecords":{"resultClass":"done","results":[]}}
x/10i $pc
Reading 64 bytes @ address 0x0002A300
=> 0x2a322 <usb_hardware_init()+34>:	movs	r2, #64	; 0x40
   0x2a324 <usb_hardware_init()+36>:	strb.w	r2, [r3, #807]	; 0x327
   0x2a328 <usb_hardware_init()+40>:	mov.w	r3, #1073741824	; 0x40000000
   0x2a32c <usb_hardware_init()+44>:	ldr.w	r4, [r3, #1080]	; 0x438
   0x2a330 <usb_hardware_init()+48>:	tst.w	r4, #1
   0x2a334 <usb_hardware_init()+52>:	bne.n	0x2a340 <usb_hardware_init()+64>
   0x2a336 <usb_hardware_init()+54>:	tst.w	r4, #2
   0x2a33a <usb_hardware_init()+58>:	bne.n	0x2a348 <usb_hardware_init()+72>
   0x2a33c <usb_hardware_init()+60>:	add	sp, #8
   0x2a33e <usb_hardware_init()+62>:	pop	{r4, pc}
{"token":39,"outOfBandRecord":[],"resultRecords":{"resultClass":"done","results":[]}}

btw - I was also seeing this same behavior (and same register dump that @chrisgr99 got). I’m on a NRF52840-DK with the Adafruit BSP. The failure seems to only occur if I try to ‘step-over’ the startup of the freertos scheduler (vTaskStartScheduler call in main.cpp of the adafruit arduino env).

If I don’t do that (and instead just let it run) everything seems to work okay and I can set breakpoints nicely in my app.

Thanks “geeksville”. What you are reporting certainly seems related to my problem. However in the firmware for the Feather nRF52840, Adafruit_TinyUSB_Core_init() - where the hang occurs - is called before vTaskStartScheduler(). I never get to stage of being able to not step over vTaskStartScheduler.

The hang occurs in Adafruit_TinyUSB_Core_init whether I step over it or not. It seems that the rtos is using an interrupt that conflicts with the debugger.

If it is useful for you, I’ve made a little workaround for this (it started happening to me again).

It is a little gdbinit script that adds a “restart” command. I run this after start and all is well for nicely hitting only the breakpoints I set. A side benefit, I can run “restart” if I want to restart my load without having to rebuild/flash.

gdbinit:

# the jlink debugger seems to want a pause after reset before we tell it to start running
define restart
  monitor reset 
  shell sleep 1
  cont 
end

And in my platformio.ini:

debug_tool = jlink
build_type = debug ; I'm debugging with ICE a lot now
debug_extra_cmds =
  source gdbinit
1 Like

Thanks! This does seem to solve the problem. Specifically this is what I did:
Create a .gdbinit file in my home directory containing:

 define restart
     monitor reset 
     shell sleep 1
     cont 
 end

Change platformio.ini file to be:

[env:adafruit_feather_nrf52840]
platform = nordicnrf52
board = adafruit_feather_nrf52840
framework = arduino
debug_tool = jlink
upload_protocol = jlink
build_type = debug 
debug_extra_cmds = source gdbinit

Then in Platformio (VSCode ), start the debugger. (Press the Run button in the Activity Bar and then the Run - PIO Debug button in the top left.)
When the program stops at the first line in main.cpp type “restart” in the debug console, hit enter.
The program starts running normally and hits the first real breakpoint, if any.

This works. Is it the correct way to do it?

3 Likes

Had same issue and fix worked. Had to set a HOME environment variable in Windows.

1 Like

Yes, this worked for me trying to debug an Adafruit Nano 33 IOT on Windows 10 using a JLink-EDU.

The only difference was that I didn’t need the sleep to delay continuing. Of course sleep isn’t in the default cmd shell anyway, and I initially used

ping -n XXX 127.0.0.1 >nul

Where XXX is the number of seconds +1. But I found it worked without needing a delay.

@chrisgr99: Thanks for your solution. It works also on a Particle Xenon (nrf52840).

@all: Has anyone tried to completely remove the bootloader as they did for an Adafruit Feather M0 in the following post? Problems starting debug session with jlink on feather M0 - #11 by prototypicalpro
This is much faster than having to restart the debug session every times.

Exact same problem, but cannot solve with this solution?!

Program runs until
void vPortStartFirstTask( void )
{
__asm volatile(

then stopped. Any ideas?

I R results:
r0 0xe0
224

r1 0x40011008
1073811464

r2 0xe000ef30
3758157616

r3 0x10
16

r4 0xe000ed00
3758157056

r5 0x0
0

r6 0x0
0

r7 0x0
0

r8 0x0
0

r9 0x0
0

r10 0x20030000
537067520

r11 0x0
0

r12 0x0
0

sp 0x20040000
0x20040000

lr 0x2d61b
185883

pc 0x2d8de
0x2d8de <vPortStartFirstTask+30>

xpsr 0x61000000
1627389952

Reading register (MSP = 0x2003FFE0)
msp 0x2003ffe0
537133024

Reading register (PSP = 0x 0)
psp 0x0
0

Reading register (PRIMASK = 0x 0)
primask 0x0
0

Reading register (BASEPRI = 0x E0)
basepri 0xe0
224

Reading register (FAULTMASK = 0x 0)
faultmask 0x0
0

Reading register (CONTROL = 0x 0)
control 0x0
0

{“token”:63,“outOfBandRecord”:[],“resultRecords”:{“resultClass”:“done”,“results”:[]}}

THANKS @geeksville!

Your gdb restart script finally solved a UARTE hang in the HAL on a Nano 33 BLE while trying to use pio debug. Sketch ran fine without pio debug. Tried the “tbreak loop” and several other things suggested on forum. Just needed to restart sketch without reloading to fix the problem. Sheesh.

Manifestation of my problem seemed a bit different from other folks here, so I include the culpable code below.

Comment in the InitVariant() code where hang occurred said:

“// Disable UARTE0 which is initially enabled by the bootloader”

with the hang occurring in:
__STATIC_INLINE bool nrf_uarte_event_check
(NRF_UARTE_Type * p_reg, nrf_uarte_event_t event)
{ return (bool)*(volatile uint32_t *)((uint8_t *)p_reg + (uint32_t)event); }