Add semihosting support for nrf52 devices (#4137)

* Turn off vscode cmake prompt - we don't use cmake on meshtastic

* Add rak4631_dap variant for debugging with NanoDAP debug probe device.

* The rak device can also run freertos (which is underneath nrf52 arduino)

* Add semihosting support for nrf52840 devices
Initial platformio.ini file only supports rak4630
Default to non TCP for the semihosting log output for now...
Fixes https://github.com/meshtastic/firmware/issues/4135

* fix my botched merge - keep board_level = extra flag for rak3631_dbg

---------

Co-authored-by: Ben Meadors <benmmeadors@gmail.com>
This commit is contained in:
geeksville 2024-06-24 08:27:37 -07:00 committed by GitHub
parent 58c00d0447
commit aa12e28568
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 126 additions and 14 deletions

View File

@ -35,7 +35,7 @@
"svd_path": "nrf52840.svd", "svd_path": "nrf52840.svd",
"openocd_target": "nrf52840-mdk-rs" "openocd_target": "nrf52840-mdk-rs"
}, },
"frameworks": ["arduino"], "frameworks": ["arduino", "freertos"],
"name": "WisCore RAK4631 Board", "name": "WisCore RAK4631 Board",
"upload": { "upload": {
"maximum_ram_size": 248832, "maximum_ram_size": 248832,

7
pyocd.yaml Normal file
View File

@ -0,0 +1,7 @@
# This is a config file to control pyocd ICE debugger probe options (only used for NRF52 targets with hardware debugging connections)
# for more info see FIXMEURL
# console or telnet
semihost_console_type: telnet
enable_semihosting: True
telnet_port: 4444

View File

@ -25,6 +25,14 @@
#include "SerialConsole.h" #include "SerialConsole.h"
// If defined we will include support for ARM ICE "semihosting" for a virtual
// console over the JTAG port (to replace the normal serial port)
// Note: Normally this flag is passed into the gcc commandline by platformio.ini.
// for an example see env:rak4631_dap.
// #ifndef USE_SEMIHOSTING
// #define USE_SEMIHOSTING
// #endif
#define DEBUG_PORT (*console) // Serial debug port #define DEBUG_PORT (*console) // Serial debug port
#ifdef USE_SEGGER #ifdef USE_SEGGER

View File

@ -149,13 +149,43 @@ void nrf52Loop()
checkSDEvents(); checkSDEvents();
} }
#ifdef USE_SEMIHOSTING
#include <SemihostingStream.h>
/**
* Note: this variable is in BSS and therfore false by default. But the gdbinit
* file will be installing a temporary breakpoint that changes wantSemihost to true.
*/
bool wantSemihost;
/**
* Turn on semihosting if the ICE debugger wants it.
*/
void nrf52InitSemiHosting()
{
if (wantSemihost) {
static SemihostingStream semiStream;
// We must dynamically alloc because the constructor does semihost operations which
// would crash any load not talking to a debugger
semiStream.open();
semiStream.println("Semihosting starts!");
// Redirect our serial output to instead go via the ICE port
console->setDestination(&semiStream);
}
}
#endif
void nrf52Setup() void nrf52Setup()
{ {
auto why = NRF_POWER->RESETREAS; uint32_t why = NRF_POWER->RESETREAS;
// per // per
// https://infocenter.nordicsemi.com/index.jsp?topic=%2Fcom.nordic.infocenter.nrf52832.ps.v1.1%2Fpower.html // https://infocenter.nordicsemi.com/index.jsp?topic=%2Fcom.nordic.infocenter.nrf52832.ps.v1.1%2Fpower.html
LOG_DEBUG("Reset reason: 0x%x\n", why); LOG_DEBUG("Reset reason: 0x%x\n", why);
#ifdef USE_SEMIHOSTING
nrf52InitSemiHosting();
#endif
// Per // Per
// https://devzone.nordicsemi.com/nordic/nordic-blog/b/blog/posts/monitor-mode-debugging-with-j-link-and-gdbeclipse // https://devzone.nordicsemi.com/nordic/nordic-blog/b/blog/posts/monitor-mode-debugging-with-j-link-and-gdbeclipse
// This is the recommended setting for Monitor Mode Debugging // This is the recommended setting for Monitor Mode Debugging

View File

@ -20,6 +20,7 @@ lib_deps =
debug_tool = jlink debug_tool = jlink
; If not set we will default to uploading over serial (first it forces bootloader entry by talking 1200bps to cdcacm) ; If not set we will default to uploading over serial (first it forces bootloader entry by talking 1200bps to cdcacm)
; Note: as of 6/2013 the serial/bootloader based programming takes approximately 30 seconds ; Note: as of 6/2013 the serial/bootloader based programming takes approximately 30 seconds
;upload_protocol = jlink ;upload_protocol = jlink
@ -27,26 +28,92 @@ debug_tool = jlink
; Allows programming and debug via the RAK NanoDAP as the default debugger tool for the RAK4631 (it is only $10!) ; Allows programming and debug via the RAK NanoDAP as the default debugger tool for the RAK4631 (it is only $10!)
; programming time is about the same as the bootloader version. ; programming time is about the same as the bootloader version.
; For information on this see the meshtastic developers documentation for "Development on the NRF52" ; For information on this see the meshtastic developers documentation for "Development on the NRF52"
[env:rak4631_dap] [env:rak4631_dbg]
extends = env:rak4631 extends = env:rak4631
board_level = extra board_level = extra
; pyocd pack --i nrf52840
; if the builtin version of openocd has a buggy version of semihosting, so use the external version
; platform_packages = platformio/tool-openocd@^3.1200.0
build_flags =
${env:rak4631.build_flags}
-D USE_SEMIHOSTING
lib_deps =
${env:rak4631.lib_deps}
https://github.com/geeksville/Armduino-Semihosting.git#35b538fdf208c3530c1434cd099a08e486672ee4
; NOTE: the pyocd support for semihosting is buggy. So I switched to using the builtin platformio support for the stlink adapter which worked much better.
; However the built in openocd version in platformio has buggy support for TCP to semihosting.
;
; So I'm now trying the external openocd - but the openocd scripts for nrf52.cfg assume you are using a DAP adapter not an STLINK adapter.
; In theory I could change those scripts. But for now I'm trying going back to a DAP adapter but with the external openocd.
upload_protocol = stlink
; eventually use platformio/tool-pyocd@^2.3600.0 instad ; eventually use platformio/tool-pyocd@^2.3600.0 instad
upload_protocol = custom ;upload_protocol = custom
upload_command = pyocd flash -t nrf52840 $UPLOADERFLAGS $SOURCE ;upload_command = pyocd flash -t nrf52840 $UPLOADERFLAGS $SOURCE
; We want the initial breakpoint at setup() instead of main(). Also we want to enable semihosting at that point so instead of
; debug_init_break = tbreak setup
; we just turn off the platformio tbreak and do it in .gdbinit (where we have more flexibility for scripting)
; also we use a permanent breakpoint so it gets reused each time we restart the debugging session?
debug_init_break = tbreak setup
; Note: add "monitor arm semihosting_redirect tcp 4444 all" if you want the stdout from the device to go to that port number instead
; (for use by meshtastic command line)
; monitor arm semihosting disable
; monitor debug_level 3
;
; IMPORTANT: fileio must be disabled before using port 5555 - openocd ver 0.12 has a bug where if enabled it never properly parses the special :tt name
; for stdio access.
; monitor arm semihosting_redirect tcp 5555 stdio
; Also note: it is _impossible_ to do non blocking reads on the semihost console port (an oversight when ARM specified the semihost API).
; So we'll neve be able to general purpose bi-directional communication with the device over semihosting.
debug_extra_cmds =
echo Running .gdbinit script
monitor arm semihosting enable
monitor arm semihosting_fileio enable
monitor arm semihosting_redirect disable
commands 1
echo Breakpoint at setup() has semihosting console, connect to it with "telnet localhost 5555"
set wantSemihost = true
end
; Only reprogram the board if the code has changed ; Only reprogram the board if the code has changed
debug_load_mode = modified debug_load_mode = modified
;debug_load_mode = manual ;debug_load_mode = manual
debug_tool = custom debug_tool = stlink
;debug_tool = custom
; debug_server =
; openocd
; -f
; /usr/local/share/openocd/scripts/interface/stlink.cfg
; -f
; /usr/local/share/openocd/scripts/target/nrf52.cfg
; $PLATFORMIO_CORE_DIR/packages/tool-openocd/openocd/scripts/interface/cmsis-dap.cfg
; Allows programming and debug via the RAK NanoDAP as the default debugger tool for the RAK4631 (it is only $10!)
; programming time is about the same as the bootloader version.
; For information on this see the meshtastic developers documentation for "Development on the NRF52"
; We manually pass in the elf file so that pyocd can reverse engineer FreeRTOS data (running threads, etc...) ; We manually pass in the elf file so that pyocd can reverse engineer FreeRTOS data (running threads, etc...)
debug_server = ;debug_server =
pyocd ; pyocd
gdbserver ; gdbserver
-t ; -j
nrf52840 ; ${platformio.workspace_dir}/..
--elf ; -t
${platformio.build_dir}/${this.__env__}/firmware.elf ; nrf52840
; --semihosting
; --elf
; ${platformio.build_dir}/${this.__env__}/firmware.elf
; If you want to debug the semihosting support you can turn on extra logging in pyocd with
; -L
; pyocd.debug.semihost.trace=debug
; The following is not needed because it automatically tries do this ; The following is not needed because it automatically tries do this
;debug_server_ready_pattern = -.*GDB server started on port \d+.* ;debug_server_ready_pattern = -.*GDB server started on port \d+.*
;debug_port = localhost:3333 ;debug_port = localhost:3333