I currently have a C project where I have to write a specific value (0xaa) to a specific address (0x3fec0), and I would like to write it during the programming sequence. The solution I have found is the following :
I write another section in the linker file :
/* Custom flag section in linker file */
_flag_start = 0x3fec0;
.flag _flag_start :
{
KEEP(*(.flag));
}
I write the value as a static variable :
static uint8_t flag __attribute__((section (".flag"))) __attribute__((__used__)) = 0xaa;
It works well, and I manage to write the right value at the right address. However it also generates a very heavy binary : because I set this section at 0x3fec0, my binary will be 261824 Bytes (0x3fec0 in decimal), meaning approx 255KB, as if it was filling with empty data until it reaches this address.
My question is : how to perform the same thing, but without impacting the size of the binary file ?
You can try to output it to another format such as Motorola s-record (srec) or intel HEX.
The program you're using to flash your device may support these formats and skip the useless data between the different address ranges to speed-up the transfer.
I've found a solution much more easy to understand, implement, and that works well.
I simply created a .bin file containing the byte "0xAA" and wrote it with my MCU-specific programmer to my device (If you want to know the specs, it's an Atmel MCU and I used the atprogram program). I wrote the content of this binary file on my MCU with the correct offset (0x3fec0) so it would be at the right place.
Related
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.)
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.
I am trying to read the MCU_ID (device electronic signature) from STM32L476 chip using a JTAG ST-Link/V2 on Windows 7. No code has to be uploaded inside the chip, the program shall just be launched on my cumputer and read this information from the flash memory.
I have managed to find and extract the following screenshot from the Reference Manuel given on ST website :
So I have to read the value stored in the flash memory at the adess 0x1FFF7590 by using a C program. I am using the Atollic TrueStudio IDE which is recommended by ST itself, but it seems to me that it includes the "stm32l476xx.h"library which does not even contain any function which could help me.
What I have done so far
After spending days and days looking for some functions or examples to do something as simple as read flash memory, I have asked on this very site How to interact with a STM32 chip memory, which helped me understand a couple of things about what I had to do; nevertheless, I haven't been able to find what I was looking for even after days reading all the links and docs advised in the comments.
I have asked a couple of professionals who told me that I should search for a JTAG driver to interact with the flash memory, but it seems a bit complicated and I haven't been able to found any.
Someone on this site told me that simply using pointer should be enough; the lack of C example and internet tutorials couldn't help me figure out how to do so.
Finally, I started recently digging around STM32Cube and HAL, even since I wanted to avoid using those because I thought that a simple read could be done without having to include those layers. Asking this question is my final hope before trying to use them.
In Conclusion :
I can't show any code since the only thing I have so far is a #include "stm32l476xx.h"and an empty main.
A hint or solution on How to read a STM32L476's flash memory in C would be just perfect. Every example of C (or any programming language which would be as low or higher level) program or instructions interacting with a STM32 chip's memory could help me a lot since it is very hard to find on internet.
Reading MCU ID using ST-Link (graphical interface)
You can use ST-Link Utility (can be downloaded from ST.com here: http://www.st.com/en/embedded-software/stsw-link004.html). After you do Target->Connect you can specify the address and number of bytes you want to read on top of the Window. This also works for the memory area where MCU ID is defined.
For STM32L476 MCU that you use it's going to be memory address 0x1FFF7590, size 0xC (96 bits). Pressing enter should allow you to see the unique ID read from the MCU you're connected to, in form of 3x32 bit values.
Reading MCU ID using ST-Link (command line interface)
ST-Link Utility provides CLI (command line interface) to do the most common operations. This is done using ST-LINK_CLI.exe located in your ST-Link Utility installation directory.
Reading Unique ID as 32-bit values (STM32L476 MCU from the example):
ST-LINK_CLI.exe -r32 0x1FFF7590 0xC
Reading as 8-bit values:
ST-LINK_CLI.exe -r8 0x1FFF7590 0xC
You can also read it to file using -Dump parameter:
ST-LINK_CLI.exe -Dump 0x1FFF7590 0xC D:\temp\out.bin
Keep in mind that you must have the priviledges to write to the destination directory. If you don't run the command prompt with administrative priviledges, in most common cases this means that you won't be able to create the file in locations such as root drive directory (C:\out.bin) or inside "Program Files", where most likely your program is installed (for example by specifying a relative path, such as giving an output file name only out.bin). The program sadly doesn't inform about failed attempts to write the file, however it does say when it succeeds to create the file. The program execution should end with a green line saying Dumping memory to D:\temp\out.bin succeded. In addition, keep in mind that only the following file extensions are supported: *.bin *.hex *.srec *.s19. It cannot be anything because the extension determines the format in which the data will be written to the file.
You can find more information about CLI parameters in User Manual UM0892.
Reading MCU ID using C code
The same can be done using a program loaded into the MCU. You read it by simply accessing the memory directly. Sample code:
#define STM32_UNIQUEID_ADDR 0x1FFF7590
uint32_t id[3];
id[0] = *(STM32_UNIQUEID_ADDR + 0);
id[1] = *(STM32_UNIQUEID_ADDR + 1);
id[2] = *(STM32_UNIQUEID_ADDR + 2);
After this operation id array should contain the same 3x32bit values you've previously read using ST-Link Utility. You may of course choose to read it as uint8_t byte array of size 12, you may even choose to read it into a struct, in case you're interested in the details (lot number, wafer number etc.). This example should however give you a general idea of how to access this value.
There is Texane stlink, that does what you want. It's written in C, interacts with STM32 chips through an ST-Link adapter, and it can read from chip memory.
What you are looking for is not a feature of ST but a feature of ARM.
Remember, ST simply uses an ARM core. I know most programmers load some code in RAM and use that to access flash. You can find these simple programs in the install directory or Keil for example.
I think this is the manual you will need. But I don't know if there is more information behind the login-wall.
I'm not sure if this is specific to the processor I'm using, so for what it's worth I'm using a Cortex M0+. I was wondering: if I generate a hex file through gcc using -fPIC, I produce...Position Independent Code. However, the intel hex file format that I get out of objcopy always has address information on each line's header. If I'm trying to write a bootloader, do I just ignore that information, skip the bytes relating to it, and load the actual code into memory wherever I want, or do I have to keep track of it somehow?
The intel-HEX format was specially designed to programm PROMs, EPROMS or processors with an internal EPROM and is normally used with programmers for theses devices. The addresses at the beginning of the records have not much to do with the program code directly. They indicate at which address of the PROM the data will be written. Remember also that the PROM can be mapped anywhere into the address space of the processor, thus the final address can change anyway.
As long as you don't want to program a PROM you must remove anything except the data from the records. (Don't forget the checksum at the end ;-)
As I understand the intel-HEX format the records must not be contiguous, there may be holes in between.
Some remarks:
The -f PIC parameter is not responsible for the intel-HEX format. I think that somewhere in your command lines you'll find -O ihex. If you want to have a file that could be executed, objcopy provides better suited output formats.
As long as you don't write earlier stages of the boot process by yourself, you don't load your bootloader - it will be loaded for you. The address at which this will happen is normally fixed and not changeable. So there is no need for position independent code, but it doesn't hurt either.
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.