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.
The region symbols should allow you to do this. See here: www.keil.com/.../armlink_chdcgbjd.htm
Thanks for the quick response Reinhard. I have seen this page before, but could never make any sense of it. Can you give me an example of an actual symbol name that can be referenced from within C ?
e.g. For the ZI region, should the base symbol name be :-
Image$$region_name$$ZI$$Base OR Image$$ER_ZI$$ZI$$Base OR ImageER_ZI$$ZI$$Base OR ImageER_ZIZI$$Base OR something else ?
The documentation doesn't specify how or where the actual region names (ER_RO, ER_RW & ER_ZI) are substituted into the specified symbol name templates. Does anyone else understand this page ?
If I try to use the symbol "Image$$region_name$$ZI$$Limit" from C, I get "undefined symbol" errors. Declaring it as "extern" makes no difference.
I'm just trying to determine the highest address used by the image.
Reinhard,
Using the sample code at http://www.keil.com/support/man/docs/armlink/armlink_chdcceee.htm results in the following error :-
.\Debug\test.axf: Error: L6218E: Undefined symbol Image$$ZI$$Limit (referred from main.o).
Can anyone advise how to use these symbols ?
Thanks, David.
The symbol names depend on the definitions in the Linker Scatter file.
When using the automated way in uVision (Linker Option "Use Memory Layout from Target Dialog" is checked) the memory regions which are defined under settings for Target Dialog are used.
For example if IROM1 is used then symbols like "Image$$ER_IROM1$$Length" are available.
The definition in C would be: extern unsigned int Image$$ER_IROM1$$Length;
Thanks Robert,
This is starting to make some sense - i just wish the documentation did :-)
As you suggest, I can access Image$$ER_IROM1$$Limit but this is NOT the end of the image; it may be the end of the code. I need to determine the actual end of the image in FLASH but cannot find the "magic incantation" to generate a valid symbol for this.
Using the ER_ROM1 region name, I can determine the following for my image :-
Load$$ER_IROM1$$Base = 0x00005000 Image$$ER_IROM1$$Base = 0x00005000 Image$$ER_IROM1$$Length = 0x000056E8 Image$$ER_IROM1$$Limit = 0x0000A6E8 Image$$ER_IROM1$$RO$$Base = 0x00005000 Image$$ER_IROM1$$RO$$Base = 0x00005000 Image$$ER_IROM1$$RO$$Length = 0x000056E8 Image$$ER_IROM1$$RO$$Limit = 0x0000A6E8 Image$$ER_IROM1$$RW$$Base = 0x0000A6E8 Image$$ER_IROM1$$RW$$Length = 0x00000000 Image$$ER_IROM1$$RW$$Limit = 0x0000A6E8 mage$$ER_IROM1$$ZI$$Base = 0x0000A6E8 Image$$ER_IROM1$$ZI$$Length = 0x00000000 Image$$ER_IROM1$$ZI$$Limit = 0x0000A6E8
However, the image in FLASH continues to 0x0000A783. I presume the extra is the ZI region which is expanded at startup, but the symbols above seem to indicate otherwise.
Incidentally, are there similar symbols for the "IRAM1" region name ? Substituting "IRAM1" for "IROM1" in the above symbol names does not work !
Can you (or anyone) suggest the correct symbol name for the end of the image when not using a custom scatter file ?
I know I could find this address by scanning backwards through FLASH, but this should not be needed.
Thanks for your help,
The complete image size in this case is the size of Flash execution region plus the size of RAM R/W region (non-zero initialized variables).
Total_Flash_Load_Image_Size = Image$$ER_IROM1$$Length + Image$$RW_IRAM1$$RW$$Length
The actual size can be even less when initial R/W values are compressed.
As you can see linker symbols are available also for IRAM1 (with the RW_ prefix).
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).
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 ?