NRF52 RBP (Readback protection) unexpected behavior

We are currently going in production with NRF52 and we are facing the following issue with RBP on NRF52832QFAAB0.

Basically looks like the processor enters an unknown state when RBP command is issued to it.

Here are the steps I take to reproduce the problem:

  1. "nrfjprog -f nrf52 --recover --log" for a clean starting state.
  2. "nrfjprog -f nrf52 --program programRev4.hex --verify -r --log" to program the board. At this point my program is running and I can verify by looking at advertising data on BLE.
  3. "nrfjprog -f nrf52 --rbp ALL --log" stops the device from advertising. Looks like it stops my program from running.
  4. Issuing a "nrfjprog -f nrf52 --reset" command (Although it reports that "the operation attempted is unavailable due to readback protection") is the only way i can get my program running. Clearly the SWD port is still open for this command to succeed. Although this seems like the solution, i would still like to know why the device halts after issuing the RBP command (step 3)

My understanding was that --rbp ALL only writes to the APPPROTECT register and that locks access to SWD port. Is that correct or are there other things that it does, possibly causing the processor core to lock up and stop the program from running?

Please find the nrfjprog log attached (i ran all commands with --log option).

log_rbp.log
--------------------------------------------------------------------------------
nrfjprog -f nrf52 --recover --log
nrfjprog verion 9.7.2
--------------------------------------------------------------------------------
FUNCTION: open_dll.
FUNCTION: open_dll.
FUNCTION: enum_emu_snr.
FUNCTION: enum_emu_snr.
FUNCTION: enum_emu_snr.
FUNCTION: enum_emu_snr.
FUNCTION: connect_to_emu_without_snr.
FUNCTION: connect_to_emu_without_snr.
FUNCTION: enum_emu_snr.
Device "NRF52832_XXAA" selected.
FUNCTION: recover.
FUNCTION: recover.
Found SW-DP with ID 0x2BA01477
Found SW-DP with ID 0x2BA01477
Scanning AP map to find all available APs
AP[2]: Stopped AP scan as end of AP map has been reached
AP[0]: AHB-AP (IDR: 0x24770011)
AP[1]: JTAG-AP (IDR: 0x02880000)
Iterating through AP map to find AHB-AP to use
AP[0]: Core found
AP[0]: AHB-AP ROM base: 0xE00FF000
CPUID register: 0x410FC241. Implementer code: 0x41 (ARM)
Found Cortex-M4 r0p1, Little endian.
FPUnit: 6 code (BP) slots and 2 literal slots
CoreSight components:
ROMTbl[0] @ E00FF000
ROMTbl[0][0]: E000E000, CID: B105E00D, PID: 000BB00C SCS-M7
ROMTbl[0][1]: E0001000, CID: B105E00D, PID: 003BB002 DWT
ROMTbl[0][2]: E0002000, CID: B105E00D, PID: 002BB003 FPB
ROMTbl[0][3]: E0000000, CID: B105E00D, PID: 003BB001 ITM
ROMTbl[0][4]: E0040000, CID: B105900D, PID: 000BB9A1 TPIU
ROMTbl[0][5]: E0041000, CID: B105900D, PID: 000BB925 ETM
Reset: Halt core after reset via DEMCR.VC_CORERESET.
Reset: Reset device via AIRCR.SYSRESETREQ.
Reset: Halt core after reset via DEMCR.VC_CORERESET.
Reset: Reset device via AIRCR.SYSRESETREQ.
FUNCTION: close_dll.
FUNCTION: close_dll.
--------------------------------------------------------------------------------
nrfjprog -f nrf52 --program programRev4.hex --verify -r --log
nrfjprog verion 9.7.2
--------------------------------------------------------------------------------
FUNCTION: open_dll.
FUNCTION: open_dll.
FUNCTION: enum_emu_snr.
FUNCTION: enum_emu_snr.
FUNCTION: enum_emu_snr.
FUNCTION: enum_emu_snr.
FUNCTION: connect_to_emu_without_snr.
FUNCTION: connect_to_emu_without_snr.
FUNCTION: enum_emu_snr.
Device "NRF52832_XXAA" selected.
FUNCTION: read_device_version.
FUNCTION: read_device_version.
Found SW-DP with ID 0x2BA01477
Found SW-DP with ID 0x2BA01477
Scanning AP map to find all available APs
AP[2]: Stopped AP scan as end of AP map has been reached
AP[0]: AHB-AP (IDR: 0x24770011)
AP[1]: JTAG-AP (IDR: 0x02880000)
Iterating through AP map to find AHB-AP to use
AP[0]: Core found
AP[0]: AHB-AP ROM base: 0xE00FF000
CPUID register: 0x410FC241. Implementer code: 0x41 (ARM)
Found Cortex-M4 r0p1, Little endian.
FPUnit: 6 code (BP) slots and 2 literal slots
CoreSight components:
ROMTbl[0] @ E00FF000
ROMTbl[0][0]: E000E000, CID: B105E00D, PID: 000BB00C SCS-M7
ROMTbl[0][1]: E0001000, CID: B105E00D, PID: 003BB002 DWT
ROMTbl[0][2]: E0002000, CID: B105E00D, PID: 002BB003 FPB
ROMTbl[0][3]: E0000000, CID: B105E00D, PID: 003BB001 ITM
ROMTbl[0][4]: E0040000, CID: B105900D, PID: 000BB9A1 TPIU
ROMTbl[0][5]: E0041000, CID: B105900D, PID: 000BB925 ETM
FUNCTION: readback_status.
FUNCTION: readback_status.
FUNCTION: read.
FUNCTION: read.
FUNCTION: read.
FUNCTION: read.
FUNCTION: read.
FUNCTION: read.
FUNCTION: read.
FUNCTION: read.
FUNCTION: read.
FUNCTION: read.
FUNCTION: read.
FUNCTION: read.
FUNCTION: power_ram_all.
FUNCTION: power_ram_all.
FUNCTION: read_region_0_size_and_source.
FUNCTION: read_region_0_size_and_source.
FUNCTION: disable_bprot.
FUNCTION: disable_bprot.
Reset: Halt core after reset via DEMCR.VC_CORERESET.
Reset: Reset device via AIRCR.SYSRESETREQ.
FUNCTION: write.
FUNCTION: write.
FUNCTION: write.
FUNCTION: write.
FUNCTION: write.
FUNCTION: write.
FUNCTION: write.
FUNCTION: write.
FUNCTION: write.
FUNCTION: write.
FUNCTION: write.
FUNCTION: write.
FUNCTION: is_qspi_init.
FUNCTION: is_qspi_init.
FUNCTION: read.
FUNCTION: read.
FUNCTION: read.
FUNCTION: read.
FUNCTION: read.
FUNCTION: read.
FUNCTION: read.
FUNCTION: read.
FUNCTION: read.
FUNCTION: read.
FUNCTION: read.
FUNCTION: read.
FUNCTION: is_qspi_init.
FUNCTION: is_qspi_init.
FUNCTION: sys_reset.
FUNCTION: sys_reset.
Reset: Halt core after reset via DEMCR.VC_CORERESET.
Reset: Reset device via AIRCR.SYSRESETREQ.
FUNCTION: go.
FUNCTION: go.
FUNCTION: close_dll.
FUNCTION: close_dll.
--------------------------------------------------------------------------------
nrfjprog -f nrf52 --rbp ALL --log
nrfjprog verion 9.7.2
--------------------------------------------------------------------------------
FUNCTION: open_dll.
FUNCTION: open_dll.
FUNCTION: enum_emu_snr.
FUNCTION: enum_emu_snr.
FUNCTION: enum_emu_snr.
FUNCTION: enum_emu_snr.
FUNCTION: connect_to_emu_without_snr.
FUNCTION: connect_to_emu_without_snr.
FUNCTION: enum_emu_snr.
Device "NRF52832_XXAA" selected.
FUNCTION: read_device_version.
FUNCTION: read_device_version.
Found SW-DP with ID 0x2BA01477
Found SW-DP with ID 0x2BA01477
Scanning AP map to find all available APs
AP[2]: Stopped AP scan as end of AP map has been reached
AP[0]: AHB-AP (IDR: 0x24770011)
AP[1]: JTAG-AP (IDR: 0x02880000)
Iterating through AP map to find AHB-AP to use
AP[0]: Core found
AP[0]: AHB-AP ROM base: 0xE00FF000
CPUID register: 0x410FC241. Implementer code: 0x41 (ARM)
Found Cortex-M4 r0p1, Little endian.
FPUnit: 6 code (BP) slots and 2 literal slots
CoreSight components:
ROMTbl[0] @ E00FF000
ROMTbl[0][0]: E000E000, CID: B105E00D, PID: 000BB00C SCS-M7
ROMTbl[0][1]: E0001000, CID: B105E00D, PID: 003BB002 DWT
ROMTbl[0][2]: E0002000, CID: B105E00D, PID: 002BB003 FPB
ROMTbl[0][3]: E0000000, CID: B105E00D, PID: 003BB001 ITM
ROMTbl[0][4]: E0040000, CID: B105900D, PID: 000BB9A1 TPIU
ROMTbl[0][5]: E0041000, CID: B105900D, PID: 000BB925 ETM
FUNCTION: readback_protect.
FUNCTION: readback_protect.
FUNCTION: connect_to_emu_with_snr.
FUNCTION: connect_to_emu_without_snr.
FUNCTION: enum_emu_snr.
Device "NRF52832_XXAA" selected.
FUNCTION: close_dll.
FUNCTION: close_dll.
--------------------------------------------------------------------------------
nrfjprog -f nrf52 -r --log
nrfjprog verion 9.7.2
--------------------------------------------------------------------------------
FUNCTION: open_dll.
FUNCTION: open_dll.
FUNCTION: enum_emu_snr.
FUNCTION: enum_emu_snr.
FUNCTION: enum_emu_snr.
FUNCTION: enum_emu_snr.
FUNCTION: connect_to_emu_without_snr.
FUNCTION: connect_to_emu_without_snr.
FUNCTION: enum_emu_snr.
Device "NRF52832_XXAA" selected.
FUNCTION: read_device_version.
FUNCTION: read_device_version.
FUNCTION: close_dll.
FUNCTION: close_dll.

