Hello,
I am trying to define an RAM area that should not be initialized by the C library init function. I found an old thread about that (http://www.keil.com/forum/11937/) but the proposed solution does not work.
I use a scatter file that define the section like that :
RW_BOOTLOADER 0x10000020 UNINIT 0x0000FFE0 { *.o (Bootram) *.o (Bootstack) }
I try to define the area in assembly code or also in C code by :
BLStackSize EQU 0x00004000 AREA Bootstack, NOINIT, READWRITE, ALIGN=3 BLStackMem SPACE BLStackSize BLStackTop
U32 __attribute__((section("Bootstack"),zero_init)) Bootstack[0x1000];
In any case I get the following result in the map file :
Execution Region RW_BOOTLOADER (Exec base: 0x10000020, Load base: 0x0001ef14, Size: 0x00005030, Max: 0x0000ffe0, ABSOLUTE, UNINIT, COMPRESSED[0x00000024]) Exec Addr Load Addr Size Type Attr Idx E Section Name Object 0x10000020 COMPRESSED 0x00001030 Data RW 328 Bootram fiveco_bootloader.o 0x10001050 - 0x00004000 Zero RW 329 Bootstack fiveco_bootloader.o
My understand is that any zero init or uninit area in any section with UNINIT keyword should not be initialized by the C lib as explained in www.keil.com/.../armlink_pge1362075670305.htm
But tests with standard lib (or microlib) with Keil toolchain 5.24.1 show always an initialization by __scatter_zi.o object.
What is wrong in my approach ??
Many thanks by advance ! Antoine
Hello Antoine ,
What does your scatterfile (the file with the .sct extension) look like? What section of the scatterfile is your assembly code being placed?
Are these articles relevant to you?
http://www.keil.com/support/docs/3480.htm
www.keil.com/.../armcc_chr1359124243221.htm.
Hi Ron,
Thanks for your reply. I already read those articles and tried to solve this issue using them, but it does not change anything.
Here is my full scatter file :
LR_IROM1 0x00000000 0x00080000 { ; load region size_region ER_BOOTLOADER 0x00000000 0x00001000 { *.o (BLRESET, +First) *.o (.bl_start) *.o (Bootloader) } RO_PARAMETERS0 0x00001000 FIXED 0x00001000 { *.o (ModuleParameters0, +First) } RO_PARAMETERS1 0x00002000 FIXED 0x00001000 { *.o (ModuleParameters1, +First) } ER_BOOT 0x00003000 FIXED 0x00000100 { *.o (MAINSTART, +First) } ; Following section needed to align vector table to a multiple of 256 ER_ACTUAL 0x00003100 FIXED 0x0003CF00 { *.o (IRQVECT, +First) *(InRoot$$Sections) .ANY (+RO) } RW_BOOTLOADER 0x10000020 UNINIT 0x0000FFE0 { ; Overlap RW_ACTUAL. Must be defined before RW_ACTUAL. *.o (Bootram) ; Use --diag_warning=L6221E linker cmd line option *.o (Bootstack) } RW_ACTUAL 0x10000020 0x0000FFE0 { .ANY (+RW, +ZI) file_config.o (+RW, +ZI) } RW_SUP_1 0x20000000 0x00004000 { .ANY (+RW, +ZI) } RW_SUP_2 0x20004000 0x00004000 { mci_*.o emac_*.o (+RW, +ZI) .ANY (+RW, +ZI) } }
Please note that it is intended that RW_ACTUAL overlap RW_BOOTLOADER. That's the reason why I need that RW_BOOTLOADER region not to be initialized.
Thanks by advance. Antoine
From this page:
www.keil.com/.../armclang_asm_dom1361290002714.htm
We see that
NOINIT Indicates that the data section is uninitialized, or initialized to zero... You can decide at link time whether an area is uninitialized or zero-initialized.
To choose at linker time how this is handled use the bss_threshold command:
www.keil.com/.../armcc_chr1359124903636.htm
This page has an example of setting bss_threshold
www.keil.com/.../armcc_chr1359124243221.htm
an except:
"Specify --bss_threshold=0 when compiling this example code, to ensure that k and l are placed in a ZI data section. If --bss_threshold=0 is not used, section name rwdata must be used instead of zidata."
Hi Kevin,
Thanks for your answer. Unfortunately, it is exactly what I already tried.
In fact, as explained in article, --bss_threshold=0 is intended to force compiler to place "small global ZI data items in ZI data sections". My area is not small at all. Additionally, my area is specified in an assembly file and not in C file. So compiler is not used.
In the first article, as you wrote, it is explained that NOINIT keyword in AREA tell "NOINIT Indicates that the data section is uninitialized, or initialized to zero... You can decide at link time whether an area is uninitialized or zero-initialized.".
But, HOW can I tell the linker to not init this space to zero ? As I understand, the UNINIT keyword in scatter file should do the job. Am I wrong ?
Thanks again by advance. Antoine
RW_BOOTLOADER 0x10000020 UNINIT 0x0000FFE0 { ; Overlap RW_ACTUAL. Must be defined before RW_ACTUAL. *.o (Bootram) ; Use --diag_warning=L6221E linker cmd line option *.o (Bootstack) } RW_ACTUAL 0x10000020 0x0000FFE0 { .ANY (+RW, +ZI) file_config.o (+RW, +ZI) }
There is something I am not understanding here. Here is what I would expect to happen before main
1) Bootram would be initialized to appropriate values
2) Bootstack would not be initialized to zero
3) RW_ACTUAL .ANY would be initialized (to zero or values) It seems to me that it is highly likely that variables in RW_ACTUAL are at the same location as variables from RW_BOOTLOADER. (You would see this in the map file and see if this is the case.
4) file_config.o would have already matched the .ANY section and would have been located and initialized based the .ANY rules.
Are you expecting something different and if so, what is it that you are expecting.
I think the Error L6221E was there for a reason and would require some work to make sure everything in the overlapping regions worked correctly when you changed it to a warning.
Hi Robert,
Your understanding is nearly correct. Bootram and bootstack are used in a pre-main code et are no more used in main code. It is why the two regions can overlap and so, yes I now what I do when I turn error L6221E to a warning.
But since the initialization is done by the call to __main function of Keil lib, the bootram and bootstack are not initialized at startup because I use them before that call.
It is so why I do not want them to be initialized by the lib, since they are no more useful at that time.
So, in your points : 1) Yes, but it is done by my code and not by the lib. 2) Yes, it is correct before main code. But it is initialized later when calling __main and it is what I try to avoid. 3) Yes and overlap is under control. 4) It is not relevant for my problem, but to be clear, since their is 3 regions with .ANY, this force the linker to put file_config object in this one (due to limitations of NXP LPC RAM architecture).
I hope that I am clear.
Thanks. Antoine
It sounds like you might need to overlay directive
http://www.keil.com/support/docs/3723.htm
That helps some.
1) Yes, but it is done by my code and not by the lib.
OK, you initialize Bootram yourself, but when __scatter is called (as part of calling __main) it seems like it will will be initialized again.
2) Yes, it is correct before main code. But it is initialized later when calling __main and it is what I try to avoid.
It appears as if you are doing it correct such that Bootstack will not be zero initialized and Bootram will be re-initialized when __main is called. Please just verify that BootRam is being initialized and that even though I think Bootstack should not be initialized to 0, it is being initialized to zero. (obviously if you are still using that stack, having it set back to zero is an issue)
Only ZI data in UNINIT sections remain un-initialized, however any RW data in the UNINIT section does get initialized.
Everything posted so far addresses how to make a Zero Init section to not initialize. It explains why if your Zero Init data gets optimized into a RW region that even though you said it should not be initialized, it will still be initialized.
Problem did not exist!
Hi, Thanks all for your help. After further analysis I found that the problem did not exist. The keyword UNINIT in the scatter file with the keyword NOINIT in the assembly area (as explained in my first message of this thread) do the job very well. My test case was not well done and the memory was cleared by another source.
Note that --bss_threshold=0 is also useless.
Sorry for that. Thanks again.
Best regards, Antoine