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 and (wiki.segger.com/J-Link_script_files. 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'm exec()'ing nrfjprog to program the application code and UICR. I tried using --reset, --pinreset and --hardreset to reset the processor, but these do not perform the same reset as J-Flash. The board pulls the nRF52 Reset pin high, so perhaps none of these methods can work.

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/.../Example_Reset_CortexM_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.

  • Hi,

     

    I'm exec()'ing nrfjprog to program the application code and UICR. I tried using --reset, --pinreset and --hardreset to reset the processor, but these do not perform the same reset as J-Flash. The board pulls the nRF52 Reset pin high, so perhaps none of these methods can work.

    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.

    reset via AIRCR is a so-called softreset, and can be triggered via "--debugreset" to nrfjprog. Could you try this one and see if that works better?

    That should be equal to this reset type: https://wiki.segger.com/J-Link_Reset_Strategies#Type_0:_Normal

     

    Kind regards,

    Håkon

  • Thank you for the quick response and suggestions Håkon. 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/.../pylink.html 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 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.

    Please let me know if you have any further comments. 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.

  • Hi,

     

    Reset and halt will stop the CPU, thus causing a higher current consumption.

    However; a debug reset / soft reset / pin-reset will cause the cpu to run, so the current consumption heavily depends on what is actually programmed into the nRF itself.

     

    Another scenario can be that the debugger interface is kept on, which causes a >1.2 mA floor current, and it highly depends on what the debugger is doing at this point in time. Having the probe actively connected (ie. not close the connection) will likely keep the debugger IF active.

     

    Since you mention 3 mA, it can also be caused by the firmware running on your device, provided that the debug IF is indeed closed at this point in time.

    Try attaching a debug session to the currently active solution to see if the nRF is stuck on executing a certain function/loop, like explained here:

     RE: How Can I Attaching to a Running Target(52832) with J-Link 

     

    Kind regards,

    Håkon

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

  • Hi,

     

    jonestn said:

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

    Great to hear that you were able to work around the issue. Hope you have a wonderful day!

     

    Kind regards,

    Håkon

Related