Programmatic reset of ARM Cortex-M4 through J-Link Plus

    This site uses cookies. By continuing to browse this site, you are agreeing to our Cookie Policy.

    • Programmatic reset of ARM Cortex-M4 through J-Link Plus

      I've written a custom manufacturing programming tool for ARM Cortex-M4 nRF52832 and nRF52810 devices. It uses a J-Link Plus USB programmer (J-Link V7.98g) and is implemented in Python using the Pylink package. The program configures J-Link to use SWD and connects to the target with chip_name 'nRF52832_xxAA' or 'nRF52810_xxAA', allowing the FICR device id and UICR information to be read.

      I have a problem resetting the processor programmatically from Python. The Pylink reset() function does something, but does not trigger required Cortex M4 normal (0) reset sequence (wiki.segger.com/J-Link_Reset_Strategies#Type_0:_Normal) and (wiki.segger.com/J-Link_script_files#Reset_sequences). I've tried setting the reset strategy through Pylink and through J-Link command strings (wiki.segger.com/J-Link_Command_Strings). Strangely, if my program exits and disconnects from the J-Link DLL while the J-Link is still physically connected, the correct target processor reset is triggered.

      I've seen that the J-Flash Start Application (F9) function performs a correct reset of the Cortex-M4 target processor, logging;
      - Reset: Halt core after reset via DEMCR.VC_CORERESET.
      - Reset: Reset device via AIRCR.SYSRESETREQ.
      These messages match those in the SEGGER example CortexM reset script (wiki.segger.com/images/8/86/Ex…ortexM_Normal.JLinkScript).

      The J-Link ARM DLL allows the reset behaviour to be customised by overriding the DLL ResetTarget() implementation with a script, but I have not been able to get this to work. It seems that should not be necessary if the J-Link DLL implements the normal Cortex M4 reset strategy.

      I haven't tried exec()'ing J-Flash or J-Commander from within my program to achieve the correct reset. I understand this would require a second connection to J-Link DLL which is not supported.

      Any help or advice on how to solve this would be appreciated.
    • After further investigation, I've confirmed that "nrfjprog --reset" is doing the same reset as J-Flash. I'm looking for the device to go into low power mode after programming (~2uA at 3v). It does after J-Flash (F9) but not after my programmatic reset.

      The difference seems to be that my application has the J-Link DLL open (pylink.readthedocs.io/en/lates…l#pylink.jlink.JLink.open) while performing the reset. The reset occurs, but the J-Link DLL then forces the device back to a higher power state (~3mA at 3v). If the program closes the J-Link DLL before reset, the low power state is achieved. If I close my Python application while the J-Link probe is connected, the device is automatically reset and drops into the low power state.

      I do not think this is a Pylink issue. I can recreate the same effect using J-Flash and J-Link. I think the J-Link DLL behaviour is the root cause, but that J-Flash operates in such a way as to avoid or workaround the behaviour.
      I believe I can now refactor my Python application to work around the J-Link DLL behaviour. I'll post here with the outcome once I've confirmed that.
    • Running with J-Link v7.98g software and a J-Link Plus USB probe S/N 601006986 and nrfjprog 10.24.0

      Test 1;
      1) Connect J-Link Plus to target device (with a Laird BL652)
      2) Start J-Flash, open nRF52832_xxAA device, SWD speed 4000
      3) Erase chip, program & verify application (device uses ~3.2mA at 3v)
      4) Close J-Flash (device is not reset and now uses ~5.4mA at 3v)
      5) Run J-Link and execute reset script (device resets and drops to ~32uA at 3v).
      6) Disconnect J-Link Plus from target device (device uses ~2.0uA at 3v)

      It requires a separate reset for the flashed application to run and the device to enter its low power state. The low power state is also achieved if I use the J-Flash Start Application (F9) function before closing J-Flash.

      Test 2;
      1) Connect J-Link Plus to target device
      2) Start J-Flash, open nRF52832_xxAA device, SWD speed 4000
      3) Erase chip, program & verify application (device uses ~3.2mA at 3v)
      4) Run J-Link and execute reset script (device resets, but still uses ~3.2mA at 3v).
      5) Close J-Flash (device uses ~5.4mA at 3v)
      6) Disconnect J-Link Plus from target device (device uses ~2.0uA at 3v)

      Test 3;
      1) Connect J-Link Plus to target device
      2) Start J-Flash, open nRF52832_xxAA device, SWD speed 4000
      3) Erase chip, program & verify application (device uses ~3.2mA at 3v)
      4) Run nrfjprog --reset (device resets and drops to ~28uA at 3v).
      5) Close J-Flash. J-Link Error "Could not start CPU core" reported (device does not reset and remains using ~28uA at 3v)
      6) Disconnect J-Link Plus from target device (device uses ~2.0uA at 3v)

      The J-Flash behaviour on exit changes depending on whether J-Link has run while it is open. In Test 1, J-Flash does not reset the processor on exit and leaves it in a abnormal high power state. In Test 2, the J-Link reset does not achieve the low power state, but J-Flash does then reset the processor on exit.

      I believe this inconsistent behaviour is somehow caused by the JLinkARM DLL as I see similar issues when using it through Pylink.

      J-Link reset script
      Device nRF52832_xxAA si SWD speed 4000 reset go exit
    • I've confirmed that I can work around the issue using Pylink's open(), connect(), read(), close() operations each time I need to use the J-Link API. In hindsight, the lack of a J-Link disconnect() operation should have been a red flag as well as the target_connected() call only returning the true state immediately after connect().

      My program can now poll the J-Link interface to determine if a target device is connected or not, and to read the device details and FICR identity. After close() the device returns to the expected low power state.