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 (https://wiki.segger.com/J-Link_Reset_S…#Type_0:_Normal) and (https://wiki.segger.com/J-Link_script_files#Reset_sequences). I've tried setting the reset strategy through Pylink and through J-Link command strings (https://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 (https://wiki.segger.com/images/8/86/Ex…mal.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 (https://pylink.readthedocs.io/en/latest/pyli…link.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_xxAAsi SWDspeed 4000resetgoexit

  • 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.

Participate now!

Don’t have an account yet? Register yourself now and be a part of our community!