Automating linker configuration in IAR Embedded Workbench - linker

I am working on a firmware project in which i have to do a crc16 check for flash integrity.
The crc is calculated using IAR Xlink linker and kept at the end of the flash. Again crc is calculated at run time from the code and compared with the stored value in the flash to check integrity. However, we can only calculate crc on the code segment of the flash memory. It's size may change whenever we make some changes in the code. Can i automate this process which i am manually doing right now?
from the .xcl linker file:
// ---------------------------------------------------------
// CRC16 Essentials: -H for fill,-J for checksum calculation
// ---------------------------------------------------------
-HFF
-J2,crc16,,,CHECKSUM2,2=(CODE)5C00-FF7F;(CODE)10000-0x20A13
Here i need to change the end value of second code segment which is 0x20A13 right now.
I get this value from the .map file, i.e on how much memory range my code is residing inside the flash.
This is the 1st change i make.
Here i need to make 2nd change from code:
sum = fast_crc16(sum, 0x5C00, 0xFF7F-0x5C00+1);
sum = fast_crc16(sum, 0x10000,0x20A13-0x10000+1);
//Check the crc16 values
if(sum != __checksum)
{
// Action to be taken if checksum doesn't match
}
Please help automating this process!!

You can try to use the __segment_begin and __segment_size or __segment_end intrinsics in IAR which are explained in the "C/C++ Compiler Reference Guide", which you can get to from your Help menu in IAR EW430. The manual says they work with segments defined in the linker file, and plenty of the people around the internet seem to be using it like that, but I tried and got compiler errors (IAR EW430 5.40.7). If that is somehow broken you might want to report it to IAR and get a fix (assuming you have a support contract).
You can use them like this:
sum = fast_crc16(sum, __segment_begin("CODE"), __segment_size("CODE"));
I don't know what happens with split segments. But why would you exclude your reset vectors from your checksum calculation? You could just go from the start of CODE to the end and include the reset vectors.
I guess you could structure your code like this:
sum = fast_crc16(sum, __segment_begin("CODE"), (char *)__segment_begin("INTVEC") - (char *)__segment_begin("CODE") + 1);
sum = fast_crc16(sum, 0x10000, (char *)__segment_end("CODE") - 0x10000);
Also, you may or may not have noticed that the __checksum variable is put into memory wherever it fits. I found it lurking after my DATA16_ID segment, which put it right in the middle of the range of my checksum code, and I did not know of a way to automate skipping sections of memory for the checksum calculation. What I did was forced __checksum to the first two bytes in flash by defining a segment for those first two bytes and putting it in there.
Edit: Missed the first change. If you are manually adjusting the range of the IAR linker checksum routine then to be able to use the segment intrinsics from the compiler your would need to define a custom segment that uses the end of your code in your linker.
I don't know if there's any way to automate that. You might need to compile your code twice (ugh) once with the segment unlimited to get the end of the code, then use a script to extract the end of code and then update a linker script. You could probably run the initial build on a pre-build command line event and just build the IAR project with an unrestricted linker file. But that seems pretty ugly.

Perhaps you can also change your solution to build the crc over the complete flash reserved for the application, not only for the used part.
Then you never need to change your linker file nor your c-code, and even a bootloader could calculating the crc without knowledge about the actual size of the application.

Related

Creating different versions of .bin file in stm32cubeide

Context
I'm currently working on a firmware for a STM32F411CEU6, using STM32CubeIDE, I'm going to be programming several UC's, everyone of them is going to have an ID (a 32 bit unsigned number), this number is static and it will never be change in his lifespan, we are a small team but maybe we will have to program a few hundred of these devices, so changing the value associated whit that ID in the code manually will be kinda exhausting, and time consuming, so, my question is:
¿Is there a way to compile different versions of firmware so it generate several .bin files, each one whit the only difference that this single constant change?
¿Is there a way to automate this process?
What have I thought
I have thought on defining this constant (and other constants if I have to) on a header file, then use something like Python to make different versions of the code, but then I would have to open every project or workspace and still have to compile and produce every .binfile manually, ¿Is there a way to produce the .bin file from python (using the STM32CubeIDE), or something like that?
Additional information
Working on a STM32F411CEU6
Using STM32CubeIDE
I have basic knowledge in python C++
Medium-advance knowledge in C
Thanks in advance!
Any help would be very much appreciated
Here are a few ideas.
The STM32F411 chip is pre-programmed (by STMicro at the factory) with a 96-bit unique device ID. Perhaps you can use the device's unique ID for your purposes rather than creating and assigning your own ID value. See Section 24.1 of the reference manual. This seems much safer than trying to create and manage a different bin file for each ID value.
If you really want your own custom ID value, then program the ID value separately from the firmware bin file so that you don't need to create/manage different bin files for each unit. Write the program so that the ID value is at a known fixed address in ROM. Use the linker scatter file to reserve that address for the ID value. Program the ROM of each unit in two steps, the bin file and the ID value.
If you really want to incorporate the ID value into the bin file then you can use a tool such as srec_cat.exe to concatenate bin (also hex or srec) files. It's very versatile and you should study the man page. One example of how you could use this tool is this: In the source code for your program, declare your unique ID value a constant pointer to a constant value located at a fixed address in ROM beyond the end of the ROM consumed by the bin file. Build the bin file like normal. Then run srec_cat.exe to concatenate the unique ID value to the bin file with the appropriate offset. You could write a script to do this repeatedly for each unique ID value. Perhaps this script runs as a post-build action from the IDE. This solution could work but it seems like a maintenance nightmare to ensure the right bin file gets programmed onto the right device.
If using a hex file is an option, you could avoiding the need for re-compilation like so:
Reserve some flash space outside of your program (optionally configure the linker script to make sure no data is placed in that section).
Use a python script to generate intel hex data with the required ID placed in the reserved location.
Simply concatenate the two hex files and program as usual. I tested this with STM32 ST-LINK Utility / STM32CubeProgrammer.
To generate the hex data, you can use the intelhex package. For example:
import struct
from intelhex import IntelHex
from io import StringIO
ID_FLASH_ADDRESS = 0x8020000
hex_data = StringIO()
ih = IntelHex()
ih.puts(ID_FLASH_ADDRESS, struct.pack('<I', chip_id))
# Output data to variable
ih.write_hex_file(hex_data)
# Get the data
hex_data.getvalue().encode('utf-8')
Notes:
See the struct documentation for the meaning of '<I'.
I output the data to a variable, but you could also write directly to a file. See intelhex documentation.

How can I convert an .abs or .s19 to a C file?

I am trying to run some MC9S12DP256 example files, but I want to see the code to understand it. Are there any ways to convert a .s19 or .abs file to a C code?
An ".s19" or an ".abs" file contains mainly the machine code of the application. The source code of it is not included, independent of the language used to write it. Even if it were written in assembly language, all symbolic informations and comments are excluded.
However, you can try to de-compile the machine code. This is not a trivial or quick task, you need to know the target really well. I did this with software for other processors, it is feasible for code up to some KB.
These are the steps I recommend:
Get a disassembler and an assembler for the target processor, optimally from the vendor.
Let it disassemble the machine code into assembly source code. You might need to convert the ".s19" file into a binary file, one possible tool for this is "srecord".
Assemble the resulting source code again into ".s19" or ".abs", and make sure that it generates the same contents as your original.
Insert labels for the reset and interrupt entry points. Start at the reset entry point with your analysis.
Read the source code, think about what it does.
You will quickly "dive" into subroutines that execute small functions, like reading ADC or sending data. Place a label and replace the numerical value at the call sites with the label.
Expect sections of (constant) data mixed with executable code.
Repeat often from point 3. If you have a difference, undo your last step and redo it in another way until you produce the same contents.
If you want C source, it is commonly much more difficult. You need a lot of experience how C is compiled into machine code. Be aware that variables or even functions are commonly placed in another sequence than they are declared. If you want to go that route, you usually also have to use the exact version of the compiler used to generate the original machine code.
Be aware that the original might be produced with any other language.

