Hi,
Can anyone tell me how my code can know what size the image is in FLASH ? Is there a symbol that I can reference that shows how much space the image occupies ?
I know this information is obvious from the generated .HEX file (and it may be possible to work it out from the .MAP file). I currently have to post-process the .HEX file and patch it (updating the relevant line's checksum accordingly).
Surely there is an easier way to do this !
Note that I'm not looking for the size of the CODE segment, just the overall image size.
Any ideas ?
Thanks,
David.
Hi Robert,
Once again, thanks for your assistance - we're definitely getting closer.
Out of interest, do you work for Keil ? If not, where are you getting this information from ? The online help just doesn't seem (at least to me) to explain this properly.
The example you gave has allowed me to get at the IRAM1 linker symbols, but I'm still not getting the numbers that I need. Your example appears to add the FLASH Code size to the RAM data size. I'm trying to determine the "actual" number of bytes occupied in FLASH by the entire downloaded image. This is probably something like the sum of the RO code and the compressed R/W and ZI data.
Perhaps it would help if I explained a bit more about what I am trying to achieve :-
I have a USB-capable BootLoader and a separate downloadable application. The BootLoader has to perform (among other checks) a CRC validation on the application before running it. In order to calculate the CRC, it needs to know both the location and the size of the application image. The location isn't a problem. At the moment I post-process the application HEX file, and insert the size at a known offset from the start of the image, before downloading the patched image to FLASH. I want to be able to build that size information into the image directly, using information that should be available from the linker. I'm not looking for the amount of RAM the application uses, or the expanded size of any ZI regions; I just need the actual size (in bytes) of the application image as stored in FLASH.
Do you know how I can achieve this ?
The current values from my application image are as follows :-
Load$$ER_IROM1$$Base = 0x00005000 Image$$ER_IROM1$$Base = 0x00005000 Image$$ER_IROM1$$Length = 0x000059EC Image$$ER_IROM1$$Limit = 0x0000A9EC Image$$ER_IROM1$$RO$$Base = 0x00005000 Image$$ER_IROM1$$RO$$Base = 0x00005000 Image$$ER_IROM1$$RO$$Length = 0x000059EC Image$$ER_IROM1$$RO$$Limit = 0x0000A9EC Image$$ER_IROM1$$RW$$Base = 0x0000A9EC Image$$ER_IROM1$$RW$$Length = 0x00000000 Image$$ER_IROM1$$RW$$Limit = 0x0000A9EC Image$$ER_IROM1$$ZI$$Base = 0x0000A9EC Image$$ER_IROM1$$ZI$$Length = 0x00000000 Image$$ER_IROM1$$ZI$$Limit = 0x0000A9EC Load$$RW_IRAM1$$Base = 0x0000A9EC Image$$RW_IRAM1$$Base = 0x40000060 Image$$RW_IRAM1$$Length = 0x00000868 Image$$RW_IRAM1$$Limit = 0x400008C8 Image$$RW_IRAM1$$RO$$Base = 0x40000060 Image$$RW_IRAM1$$RO$$Base = 0x40000060 Image$$RW_IRAM1$$RO$$Length = 0x00000000 Image$$RW_IRAM1$$RO$$Limit = 0x40000060 Image$$RW_IRAM1$$RW$$Base = 0x40000060 Image$$RW_IRAM1$$RW$$Length = 0x00000868 Image$$RW_IRAM1$$RW$$Limit = 0x400008C8 Image$$RW_IRAM1$$ZI$$Base = 0x400008C8 Image$$RW_IRAM1$$ZI$$Length = 0x00000218 Image$$RW_IRAM1$$ZI$$Limit = 0x40000AE0
I don't understand why the IROM1 RW and ZI regions both show as having lengths of 0. Surely these should show the compressed sizes of the RW and ZI regions respectively. Can you explain this ?
Thanks again,
The linker scatter file which defines memory layout (regions and export symbols) can be quite complex and is indented for advanced users which need special features. uVision takes out the complexity and handles this automatically with auto generated scatter file.
From your listing of linker symbols I guess the following scatter file was used:
LR_IROM1 0x00005000 ???(size) { ER_IROM1 0x00005000 ???(size) { *.o (RESET, +First) *(InRoot$$Sections) .ANY (+RO) } RW_IRAM1 0x40000060 ???(size) { .ANY (+RW +ZI) } }
IROM1 has no RW/ZI regions and therefore the length of those regions is 0.
When you look at the generated map file you should see something like:
Load Region LR_IROM1 (Base:0x00005000, Size:0x00006254 Execution Region ER_IROM1 (Base: 0x00005000, Size: 0x000059ec Execution Region RW_IRAM1 (Base: 0x40000060, Size: 0x00000a80
Flash Image Size covers the code and constants (IROM1) and values for non-zero initialized variables (RW from IRAM1) and is Image$$ER_IROM1$$Length + Image$$RW_IRAM1$$RW$$Length.
This applies only when RW data is not compressed. If it is compressed (search for COMPRESSED in the map file) then the image will be smaller and I believe that there is no linker symbol which gives this information (last time I checked).
If you want to protect the image with CRC you can still do this even if RW data is compressed by padding the remaining area with known values or for example make sure that the unused Flash was erased (value 0xFF).
Thanks Robert,
Your explanation is very helpful. Do you work for Keil ?
Your guess at my .SCT file is pretty close. It's not quite right, but I made changes in the "Target" options dialog after creating the project, and I don't think uVision keeps the .SCT file up to date after initial creation. It certainly doesn't reflect recent changes.
I'm confused as to where the ZI and RW sections of my application are stored, as the symbols show the RO size, but 0 for ZI and RW - I certainly have initialised variables and static global data that must be stored somewhere in the image. Does the linker just report the figures for the sum of (CODE + Compressed RW + Compressed ZI) ?
The .MAP file shows the regions as follows :-
Load Region LR_IROM1 (Base: 0x00005000, Size: 0x00005cb8, Max: 0x0000b000, ABSOLUTE, COMPRESSED[0x000054ec]) Execution Region ER_IROM1 (Base: 0x00005000, Size: 0x00005450, Max: 0x0000b000, ABSOLUTE) Execution Region RW_IRAM1 (Base: 0x40000060, Size: 0x00000a80, Max: 0x00003fa0, ABSOLUTE, COMPRESSED[0x0000009c])
Note that the details above are based on a different build than the one I quoted from earlier.
This shows two regions as COMPRESSED. Is there any way to turn this off (i.e. Make them uncompressed), just for experimentation purposes ? I don't know the difference between the Load region and the Execution Region.
I am very surprised that Keil's linker has no mechanism to make available the actual size of the generated image. (Reinhard, can this be added to the "Wish List" ?)
I tried to use Image$$LR_IROM1$$Length, but it doesn't seem to exist. The compressed length shown for the LR_IROM1 region (0x54ec) is correct and is the value I am looking for.
I understand your alternative suggestions for CRC, but both present the same problem; what value to use ? What value is guaranteed not to be at the real end of the image ? e.g. If I depend on 0xFF (erased FLASH), I will miscalculate if the last byte(s) of the image actually contains 0xFF.
Thanks again for all your assistance - it is much appreciated.
Regards, David.
Hi David,
Yes, I work for Keil.
When you are using the Linker option "Use Memory Layout from Target Dialog" and you have no Scatter File selected then uVision updates the auto scatter file when the memory layout changes.
RW and ZI section are stored in the Load region after the Code and Constants.
In your example the total length of the image which needs to be stored in Flash is the length of the Load region which is 0x54EC (Compressed). The majority is occupied by code and constants which is the length of the ROM Execution region and is 0x5450 and in the remaining 0x9C bytes are the compressed initial values of RW data.
Load region shows the image layout stored in Flash and the Execution regions where it is actually located at execution time.
You can disable the compression by the Linker option "--datacompressor off".
I agree that there should be a linker symbol like Image$$LR_IROM1$$Length which shows the actual total length of the Load region (Flash Image Size) regardless if the data compression is on or off. We have put this on our To Do list.
In the mean time you can bypass this by the methods that I have described earlier (especially when data compression is off).
Regards, Robert
Thanks for the explanation about the auto scatter file. My confusion arose from the fact that this is not the file that is greyed out in the relevant dialog. When I deselect "Use Memory Layout from Target Dialog" and select "Edit" for the named SCT file, this must be a different file from the auto scatter one as it is definitely NOT updated automatically when I edit values in the "Target" dialog.
I understand the arithmetic and that 0x9c accounts for the compressed data, although I assumed that this was BOTH ZI and RW, not just RW.
What I don't understand is why the linker symbols show both ZI length and RW length as 0. What is the value of these symbols if they don't show the actual region sizes, or are they currently only valid if compression is disabled ?
I will try without compression today and see whether I can get the figures that I need.
I appreciate you adding my request to the "To Do" list as this will be a useful addition.
Thanks for your help.
I haven't looked at these symbols for the ARM compiler, but just a note about zero-initialized data.
Zero-initialized variables should not need to consume any space in the FLASH image. The startup code just needs to know the start addres, and how many bytes of RAM to clear before calling main(). That is the big reason to separate initialized variables from zero-initialized (cleared) variables. Else, a 16kB large transfer buffer would require 16kB of (compressable) data mirrored in the FLASH.
Most C compilers uses the name BSS for zero-initialized data, where BSS stands for Block Started by Symbol.
"Most C compilers uses the name BSS for zero-initialized data, where BSS stands for Block Started by Symbol."
Interesting ... I remember learning years ago that it stood for 'block storage segment'.
Done a quick search, both seem to be acceptable. Neither (to me) seem particularly logical.
Why should everything be logical :)
Yes, more than one acronyme are suffering from contention as to the "original" or "true" name, since they often got invented in a more "creative" state of a developer and without being immediately documented.
The startup code only has a symbol to tell it where the BSS/ZI data starts. Normally the size isn't explicitly stored. Instead, there is a second symbol where the data ends, and the size is computed by the startup code.
This in relation to the DATA segment, where the startup code has a full set of data to copy.
This sounds reasonable, but assumes that all ZI data is contiguous. Is that a reasonable assumption for all compilers ?
At least for "real" processors, that assumption should be real. I'm not sure about compilers for embedded processors - if the processor has non-contiguous data memory areas, there can be a need to be able to split zero-initialized variables into these memory areas.
Fair enough. That probably explains why the ZI length is shown as 0 (though I don't see much value in having the symbol if it is always 0).
But what about the RW length ? My image definitely has some (non-zero) initialised data.
Are you sure that you haven't mixed up the IRAM1 and IROM1 symbols?
Quite sure. If you look above, you'll notice that the two report diferently. i.e.
Image$$ER_IROM1$$RW$$Base = 0x0000A9EC Image$$ER_IROM1$$RW$$Length = 0x00000000 Image$$ER_IROM1$$RW$$Limit = 0x0000A9EC Image$$RW_IRAM1$$RW$$Base = 0x40000060 Image$$RW_IRAM1$$RW$$Length = 0x00000868 Image$$RW_IRAM1$$RW$$Limit = 0x400008C8
David
Yes, your IRAM1 region has a couple of RW variables. Your IROM1 does not. Trying to use FLASH for writeable variables (le'ts assume we are talking about EEPROM or similar that allows writing at that granularity) would not be so good.
Hi Per,
No-one other than you has said anything about trying to use FLASH for writeable variables.
Can I suggest that you read the full thread properly before jumping to patronising conclusions ?
My previous comments referred to Robert's more constructive response above (9-Sep-2007 22:35), where he states :-
"In your example the total length of the image which needs to be stored in Flash is the length of the Load region which is 0x54EC (Compressed). The majority is occupied by code and constants which is the length of the ROM Execution region and is 0x5450 and in the remaining 0x9C bytes are the compressed initial values of RW data."
My question was, assuming the above is correct (and I have no reasons to doubt that it is), why do the linker symbols not show the individual sizes of the ROM execution region and the compressed RW region ?
I believe there may be a problem in that these symbols may only contain valid information when compression is not enabled.
For the avoidance of further doubt, we are talking about initialised (non-zero) variables, not ZI data. The compiler/linker must store the information on initial values somewhere within the IROM1 image and expand the data (initilalising RAM) at startup.
Nothing patronizing about my answer, and I have read the full thread.
I have not said that you are trying to use the FLASH for writeable variables. I am saying that your compiler specifically knows that it can't put variables there, and that I belive that is the reason why the symbols are zero.
And I'm trying to suggest that your R/W data is only represented by the IRAM1 symbols.
It is not an explanation why the compiler doesn't emit enough information to add upp to the total used space in the FLASH, but a suggestion why your IROM1 symbols shows zero for RW and ZI, while your IRAM1 symbols for RW and ZI are not zero.