square / pylink

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

Support for Segger Flasher #99

Open kettenbach-it opened 3 years ago

kettenbach-it commented 3 years ago

Would it be possible to implement support for the "Segger Flasher" in this software?

The Segger Flasher works differently from the Segger JLink: the hex file to be flashed is stored to the Flasher and then the flash process is triggered. In this way, the Segger Flasher can program various chips that the JLink cannot.

I'd be willing to help, though I'd need some assistance.

kettenbach-it commented 3 years ago

I've looked into the code and I've seen, that the way I described the Segger Flasher, the PyLink code already works......

hkpeprah commented 3 years ago

Would flash_file() address what you are trying to do here?

kettenbach-it commented 3 years ago

Let me explain:

I'm using flash_file() with Segger Tools 7.20a and Segger Jlink to successfully flash a nordic nRF52832 chip.

Now I want to flash PIC18F87K22. Segger says, that this PIC18 chip is supported if I use Segger Flasher (another Emu, more expensive than JLink) instead of JLink and a tool called "Universal Flasher" instead of JFlash or pylink.flash_file()

Since "Universal Flasher" is a crappy QT-GUI with no CLI etc. it doesn't solve my problem and I'd rather want to use Pylink to do the job, since I want to do automatic testing of hardware during CI/CD pipelines.

I asked Segger, if there's a possibility to use Python to flash the PIC18 and they say, that this is possible if I buy the "SDK". Well, as far as I can see, the "SDK" is just the documentation and the header files of the libjlinkarm[dylib|so|dll] that pylink already used to flash my Nordic chip.

Btw, the libjlinkarm is the same of the Software "Flasher" as well as for "JLink":

root@host: /opt/SEGGER>sha1sum  Flasher_V720a/libjlinkarm.so.7.20.1
2d9a03c05c854c95d33ce78ba13bf5b0211cb985  Flasher_V720a/libjlinkarm.so.7.20.1
root@host: /opt/SEGGER>sha1sum  JLink_V720a/libjlinkarm.so.7.20.1
2d9a03c05c854c95d33ce78ba13bf5b0211cb985  JLink_V720a/libjlinkarm.so.7.20.1

So I'm wondering how I could do the job with pylink.

If I do it the same way, that I use with the Nordic chip, I get:

pylink.errors.JLinkException: Unsupported device selected.

How do I make pylink behave like the "Universal Flasher" instead of JFlash?

hkpeprah commented 3 years ago

You might need to add support yourself. There is a documented process on their wiki outlining how to add support for an un-supported chip. I've not tried it myself, but it seems somewhat straightforward, and should just work if you follow their steps. I believe with the way the code works though, as outlined by someone else who had done this in the past, is that you will need to either create your own Library instance as to avoid the copy-behaviour of the underlying API, or pass the path yourself.

kettenbach-it commented 3 years ago

Mh, that's an interesting hint. The chip is already in an XML-file shipped with "Universal Flasher" but it's missing in the "JLinkDevices.xml" of JFlash. I'll see if I can hack something

kettenbach-it commented 3 years ago

@hkpeprah I played a bit with the JLinkDevices.xml and found that loading an alternative XML file via jlink.exec_command('JLinkDevicesXMLPath /my/own/JLinkDevices.xml') works for me in principle.

But this does not solve my actual problem. The reason is that the chip I would like to flash is not flashed with "JFlash", but with "Universal Flash Loader" not using JLink but using "Flasher Pro" as the hardware interface.

The "Universal Flash Loader" has its own XML files, which can be found in the Flasher Software and Documentation Pack in the directory "Devices_UNI". For my chip it looks like this:

  <Device>
    <ChipInfo Vendor="Microchip" Core="PIC18" Family="PIC18" Name="PIC18F87K22" Interface="LVP via ICSP"/>
    <FlashBankInfo Name="Application"   BaseAddr="0x00000000" Size="0x00020000" Sect="0x00002000" Blank="0xFF" Loader="PIC18FX7.PEX"/>
    <FlashBankInfo Name="ID register"   BaseAddr="0x00200000" Size="0x00000008" Sect="0x00000008" Blank="0xFF" Loader="PIC18FX7.PEX"/>
    <FlashBankInfo Name="Configuration" BaseAddr="0x00300000" Size="0x00000010" Sect="0x00000010" Blank="0xFF" Loader="PIC18FX7.PEX"/>
    <FlashBankInfo Name="EEPROM"        BaseAddr="0x00F00000" Size="0x00000400" Sect="0x00000400" Blank="0xFF" Loader="PIC18FX7.PEX"/>
    <Config Name="DeviceId" Value="0x51C0"/>
    <Config Name="ICSP_SPEED" Value="5000000">
      <Edit Style="Decimal" Min="10000" Max="10000000" Bytes="4"/>
    </Config>
  </Device>

The "Flash Loader" (PEX file) used by the "Universal Flash Loader", that is described in the link to the wiki you posted above and is referenced in above XML, can also be found there. It was built by Segger.

This is what the "Universal Flash Loader" looks like when I flash my chip with it:

image

image

There's another menu for selecting the flasher and another one for selecting the chip - that's all.

And here's it's output:

Download to Flasher.
Info: Preparing download to Flasher...
Info: Selected project file name "FLASHER.UNI"
Info: Selected data file: /root/VerA02.hex
Info: Selected target device: PIC18F87K22
Info: Opening flash loader: /opt/SEGGER/Flasher_V720a/Devices_UNI/FlashLoader/PIC18FX7.PEX
Connected to Emulator with S/N: 695000337
Info: Downloading (119832 bytes, CRC: 0x73D33CCD) ...
Connected to Emulator with S/N: 695000337
Info: Downloading (3936 bytes, CRC: 0x5B991457) ...
Connected to Emulator with S/N: 695000337
Info: Downloading (742 bytes, CRC: 0x02321EE8) ...
Download successful.

There seem to be three writes to the chip.

According to Segger, the functionality of "Universal Flash Loader" can also be replicated via the Segger API (DLL) and therefore in Python (they say).

Obviously, you have to choose a different procedure to flash this chip than is currently the case with Pylink. For example, you cannot access the devices in the DLL. When I copy the above XML for my chip into the JLInkDevices.xml given as JLinkDevicesXMLPathto Pylink, I get error messages by the DLL not being able to read this XML. The "Universal Flash Loader" seems to call the API without having a supported chip in the APIs XML, but in its own XML. If I modify Pylink, so it accepts no chip_name for flash_file(), a dialogue of the DLL raised, that the chip "UNSPECIFIED" is not supported. I have no clue how this is done by "Universal Flash Loader"

It would be conceivable, however, that e.g. a multiple flash_write() has to be done at different addresses given by the XML of the Flasher. So for pylink we would need to implement something like flash_universal(xml=..., flash_loader=....) which does those writes to the addresses in the XML using an API-call which does not need a chip_name.

I will talk to my team about whether we should continue here. We'd probably need to buy the SDK or get support from Segger how to do it - with the semi-legal publicly available PDF of the API, I wasn't able to find out how to do it.

What do you think?