Parents
  • My experience is with the nRF52840 rather than the NRF52832QFAAB0, but I think the devices are similar.  The comments here relate to the nRF52840 and you can compare to see if they are relevant for your situation.

    Setting read back protection via the APPROTECT register only disables one component of debug port access.  The CTRL-AP port remains functional even when protected.  See 'Debug and Trace' section in the objective specification.  This makes sense, since there still needs to be functioning component accessible via SWD which is capable of accepting an ERASEALL type command to unprotect the unit.  The CTRL-AP is also capable of issuing device resets.

    I've attempted to perform a similar process for setting APPROTECT for production and the following procedure works for me when using the Python pynrfjprog API.

    # Start the processor before applying readback protection so that CPU
    # is operational and running directly after protection is applied.
    self.nrfjprog.halt()
    self.nrfjprog.debug_reset()
    self.nrfjprog.go()
    
    self.nrfjprog.readback_protect(API.ReadbackProtection.ALL)
    self.nrfjprog.pin_reset()

Reply
  • My experience is with the nRF52840 rather than the NRF52832QFAAB0, but I think the devices are similar.  The comments here relate to the nRF52840 and you can compare to see if they are relevant for your situation.

    Setting read back protection via the APPROTECT register only disables one component of debug port access.  The CTRL-AP port remains functional even when protected.  See 'Debug and Trace' section in the objective specification.  This makes sense, since there still needs to be functioning component accessible via SWD which is capable of accepting an ERASEALL type command to unprotect the unit.  The CTRL-AP is also capable of issuing device resets.

    I've attempted to perform a similar process for setting APPROTECT for production and the following procedure works for me when using the Python pynrfjprog API.

    # Start the processor before applying readback protection so that CPU
    # is operational and running directly after protection is applied.
    self.nrfjprog.halt()
    self.nrfjprog.debug_reset()
    self.nrfjprog.go()
    
    self.nrfjprog.readback_protect(API.ReadbackProtection.ALL)
    self.nrfjprog.pin_reset()

Children
  • Austin,

    Thanks for the info. However I still want to understand why writing to readback protect (sometimes) causes my program to halt or stop from running. I couldn't find an answer to that in your response.

    And because you have a pin reset following your RBP you haven't noticed this issue.

    Although I can confirm at my desk that having the reset after the RBP will recover the device, I need someone from the Nordic design team to explain how setting the RBP might affect the program running in the core, possibly.

  • One way that setting RBP might affect the running program is due to timing for flash writing.  The NVM controller will need to be active to write RBP in flash and this could conflict with uses of the NVM controller in your own application.  Additionally, if you're running the SoftDevice during programming of RBP, since the SoftDevice is no longer in control of flash writes made through the SWD port, timing constraints within the SoftDevice may no longer be met and cause a fault.  The SoftDevice usually carefully times flash writes with knowledge of other events in the system, but it cannot control writes from external interfaces like SWD.

    Nordic engineers may have more suggestions.

Related