This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts

nRF9160 CTRL-AP access using J-Link Commander/GDB

I've managed to find some magic numbers/commands for working with nRF5x devices using the CTRL-AP interface, but having no such luck with the commands on an nRF9160. I've tried (using J-Link Commander):

J-Link>connect
Please specify device / core. <Default>: CORTEX-M33
Type '?' for selection dialog
Device>
Please specify target interface:
J) JTAG (Default)
S) SWD
T) cJTAG
TIF>
Device position in JTAG chain (IRPre,DRPre) <Default>: -1,-1 => Auto-detect
JTAGConf>
Specify target interface speed [kHz]. <Default>: 4000 kHz
Speed>
Device "CORTEX-M33" selected.


Selected interface (JTAG) is not supported by the connected probe.
J-Link>SWDSelect
Select SWD by sending SWD switching sequence.
Found SWD-DP with ID 0x6BA02477
J-Link>SWDWriteDP 1 0x50000000
Write DP register 1 = 0x50000000
J-Link>SWDWriteDP 2 0x01000000
Write DP register 2 = 0x01000000
J-Link>SWDWriteAP 1 0x00000001
Write AP register 1 = 0x00000001
J-Link>SWDReadAP 2
Read AP register 2 = 0x02000000
J-Link>SWDReadAP 2
Read AP register 2 = 0x00000000

Is there something different to be done on the nRF9160? I would have thought that, after having done the above, the device would have performed a mass erase of its flash.

The nRF9160 has sections on using things like the "mailbox" interface with CTRL-AP, but little to absolutely no examples/documentation on opening a terminal and actually using it (that I've found, anyway).

  • Hi,

     

    The algorithm is slightly changed, as the nRF9160 reset behavior is changed on the SWJ-DP compared to nRF52-devices:

    https://infocenter.nordicsemi.com/topic/ps_nrf9160/pmureset.html?cp=2_0_0_4_0_4_7#reset_behaviour

    https://infocenter.nordicsemi.com/topic/ps_nrf52840/power.html?cp=4_0_0_4_2_5_7#concept_res_behav 

     

    *Updated script* Could you try this script?

    SWDSelect   // Activate SWD
    SWDWriteDP 1 0x50000000  // Enable debug power
    SWDWriteDP 2 0x04000000  // Selects the 0x04XXXXXX Access Port and 0xXXXX00XX Register bank in the access port
    SWDWriteAP 1 0x00000001  // CTRL-AP Bank 0, register offset 1 (ERASEALL 0x004): Erase all command
    
    SWDReadAP 2 // CTRL-AP Bank 0, register offset 2 (ERASEALLSTATUS 0x008): Erase all command status
    SWDReadAP 2 // Must read twice to get the value.
    
    // Wait a good amount of time, so eraseall process is done.
    sleep 500
    
    // Perform a pin reset
    r0
    sleep 10
    r1
    sleep 10
    
    SWDSelect   // Activate SWD
    SWDWriteDP 1 0x50000000  // Enable debug power
    SWDWriteDP 2 0x04000000  // Selects the 0x04XXXXXX Access Port and 0xXXXX00XX Register bank in the access port
    
    SWDReadAP 3 // CTRL-AP Bank 0, register offset 3 (APPROTECTSTATUS 0x00C): Access port protection status
    SWDReadAP 3 // //Second read returns the value: 0: enabled 1: not enabled
    
    exit

     

    Kind regards,

    Håkon

  • Okay, that does seem to work!

    From what I can gather with testing your steps, the first SWDWriteAP 1 0x0000001 doesn't do anything, right? It seems I need to do the two WriteDP steps, reset with r0+r1, and then do the WriteDP steps again and *then* WriteAP 1... works. Skipping the first WriteAP 1 results in the same thing: the part being erased during the two ReadAP 3 steps.

    If I wanted to read a single word from the mailbox, would I need to do the same thing, but replace WriteAP 1 with ReadAP 8? Doing that returns 0xFFFFFFFE right now, which might be because my steps are wrong or my firmware isn't properly writing to the mailbox; it'd just be nice to know if it's likely to be one or the other.

    Thanks!

  • Hi,

     

    In combination with R&D, I have an updated the original post, with comments on what is written/read etc.

    There was some errors in the original script, where the actual erase happened last.

      

    erik.johnson said:
    If I wanted to read a single word from the mailbox, would I need to do the same thing, but replace WriteAP 1 with ReadAP 8? Doing that returns 0xFFFFFFFE right now, which might be because my steps are wrong or my firmware isn't properly writing to the mailbox; it'd just be nice to know if it's likely to be one or the other.

    Reading SWD registers must be done with two commands, similar to how reading over I2C works. Each bank has 8 registers (0 to 7). 

    Kind regards,

    Håkon

  • Looks like the erase process does occur on the first time through. I'm not sure exactly what was happening that made me think it needed to be on the second one... I think I might not have done the SWDReadAP 2 after the write attempt, which seems to be necessary in order to trigger the erase.

    Does the index math for the various registers always use the offset value, or is it an index in the list of registers in section 9.2.5? That is, if I wanted to write to the ERASEPROTECT.DISABLE register, do I use 0x1C = 28, 28/4 = 7, or is it register 5 because it's the fifth in the list? Just want to be sure, since I'm not having success initiating the mass erase with my nRF9160 (which is writing 0x12345678 to its ERASEPROTECT.DISABLE register).

    Is the byte order still the same endianess? That is, I should be doing:

    SWDWriteAP 7 0x12345678

    and not:

    SWDWriteAP 7 0x78563412

    correct?

    Is there a time or try limit to writing to that register? As in, if I write the wrong value, will I need to power cycle the device and try again? Or can I sort of brute force the value and still have it work? Should I be doing a read of register ERASEALLSTATUS after writing to the DISABLE register to trigger the mass erase?

    Thanks for the help so far!

  • I also am not even able to write from the debugger to MAILBOX.TXDATA:

    J-Link>SWDSelect
    Select SWD by sending SWD switching sequence.
    Found SWD-DP with ID 0x6BA02477
    J-Link>SWDWriteDP 1 0x50000000
    Write DP register 1 = 0x50000000
    J-Link>SWDWriteDP 2 0x04000000
    Write DP register 2 = 0x04000000
    J-Link>SWDWriteAP 8 0x12345678
    Write AP register 8 = 0x12345678 ***ERROR

    The register address is 0x020 = 32, 32/4 = 8.

    Do I need to be selecting a different register bank than 0 or something?

Related