Skip to content

cpu/nrf52: Add Make Option to Enable Pinreset #20775

@crasbe

Description

@crasbe

Description

In PR #10072, the nrf52_resetpin_cfg tool was introduced, allowing to program the persistent UICR register on the nRF52 boards.
Something must have changed since 2018, but when an nRF52 is programmed via the J-Link (not via bootloader), the UCIR register is always reset and therefore the pinreset does not work anymore.

Usually the programming sequence is somewhat like this:

  • Unlock (or recover) the device (this erases all of the Flash and the UICR, which holds the Pinreset configuration)
  • Perform a chiperase
  • Write the bin/hex
  • Verify
  • (optionally) write the UCIR
  • on the first reset or power down, power up, the nRF has the readback protection enabled which you can only disable by "unlocking" or "recovering" the device, deleting Flash and UICR

nrfjprog shows the issue nicely. I try to read the UICR register after powering up an nRF52840DK board. It fails because the readback protection is activated. Then I recover the device, which deletes the Flash and UICR area. After that I can read out the UICR, but it is blank.
To see how it should look like, I activate the pinreset (without powering the device down in between!) and read it out again.

chris@ThinkPias:~$ nrfjprog --readuicr asdf.hex
[error] [ Client] - Encountered error -90: Command read_device_info executed for 2 milliseconds with result -90
[error] [ Worker] - Access protection is enabled, can't read device version.
[error] [ Client] - Encountered error -90: Command read_memory_descriptors executed for 2 milliseconds with result -90
[error] [ Worker] - Can't read memory descriptors, ap-protection is enabled.
ERROR: The operation attempted is unavailable due to readback protection in
ERROR: your device. Please use --recover to unlock the device.
NOTE: For additional output, try running again with logging enabled (--log).
NOTE: Any generated log error messages will be displayed.
chris@ThinkPias:~$ nrfjprog --recover
Recovering device. This operation might take 30s.
Erasing user code and UICR flash areas.
Writing image to disable ap protect.
chris@ThinkPias:~$ nrfjprog --readuicr asdf.hex
Storing data in 'asdf.hex'.


chris@ThinkPias:~$ nrfjprog --pinresetenable
Enabling pin reset.
chris@ThinkPias:~$ nrfjprog --readuicr asdf2.hex
Storing data in 'asdf2.hex'.

On the left side, the UICR is shown before enabling the pinreset and on the right side it is shown after the pinreset.
UICR before and after pinresetenable

Programming with J-Link is pretty much the same, but nrfjprog is a lot more verbose about what it does and why it does (or does not) do something.

So essentially what I want to say is that it would be nice to be able to activate the Pinreset when flashing a RIOT image with make flash.
@benpicco proposed a software based solution in #19833, but the nRF52s do have the Pinreset registers in UICR, so why not use them? (However I am still in favor of merging that PR, it is nice to have a software option as well.)

Now... the thing is that with nrfjprog it is very easy to activate the Pinreset, just call nrfjprog --pinresetenable after programming (and before the first reset). With J-Link it is not so easy because it does not have a dedicated option to do it.
In general I see two main possibilities:

  1. Create a JLINK_POST_FLASH define for dist/tools/jlink.sh, that writes the right values into the UICR. So far nobody seems to use JLINK_POST_FLASH for anything.
  2. Activate the pinreset with nrfjprog. This would require an additional dependency, which is probably not favorable.

Option 1 seems to work. The base address for the UICR register is 0x10001000 for the nRF52840 and the offset for of the PSELRESET registers is 0x200 and 0x204. Essentially I just copied the memory content from what `nrfjprog` puts into the registers. Setting the registers with the J-Link programmer works when I add `JLINK_POST_FLASH` to the command like this:
JLINK_POST_FLASH='Write4 0x10001200 00000012 00000012' BOARD=nrf52840dk make flash term

We can check the burn file that is created by makefiles/tools/jlink.inc.mk has the right post-flash operation:

chris@ThinkPias:~/flashdev-riot/RIOT/examples/default$ cat bin/nrf52840dk/burn.seg 
loadfile /home/chris/SmartSensors/spacepatch-riot/RIOT/examples/default/bin/nrf52840dk/default.elf
Write4 0x10001200 00000012 00000012
r
g
exit

HOWEVER when I add JLINK_POST_FLASH = Write4 0x10001200 00000012 00000012 to the boards/nrf52840dk/Makefile.include and just call BOARD=nrf52840dk make flash term, it does not work. What's odd though is that it does work when I call JLINK_POST_FLASH='' BOARD=nrf52840dk make flash term.

Then I tried it with JLINK_PRE_FLASH because that is actually used by some boards, but it has the same behavior.

What's odd as well is that the 'stk3200' board, which uses JLINK_PRE_FLASH in it's boards/stk3200/Makefile.include shows the same behavior. Without adding JLINK_PRE_FLASH='' or similar to the command line, the r from the Makefile is not added to the burn.seg file.

Maybe someone has some guidance on that or generally some feedback about the approach.

Useful links

Documentation about the UICR:
https://docs.nordicsemi.com/bundle/ps_nrf52832/page/uicr.html#register.PSELRESET-0

Documentation about the Pinreset (not very much unfortunately):
https://docs.nordicsemi.com/bundle/ps_nrf52832/page/power.html#d935e411

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions