Skip to content
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

cpu/nrf52: OpenOCD not working with newer Revision Silicon and nRF52840 J-Link #20968

Closed
5 tasks done
crasbe opened this issue Nov 8, 2024 · 5 comments
Closed
5 tasks done

Comments

@crasbe
Copy link
Contributor

crasbe commented Nov 8, 2024

Description

In the PR #20965 @mguetschow raised the question whether the fix could be implemented for OpenOCD as well and I discovered that using OpenOCD with RIOT on the nRF52 platform seems to have two issues:

  1. OpenOCD does not work with the J-Link embedded in the nRF52840 DK (I have PCA10056 Rev 3.0.1 from 2023 here, older versions might work).
PROGRAMMER=openocd BOARD=nrf52840dk make -C examples/hello-world flash
...
### Flashing Target ###
Open On-Chip Debugger 0.11.0
Licensed under GNU GPL v2
For bug reports, read
        http://openocd.org/doc/doxygen/bugs.html
swd
Error: No J-Link device found.

To get some more debug information, you can add change line 340 of dist/tools/openocd/openocd.sh:

- sh -c "${OPENOCD} \
+ sh -c "${OPENOCD} -d3 \

This yields the following:

...
Debug: 87 2 target.c:1639 handle_target_init_command(): Initializing targets...
Debug: 88 2 semihosting_common.c:99 semihosting_common_init():  
Debug: 89 2 jlink.c:647 jlink_init(): Using libjaylink 0.2.0 (compiled with 0.2.0).
Debug: 90 12 jlink.c:526 jaylink_log_handler(): Found 0 USB device(s).
Error: 91 12 jlink.c:683 jlink_init(): No J-Link device found.
Debug: 92 12 command.c:628 run_command(): Command 'init' failed with error code -100
User : 93 12 command.c:694 command_run_line():
...

The latest libjaylink recognizes the following Product IDs (https://gitlab.zapb.de/libjaylink/libjaylink/-/blob/master/libjaylink/discovery_usb.c?ref_type=heads#L50-L71 https://gitlab.zapb.de/libjaylink/libjaylink/-/blob/master/contrib/60-libjaylink.rules?ref_type=heads#L23-L45), and Segger J-Link firmware from "2024 Oct 9 11:01" uses 1060:

chris@ThinkPias:~$ lsusb
...
Bus 003 Device 005: ID 1366:1060 SEGGER J-Link
...

I will write Mark Schink, who is the (only?) developer of libjaylink an E-Mail and ask him to add the nRF52840DK product ID to the library. HOWEVER only when OpenOCD adopts the new libjaylink and pushes a new release this issue will be fixed.
So we'll probably have to add a remark to the documentation that the nRF52840 DK is not supported by OpenOCD for the time being.


Using a different programmer than the builtin J-Link (such as an J-Link EDU, which is supported by libjaylink v0.2.0) does work, but it brings us to the next issue:
  1. The OpenOCD script from RIOT does not unlock the APPROTECT register of the nRF52 chip. This is an issue that was not present on older silicon revisions, because the protection mechanism was a lot less strict (similarly to how the reset used to work differently).

On newer revisions, the chip is always protected after a reset or power cycle after programming and can not be read out or written to. The only way to write to the chip is to unprotect it, which the current OpenOCD script does not do.

OpenOCD provides a command for it, called nrf52_recover... HOWEVER it has to be called after the initialization and before any other commands trying to access it. Looking at the script in dist/tools/openocd/openocd.sh L339ff, we would have to define a new variable:

    # flash device
    sh -c "${OPENOCD} \
            ${OPENOCD_ADAPTER_INIT} \
            -f '${OPENOCD_CONFIG}' \
            ${OPENOCD_EXTRA_INIT} \
            ${OPENOCD_EXTRA_RESET_INIT} \
            -c 'tcl_port 0' \
            -c 'telnet_port 0' \
            -c 'gdb_port 0' \
            -c 'init' \
+           ${OPENOCD_POST_INIT_CMDS} \
            -c 'targets' \
            ${OPENOCD_CMD_RESET_HALT} \
            ${OPENOCD_PRE_FLASH_CMDS} \
            -c 'flash write_image erase \"${IMAGE_FILE}\" ${IMAGE_OFFSET} ${IMAGE_TYPE}' \
            ${OPENOCD_PRE_VERIFY_CMDS} \
            ${OPENOCD_VERIFY} \
            -c 'reset run' \
            -c 'shutdown'" &&

And the boards/common/nrf52/Makefile.include would get the following entry:

# Before writing to the nRF52 flash, the APPROTECT has to be disabled
# or in Nordic terms 'recovered'. This will delete the entire flash content and
# the UICR register.
OPENOCD_POST_INIT_CMDS = -c nrf52_recover

  1. A somewhat unrelated issue: the variables OPENOCD_EXTRA_INIT and OPENOCD_EXTRA_RESET_INIT are not exported in makefiles/tools/openocd.inc.mk and therefore ignored when you try to use them in a Makefile.
    Apparently at the moment nobody does that, so nobody noticed it.

Versions

OpenOCD v0.1.1
libjaylink v0.2.0

Tasks

  • Get Product ID 1060 added to libjaylink
  • Have OpenOCD update libjaylink in the next release (hopefully?)
  • Add an information in the documentation why the nRF52840 DK is not currently supported by OpenOCD.
  • Add the OPENOCD_POST_INIT variable to the build system.
  • Add the unexported variables to the openocd.inc.mk file.

Currently I can't really tell how high of a priority this is for me and apparently nobody else uses OpenOCD to program nRF52 chips (because if someone did, it would've surfaced this issue 😅 )

