-
Notifications
You must be signed in to change notification settings - Fork 2k
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: Add Make Option to Enable Pinreset #20775
Comments
Thanks for opening the issue, I also already stumbled upon this. Just for reference, here are some links from the nRF52840 PS:
An explanation for this can be found on https://docs.nordicsemi.com/bundle/ps_nrf52840/page/dif.html#d402e184: access port protect is enabled by default for newer build codes, which means that UICR will be reset on every flash. This was before only the case after manually enabling ap protect. A work-around I was using locally is adding the following to the nrf52 boot-up code: diff --git a/cpu/nrf52/cpu.c b/cpu/nrf52/cpu.c
index 7f34a4d231..25d90d1c1f 100644
--- a/cpu/nrf52/cpu.c
+++ b/cpu/nrf52/cpu.c
@@ -86,6 +86,19 @@ void cpu_init(void)
/* trigger static peripheral initialization */
periph_init();
+
+// valid for nrf52840dk, see RIOT/dist/tools/nrf52_resetpin_cfg/Makefile
+#define RESET_PIN 18
+ if (((NRF_UICR->PSELRESET[0] & UICR_PSELRESET_CONNECT_Msk) != (UICR_PSELRESET_CONNECT_Connected << UICR_PSELRESET_CONNECT_Pos)) ||
+ ((NRF_UICR->PSELRESET[1] & UICR_PSELRESET_CONNECT_Msk) != (UICR_PSELRESET_CONNECT_Connected << UICR_PSELRESET_CONNECT_Pos))){
+ NRF_NVMC->CONFIG = NVMC_CONFIG_WEN_Wen;
+ while (NRF_NVMC->READY == NVMC_READY_READY_Busy) {}
+ NRF_UICR->PSELRESET[0] = RESET_PIN;
+ NRF_UICR->PSELRESET[1] = RESET_PIN;
+ while (NRF_NVMC->READY == NVMC_READY_READY_Busy) {}
+ NRF_NVMC->CONFIG = NVMC_CONFIG_WEN_Ren;
+ NVIC_SystemReset();
+ }
}
/** I think such code could be conditionally compiled in depending on the make option as option 3, with the advantage that it would be independent of the flashing tool, but the disadvantage that it would slightly increase .text, and lead to some overhead especially on the first, but also on subsequents starts. I don't have a strong opinion on which way to go, but I just wanted to mention that option as well. |
Thank you, I was looking for this information but I searched at the wrong spot (I looked at the erratas and searched for UICR and Pinreset, but not for AP).
Your option 3 is very good, but I would probably approach it in a more general way (read: write a function that can make any pin a reset pin, as was intended with the PSELRESET register). At least the nRF52DK and nRF52840DK have different pins for the reset button. For the nRF52DK it is on P0.21 (https://infocenter.nordicsemi.com/pdf/nRF52_DK_User_Guide_v2.x.x.pdf page 6) and for the nRF52840DK it is on P0.18 (https://infocenter.nordicsemi.com/pdf/nRF52840_DK_User_Guide_v1.2.pdf page 14). Therefore I would only add the An elegant solution would be to have something like |
I did some more work finding out about why the After some googleing I found out, that this behavior means the variable was not exported (from the make environment to the shell script environment). But when I define After a lot of digging I found it. @aabadie removed all JLINK related variables from the export list in HOWEVER in PR #15475, this include was removed and from that point, the ... Phew, that was a lot of digging 😅 |
From looking in #15475 I would expect Not sure why it would not be included just from looking at github PRs and source code. If you would want In practice, using exports there is a simplification to not have to provide and parse arguments. Things that can help debug, are the usual "print" debug that can be added https://www.gnu.org/software/make/manual/html_node/Make-Control-Functions.html and is easier to look at that the full verbose output of make.
|
@cladmi Thank you for taking time to explain this a little more to me.
You are right,
This is right as well, but I copied the code from For debugging, I changed the
So indeed it looks like the variables should be exported and indeed
To get to the bottom of this, I replaced the
And now it works. From what I could grasp from the Make documentation, the "flash%" is a pattern which matches with any non-empty substring. So a match would be "flash-only", but "flash" itself would not. When I change To test the theory, I reverted the target back to So... where does this leave us now? We could change |
From https://www.gnu.org/software/make/manual/make.html#Pattern-Rules seems indeed the case. I may have overlooked this at that time, so would be the one to blame for introducing this pattern, I do not remember. Let's say it's my fault and would be easier :D Changing Either as a quickfix only here first if that unblocks you and plan to fix the rest later, or directly as a longer plan to fix all files as other targets may also be affected. Could even get some kind of Not sure who is maintaining these at the moment, I am long gone. Out of scope: Noting that -ifneq (,$(JLINK_RESET_FILE))
- # Export JLINK_RESET_FILE to required targets if not empty
- $(call target-export-variables,$(JLINK_TARGETS),JLINK_RESET_FILE)
-endif
+$(call target-export-non-empty-variables,$(LINK_TARGETS),JLINK_RESET_FILE) |
At the moment I prefer the quick fix, because this is already the third tangent I'm on. Originally I just wanted to make the nRF52 documentation a bit better, then I stumbled upon this reset thing (well I knew about it before, but that's part of the documentation) and this Makefile issue is now required to fix the reset issue.
The
OPENOCD_TARGETS = debug% flash% reset
# Export GDB_PORT_CORE_OFFSET to required targets
$(call target-export-variables,$(OPENOCD_TARGETS),GDB_PORT_CORE_OFFSET)
ifneq (,$(OPENOCD_CMD_RESET_HALT))
# Export OPENOCD_CMD_RESET_HALT only to the flash targets
$(call target-export-variables,flash,OPENOCD_CMD_RESET_HALT)
$(call target-export-variables,flash-only,OPENOCD_CMD_RESET_HALT)
endif
OPENOCD_FLASH_TARGETS = flash flash-only flashr
ifneq (,$(IMAGE_OFFSET))
# Export IMAGE_OFFSET only to the flash/flash-only target
$(call target-export-variables,$(OPENOCD_FLASH_TARGETS),IMAGE_OFFSET)
endif
This is something that especially the OpenOCD script would benefit from, but I don't feel comfortable making so many changes that are somewhat hard to test (OpenOCD is used by much more platforms than I can test) and it is beyond what I originally tried to achieve 😅 For the time being, I will create a PR with the quick fix for |
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:
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.
On the left side, the UICR is shown before enabling the pinreset and on the right side it is shown after the pinreset.
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 callnrfjprog --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:
JLINK_POST_FLASH
define for dist/tools/jlink.sh, that writes the right values into the UICR. So far nobody seems to useJLINK_POST_FLASH
for anything.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:
We can check the burn file that is created by makefiles/tools/jlink.inc.mk has the right post-flash operation:
HOWEVER when I add
JLINK_POST_FLASH = Write4 0x10001200 00000012 00000012
to the boards/nrf52840dk/Makefile.include and just callBOARD=nrf52840dk make flash term
, it does not work. What's odd though is that it does work when I callJLINK_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 addingJLINK_PRE_FLASH=''
or similar to the command line, ther
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
The text was updated successfully, but these errors were encountered: