While doing an electronic project in MPLAB, I found it necessary to create an unique serial number for each device I program in order to have a proper USB functionality. Something as simple and often needed as this has to be already solved. Or so I thought.
Oh, I found solutions and solutions for this particular issue. Most of them were only useful with their device programmers - and I wanted something to work inside of MPLAB. Some other worked by modifying source code - a big no-no when you do source control. Some required serial number placed at an exact location - annoying (and volatile) to calculate in my case because USB serial number is a part of a bigger structure. Commercial solutions were also out of question... With each visited link I grew more firm in decision to roll out my own ("me hammer, problem nail" approach).
However, simple replacement is not necessarily an easy thing to do. You see, in world of microcontrollers Intel Hex format is the ruler. Without getting into details, format has two characteristics that make it suitable for firmwares. It splits data into fixed length blocks which is really nice when you have to do chip programming in blocks. Additionally every row is checksumed so data corruption can be avoided. Both those characteristics conspire against us to do simple file change. Not only that we cannot just simply change data because of checksum but we often cannot even simply find it because it can span across the rows.
So, it was a scripting time. Because of annoyingly difficult parsing, simple CMD was out of question. Only other choices were PowerShell or a completely custom program. While custom program would probably offer easiest development, I didn't want to embed only executable. And embedding sources would mean that I would need Visual Studio on each machine I want to compile this at - to high cost in practicality. Only other choice really was PowerShell - environment that exists on every Windows 7 and higher machine.
Requirements were straightforward. I wanted something that would be a single call (Microchip's MPLAB can call only single external build command). It had to replace file in-place (so that I could continue using PICkit 3 programming procedure). It had to change file as little as possible (e.g. by not removing extra headers). It had to support ASCII random (USB MSD specifications). And, lastly, it had to be capable of producing a valid output hex without checksum shenanigans.
I won't dwelve into boring details and explain each part of code but it suffices to say that it loads whole file in memory, searches for placeholder and then replaces that placeholder with random value, adjusting the checksum as it goes. End result is the file that gets pushed onto the device.
Here is an example command (Project Properties
, Conf
, Building
, Execute this line after build
):
PowerShell.exe -ExecutionPolicy RemoteSigned -File ${ProjectDir}\..\Setup\HexReplace.ps1 ${ProjectDir}\dist\default\production\Source.production.hex 197901281815 -AsciiHexRandom -Destination2 ${ProjectDir}\..\Binaries\TmpUsb.hex
First part we might as well ignore because it is only preparing terrain for script by calling PowerShell. First meaningful argument is a location of an intermediate Intel hex file followed by a placeholder value. Since my device is USB based, I opted to have a valid serial number (197901281815
) as a placeholder - makes live easier if script fails. Most common approach is to use something that won't appear by accident (various number of X characters seem to be popular choice). Anything unique will do.
Switch AsciiHexRandom
ensures that our randomness will be limited to numbers 0 to 9 and letters A to F, as required by MSD Bulk Only Transport 1.0 specification. If that parameter gets omitted random binary (0 to 255) will be used. Which one is better actually depends on your use case.
Last pièce de résistance is -Destination2
argument. That ensures script will not only change file but additionally copy it to a different place. It is not strictly necessary but I find it useful for archiving purposes. You can omit it without any consequence.
And that is my way of generating random serial number from within MPLAB project. Try it out and see whether it fits your needs.
PS: Script itself was not designed but grown. As such it is full of unoptimized code (just check function that does replacement) and it treats memory as kids treat candy. But realistically we are speaking about file that won't be bigger than couple hundreds KB in the worse case scenario. I could not justify spending time I would need to make it "proper" when it already runs (unoptimized) within a fraction of a second.
PPS: Yes, I have cheated by embedding C# code inside of PowerShell.
PPPS: If something goes wrong, add -debug
argument. That will give you a bit more information to go with.