Generating load time serial number for PCB application

I am trying to generate an incrementing value at load time to be used to "serialize" a PCB with a unique code value. Not an expert in ld or preprocessor commands, so looking for some help.
The value will be used in a unique ID for each board that the code is loaded on and will also be used as a counter for boards in the field.
I have no preconceived idea of how I might accomplish this, so any workable answer to get me started, including a pre-preprocessor macro is fine. In my olden days, I recollect adding a couple lines to the linker file that would accomplish this, but I have been unable to resurrect that information anywhere (including my brain's memory cells).
The simpler the answer, the better.
My solution to the problem was remarkably simple.
The binary contained
const char *serial = "XY-00000";
I then wrote a short program that boiled down to:
char uniqueserial [8];
/* Generate serial - this was an SQL call to the manufacturing DB */
char *array;
/* Read binary into array */
memcpy(memmem(array, "XY-00000",8), uniqueserial,8);
/* Write array to temp bin file for flashing */
Depends on the serial template string being unique in the binary. Use strings command to check. I disable crc protected object files due to taste. I like my embedded binaries being exact memory dumps.
The linker is not the right place for two reasons:
the executable can be loaded with the same id in several devices, making your approach void.
You should have to link the executable for each device you are programming, which poses an spent of cpu resources.
The best place is to patch the executable at loading time with the serial number.
Select a data patern as token to initialize your variable with the device id (a pattern difficult to happen elsewhere in your program binary) and initialize your serial number variable to that data pattern (better if you do it statically initializing an array variable or something similar)
Make a program to be executed on each download to device that search for the pattern in the executable file, before loading the binary program into the device and writes the correct value to be programmed into the device (beware that you are patching a binary, so you cannot think on variable lenght strings or the like, that can trash all the work made by the linker)
Once patched the binary executable, you can download it to the device.
Another solution is to reserve a fixed area in your linker script for all this kind of information. Then, put all your device information variables there. Then get the exact positions in rom for the individual variables and include the proper data in the loaded image. In this case, the linker is your friend, reserving some fixed segment in your device's rom allocated for storing the device's individual data (you can put there mac addresses, serial numbers, default configuration, etc.)

Adding header to firmware image stm 32

I'm getting my hands around developing a custom bootloader on STM32 (something like IAP AN4657). Assuming the flash is divided into 3 regions scratch,user area, IAP code (bootloader) and firmware to be upgraded is in scratch area. I want to have a header with firmware version and checksum, I need some understanding on how to implement header to firmware and check the for validity of firmware from IAP (bootloader) code. Any reference to resources are appreciated.
You can create a structure that holds the header information and put this header at a known location in flash. There are two general approaches to this that you see being used:
Padding firmware binary up to the size of flash, minus size of the header and putting it at the end,
Putting firmware header somewhere at the beginning, before .text, .data and .bss that vary in size.
The approach depends on what your requirements are, how complex you want your bootloader to be and how much effort are you willing to put in to make it more optimized or flexible. It is often desired for the bootloader to be as simple as possible and often not self-programmable (there's one bootloader section that is never modified after leaving the factory). Either way, the header should reside at a constant offset within flash. To elaborate further on the two approaches mentioned above:
1. Firmware header at the end of (padded) binary.
This is an easier approach, especially as some tools/IDEs (like IAR for example) have ready-to-use mechanisms for this. Let's say you have the firmware header that has the following format:
typedef struct
{
uint32_t firmware_verson;
uint32_t crc32;
} sFirmwareHeader;
In such case you pad the firmware binary (with 0xFF for example) up to FLASH_SIZE - sizeof(sFirmwareHeader) and place the struct there. Those same tools often also have the capability of calculating CRC of the firmware binary and placing it at the end, which is exactly what fits this approach. The big downside is that every time you want to do firmware upgrade this way, you need to transfer the whole application binary from start to finish, including the padding bytes. If your application is small, this is quite a few unnecessary bytes being transferred. Of course I'm not mentioning any compression methods that would make this smaller, as those would make your bootloader more complex and therefore more error-prone.
2. Firmware header at the start of the application binary
Another approach is placing the firmware header somewhere at the start. Good place for this may be after ISR vectors but before .text, .data and .bss which will vary in size as you change your application code. A good idea is to extend the mentioned structure with the firmware_size field:
typedef struct
{
uint32_t firmware_verson;
uint32_t firmware_size;
uint32_t crc32;
} sFirmwareHeader;
That way the bootloader can still not only verify the CRC of the firmware file to be loaded, but also verify the integrity of the application that has already been loaded into the flash, as the firmware header still resides under constant offset in flash memory, it's just not at the end like in the 1st approach. The advantage of this method is that you only need to transfer as many bytes as necessary. The downside is that there likely won't be any ready-to-use tools for you. You'll need to write some kind of a simple program/script to calculate the CRC value for you after building the application firmware binary (firmware_size value can be supplied by the linker).
To make the answer more complete, here's a snippet of code that should give you a good starting point regardless which approach you plan to use. These are for gcc.
Part of the linker script defining a section to hold firmware header at a constant 0x200 offset counting from the start of the FLASH memory section:
__fw_header_offset = 0x200;
SECTIONS
{
/* ISR vectors */
.fw_header : ALIGN(4)
{
FILL(0xFF)
. = ORIGIN(FLASH) + __fw_header_offset;
KEEP(*(.fw_header))
} >FLASH
/* Other sections in Flash */
}
Then in your application code you can do this:
const sFirmwareHeader __attribute__ ((section(".fw_header"))) FirmwareHeader = {
1, // firmware_verson
0 // crc32, this can be filled with an external application after building firmmwre binary
};
which creates a global FirmwareHeader structure and places is under `.fw_header' section defined eariler.
I also use in my projects something similar.
The header with firmware version and CRC checksum was placed in linker script at the end of FLASH, so header structure with version of firmware was defined on one place in source code and checksum was last bytes in binary.
Checksum was added after building and converting elf to binary file with simple python scrip. but some compilers (IAR) has feature to calculate and place checksum of firmware.
In my case after boot I look to header in update area and if there was something and CRC was OK and whole header was different than header in application I start copying this update area to application area.

protect c++ output file(pe file) from editing using crc

How to protect c++ output file(pe file) from editing using crc(Cyclic Redundancy Check)?
**Best Regards**
You can use CRC's to effectively check to see if a file was accidentally altered, but they are not effective for copy protection, or preventing cheats on a game.
Usually, when I program has some sort of CRC check, I find the code which does the check, and change the assembly instruction from a conditional branch to an unconditional branch. This is usually quite easy to find, because normally after a CRC fail, the program displays a message and exits. I place a break point when the message occurs, and examine all the frames in the stack. I then put break points on each point in the stack, run the program again, and see which one does the CRC check.
This isn't particularly difficult, and people often bundle little programs which will apply the same changes to the software of your choice.
You need a static variable in your code. The variable needs to be initialized to a value that can easily found with an hex editor (e.g. DEADBEEF)
you need a crc-algorithm (try searching google)
The tricky part. You need to get pointer in memory to the start and to the end of your exe. You can parse the pe file header for the code location and run the crc-algorithm from start of code to end of code. Then you have the value.
Of course you have to check the calculated value with the one in the static variable.
Inserting the value - depending on how often you build, you might want to programm a tool. You can always run your program and set a breakpoint on the comparison. Then you note down the value and hex-edit it into the executable. Or you create a standalone program that parses the pe-header as well, uses the same function (this time on the file) and patches it in. This could be complicated though, because I don't know what is changed by the OS during loading.

Resources