We are running a survey to help us improve the experience for all of our members. If you see the survey appear, please take the time to tell us about your experience if you can.
Hi
I have a requirement to have a header struct containing CRC16, minor,major versions and an ident as a total of 4 x uint16_t at the start of my firmware file. This will be in each of 3 firmwares HEX files that live at different addresses within the flash starting 0x08000000.
Obviously, my bootloader will be at 0x08000000 (start of flash), but the initial 8 bytes will be the struct above. Does anyone know if this is achievable??
Micro is Cortex M3 with 1MB flash (STM32F103ZG) with RTX RTOS
My code to add my struct at 0x08000000 is thus:
//////////////////////////////////////////////
#pragma pack(1) typedef struct { uint16_t FileCRC16; uint16_t FwType; uint16_t MajorRev; uint16_t MinorRev; } str_Firmware_Header_Info_t,*pstr_Firmware_Header_Info_t;
//Enum of FirmwareTypes typedef enum { BL = 0, //BootLoader FC = 1, //FunctionalCode HI = 2, //HumanInterface BLFC = 3, BLFCHI = 4, FCHI = 5, INVALID = 6, //No Start line, or bad addresses etc UNKNOWN = 7, } FirmwareTypes;
#define BOOTLOADER_BASE_ADDRESS 0x08000000 #define CRC16_PLACEHOLDER 0x0000 #define BOOTLOADER_MajorRev 0 #define BOOTLOADER_MinorRev 1
const str_Firmware_Header_Info_t FIRMWARE_HEADER __attribute__ ((at(BOOTLOADER_BASE_ADDRESS))) = {CRC16_PLACEHOLDER,BL,BOOTLOADER_MajorRev,BOOTLOADER_MinorRev};
///////////////////////////////
In the project setting, 'Target' tab, I have IROM1 defined as Start:0x08000000 with Size:0x20000
building the above leads to a map file extract below:
/////////////////////////////////////////////
FIRMWARE_HEADER 0x08000000 Data 8 main.o(.ARM.__AT_0x08000000) __Vectors 0x08000008 Data 4 startup_stm32f10x_hd.o(RESET) __Vectors_End 0x08000138 Data 0 startup_stm32f10x_hd.o(RESET) __main 0x08000139 Thumb Code 0 entry.o(.ARM.Collect$$$$00000000) _main_stk 0x08000139 Thumb Code 0 entry2.o(.ARM.Collect$$$$00000001) _main_scatterload 0x0800013d Thumb Code 0 entry5.o(.ARM.Collect$$$$00000004) __main_after_scatterload 0x08000141 Thumb Code 0 entry5.o(.ARM.Collect$$$$00000004) _main_clock 0x08000141 Thumb Code 0 entry7b.o(.ARM.Collect$$$$00000008) _main_init 0x08000141 Thumb Code 0 entry8.o(.ARM.Collect$$$$00000009) BOOT_jump 0x0800014d Thumb Code 20 bootloader.o(.emb_text)
///////////////////////////////////////////////
Using the above, if I stick a breakpoint at the start of main(), I can step through the initial lines, but then it gets to my 'system startup task':
os_sys_init_user( System_Startup_Task, PRIORITY_ZERO, Startup_System_Task_Stack, sizeof(Startup_System_Task_Stack) );
The 'system startup task' never actually starts and the code falls unto the while(1); that sits below it.
Now, if I remove the line that creates the FIRMWARE_HEADER:
then everything works. The map file becomes:
__Vectors 0x08000000 Data 4 startup_stm32f10x_hd.o(RESET) __Vectors_End 0x08000130 Data 0 startup_stm32f10x_hd.o(RESET) __main 0x08000131 Thumb Code 0 entry.o(.ARM.Collect$$$$00000000) _main_stk 0x08000131 Thumb Code 0 entry2.o(.ARM.Collect$$$$00000001) _main_scatterload 0x08000135 Thumb Code 0 entry5.o(.ARM.Collect$$$$00000004) __main_after_scatterload 0x08000139 Thumb Code 0 entry5.o(.ARM.Collect$$$$00000004) _main_clock 0x08000139 Thumb Code 0 entry7b.o(.ARM.Collect$$$$00000008) _main_init 0x08000139 Thumb Code 0 entry8.o(.ARM.Collect$$$$00000009) BOOT_jump 0x08000145 Thumb Code 20 bootloader.o(.emb_text)
////////////////////////////////////////////
So... vectors are offset by 8 bytes (the size of my struct) in the 1st map, and placed at 0x08000000 in the second map file.
Am I barking up the wrong tree here, is there any way to have the struct at the start of my hex file?
Kind Regards
Nigel
Just to update this... The zero-padding in the output hex file where there is a gap between the end of the actual firmware code and a struct/etc that has been manually fixed at an address using, for instance:
#define CRC16_PLACEHOLDER 0x0000 #define FUNCTIONALCODE_MajorRev 0 #define FUNCTIONALCODE_MinorRev 1
const str_BLFCSP_Firmware_Ident_Info_t FIRMWARE_HEADER __attribute__ ((at(FC_BASE_ADDRESS+FC_LENGTH-sizeof(str_BLFCSP_Firmware_Ident_Info_t)))) = {0,0,0,0,FC,FUNCTIONALCODE_MajorRev,FUNCTIONALCODE_MinorRev,CRC16_PLACEHOLDER};
Would appear to be a 'feature' of Keil. To force the output HEX file to NOT include said zero-padding, one needs to define IROM1 and IROM2
IROM1: 0x8010000 0xDFFF0 IROM2: 0x80EFFF0 0x10
Then, one put the struct/etc that is to be located at a specific location IN ITS OWN c file 'firmware_itent.c'. You can then right click the 'firmware_ident.c' in the project tree and change the 'code/const' settings to 'IROM2'.
The output hex file then contains:
:020000040801F1 :10000000586A0120B1190308B9190308BB1903087C :10001000BD190308BF190308C11903080000000037 :10002000000000000000000000000000A90101081D :10003000C519030800000000390201088502010803 :10004000CB190308CB190308CB190308CB190308F4 :10005000CB190308CB190308CB190308CB190308E4 :10006000CB190308CB190308CB1903089B6A0108B5 :10007000CD6A0108CB190308B76A0108CB19030838 //Lots more hex data lines, but no Zero-padding :02000004080EE4 //Ext lin addr record pointing at upper 4 bytes for location of firmware_ident :10FFF00000000000000000000200000001000000FE //Actual firmware ident data :0400000508010131BC //Record 5 - location of main() :00000001FF //end record