square / pylink

Python Library for device debugging/programming via J-Link
https://pylink.readthedocs.io/en/latest/
Other
346 stars 127 forks source link

Flashing .hex files #157

Closed JonathanCBU closed 11 months ago

JonathanCBU commented 1 year ago

Hello,

I need to flash .hex files programmatically, and I am already using pylink for RTT viewer stuff so I'd like to keep using the same library.

Now, JFlashLite can flash a hex file using the GUI without any issue, but the flash_file method doesn't seem to work (I'm assuming that's because of the address encoding within hex files).

When attempting to flash using Jlink.flash_file(<hex_file>, 0) I see the UI appear, but it never moves past erasing, and it always crashes with JLinkFlashException: Programming error occured.

Is there a recommended method for flashing hex files? If not, Is the next best thing parsing the file and flashing it in byte chunks?

hkpeprah commented 1 year ago

You can use intelhex to read in the HEX file to a bytes array, then use .flash() to flash it:

import intelhex

ih = intelhex.IntelHex()
ih.fromfile('myfile.hex', format='hex')
data = ih.tobinarray()
JonathanCBU commented 1 year ago

Ahhh I see, and then I should be able to flash that whole set of data starting at adder 0?

hkpeprah commented 1 year ago

Yup!

JonathanCBU commented 1 year ago

That method definitely made a flash-able bin array (although I needed one more step of data_list = data.tolist()).

Unfortunately though, the .erase() function does not seem to reliably work reliably. It did work a few times, but I cannot pinpoint what is changing between attempts. Per this discussion I am making sure the Jlink is halted before erasing, but I do not always see that erasing happens.

Here is how I am setting up my Jlink.

import pylink
import intelhex

jlink = pylink.JLink()
jlink.open(<jlink_sn>)
jlink.set_tif(pylink.enums.JLinkInterfaces.SWD)
jlink.connect(<chip_name>)

ih = intelhex.IntelHex()
ih.fromfile(<hex_file>, format='hex')
data = ih.tobinarray()
d_list = data.tolist()

# in an python session I would confirm jlink.halted() returns true before continuing
jlink.halt()

current_mem = jlink.memory_read(0, len(d_list))

# here I would see the JLink UI flash on screen for less than a second and the function would return 0
jlink.erase() 

 # should be a list of 255 but instead returns the same thing as current_mem
erased_mem = jlink.memory_read(0, len(d_list))

# fails if erased_mem is not a list of 255 (fails with "ValueError: Invalid error code: -3")
jlink.flash(d_list, 0)

Note: The only times I have seen .erase() work I have had to run it twice and it still returned 0, but other times I have tried running it upwards of 10 times without seeing it work.

hkpeprah commented 1 year ago

Do you have the debugging logs? The logs that print to the Python logger? Sometimes, the CPU isn't halted properly due to something else on the device waking it up.