I'd like to hear some feedback about the proposed fixes.

@mguetschow
Copy link
Contributor

Thanks so much for digging into this!

I have the following setup:

  • nrf52840dk PCA10056 Rev 3.0.1 2023.12 (probably same as you)
  • openOCD 0.12.0 (newer than yours)

After flashing once with J-Link (where the Debug Port Protection gets presumably disabled), flashing with openOCD works just fine:

$ PROGRAMMER=openocd BOARD=nrf52840dk make -C examples/hello-world flash-only
...
### Flashing Target ###
Open On-Chip Debugger 0.12.0
Licensed under GNU GPL v2
For bug reports, read
        http://openocd.org/doc/doxygen/bugs.html
swd
Info : J-Link OB-nRF5340-NordicSemi compiled Oct 30 2023 12:13:06
Info : Hardware version: 1.00
Info : VTarget = 3.300 V
Info : clock speed 1000 kHz
Info : SWD DPIDR 0x2ba01477
Info : [nrf52.cpu] Cortex-M4 r0p1 processor detected
Info : [nrf52.cpu] target has 6 breakpoints, 4 watchpoints
Info : starting gdb server for nrf52.cpu on 0
Info : Listening on port 36995 for gdb connections
    TargetName         Type       Endian TapName            State       
--  ------------------ ---------- ------ ------------------ ------------
 0* nrf52.cpu          cortex_m   little nrf52.cpu          running

[nrf52.cpu] halted due to debug-request, current mode: Thread 
xPSR: 0x01000000 pc: 0x00000da8 msp: 0x20000200
Info : nRF52840-xxAA(build code: F0) 1024kB Flash, 256kB RAM
Warn : Adding extra erase range, 0x00002ce4 .. 0x00002fff
auto erase enabled
wrote 11492 bytes from file /home/mikolai/TUD/Code/RIOT-build/examples/hello-world/bin/nrf52840dk/hello-world.elf in 0.528748s (21.225 KiB/s)

verified 11492 bytes in 0.076022s (147.624 KiB/s)

shutdown command invoked
Done flashing

I'm not sure how openOCD selects the J-Link version it uses, so that could be the difference here.

After reconnecting the board and without an initial flash via J-Link, flashing with openOCD is indeed impossible due to access port protection:

$ PROGRAMMER=openocd BOARD=nrf52840dk make -C examples/hello-world flash-only
...
### Flashing Target ###
Open On-Chip Debugger 0.12.0
Licensed under GNU GPL v2
For bug reports, read
        http://openocd.org/doc/doxygen/bugs.html
swd
Info : J-Link OB-nRF5340-NordicSemi compiled Oct 30 2023 12:13:06
Info : Hardware version: 1.00
Info : VTarget = 3.300 V
Info : clock speed 1000 kHz
Info : SWD DPIDR 0x2ba01477
Error: [nrf52.cpu] Could not find MEM-AP to control the core
****** WARNING ******
nRF52 device has AP lock engaged (see UICR APPROTECT register).
Debug access is denied.
Use 'nrf52_recover' to erase and unlock the device.

Warn : target nrf52.cpu examination failed
Info : starting gdb server for nrf52.cpu on 0
Info : Listening on port 36369 for gdb connections
    TargetName         Type       Endian TapName            State       
--  ------------------ ---------- ------ ------------------ ------------
 0* nrf52.cpu          cortex_m   little nrf52.cpu          unknown

Error: [nrf52.cpu] Could not find MEM-AP to control the core
****** WARNING ******
nRF52 device has AP lock engaged (see UICR APPROTECT register).
Debug access is denied.
Use 'nrf52_recover' to erase and unlock the device.

Error: [nrf52.cpu] Debug AP not available, reset NOT asserted!

I'd like to hear some feedback about the proposed fixes.

They all sound sensible to me. Maybe we could have the POST_INIT fix even before the libjaylink changes so that flashing at least works in your case 2.

@crasbe
Copy link
Contributor Author

crasbe commented Nov 8, 2024

Thank you for your quick feedback.
Could you post the output of lsusb? It looks like your builtin J-Link has an older firmware version (October 2023). Maybe SEGGER changed the product ID at some point?

Other than that the behavior is expected. As long as the device is not reset/power cycled, it stays unlocked. Therefore you can program it with OpenOCD after programming it with J-Link.

I will probably incorporate the POST_INIT_CMD into the reset PR. In the meantime I found out how to set the UICR register with OpenOCD, so the reset fix can be applied to OpenOCD as well.

@mguetschow
Copy link
Contributor

Could you post the output of lsusb?

Bus 001 Device 017: ID 1366:1051 SEGGER J-Link

I will probably incorporate the POST_INIT_CMD into the reset PR. In the meantime I found out how to set the UICR register with OpenOCD, so the reset fix can be applied to OpenOCD as well.

Great!

@crasbe
Copy link
Contributor Author

crasbe commented Nov 10, 2024

The author of libjaylink, Marc Schinkel, added the Product ID to the lib and will create a new revision soon. OpenOCD will not use libjaylink as a submodule in the next release but will use libjaylink as a shared library installed from the package sources.
Therefore, adding product IDs is decoupled from OpenOCD releases.

The first two tasks are therefore completed, I'll just have to add a remark to the documentation to use the correct OpenOCD and libjaylink releases for the nRF52840DK.

@crasbe
Copy link
Contributor Author

crasbe commented Nov 21, 2024

I added the remark to the #20592 issue, so this one can be closed.

Thank you @mguetschow for working with me on this :)

@crasbe crasbe closed this as completed Nov 21, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants