3
votes

I have written a bootloader for a Kinetis K24 Cortex M4. The bootloader loads additional functionality over USB into ram at runtime. This ramcode exists as its own EWARM project generating a binary. The entry point to this binary must always be 0x20000000 and the vector table must always live at 0x20007000 in order to play nicely with my .NET tool. The IAR startup code handles clearing of the .bss and the .data copy but it also does some other things I dont want. I can't figure out how to force the IAR entry point to a specific address so I have created my own entry point like so

#pragma section=".bss"

#pragma location=".init"
__interwork int __low_level_init(void)
{
    char * from = __section_begin(".bss");
    char * to = __section_end(".bss");

    __DI(); // Disable interrupts

    memset(from, 0x00 , (to - from));

    memcpy(__vector_table, (unsigned char *)ROM_VECTOR_LOCATION, VECTOR_TABLE_SIZE);

    SCB_VTOR = (unsigned int) & __vector_table;

    main();

    SCB_VTOR = (uint32_t)ROM_VECTOR_LOCATION;
}

When I debug the code I can see that my global variables initialized to non-zero values take on random values. I believe this is because I am not copying the .data section from the LMA to the VMA.

My question is how do I duplicate this copy of the .data section from LMA to VMA?

I would also settle for using the IAR startup code if I could figure out how to break it up but the entry point can't be the reset vector. The entry point has to be 0x20000000 and the vector table has to live at 0x20007000

1
You already do one memcpy of some data, why not add another? All the information you need should be available to you, yes? The start and end of the .data segment in FLASH, as well as some location for it in RAM? - Some programmer dude
Some useful tips & tricks for how to roll out the "CRT" yourself on a generic MCU. Most notably your code seems to fail to setup the clock before you init .data and .bss. That would be very bad. Though of course not all from that link applies to Cortex M4, ARM sets the SP through hardware etc. - Lundin
Yes, I assume this will be a simple copy but I do not know where this information is located. It's not in my linker script and nothing in the map file stands out. - lusher00
If you want the variables to be initialized proberly calling main from __low_level_init is not a very good idea. __low_level_init is called before the initialization code. - Johan
Anyway, I don't know what IAR names the various segments, but obviously you need a memcpy from wherever .data initializers are stored in flash, to the RAM block named .data. Check your linker file/map file/symbol browser to find out the name used. I don't believe LMA/VMA is an issue. - Lundin

1 Answers

1
votes

The IAR function which handles the copy of the .data section is called __iar_data_init3(). I had considered calling this directly but couldn't believe it was that simple. IAR suggested this is the correct solution. I also used the keyword __root to prevent the compiler from removing my "unused" function. This allowed me to rename it something more appropriate like startup(). Calling it __low_level_init() was just a hack to prevent the compiler from removing it. __low_level_init() was not called as part of the startup sequence but rather the entry point I was loading the program counter with in the bootloader. This is my final solution

#pragma section=".bss"
#pragma location=".init"
__root void startup()
{
    char * from = __section_begin(".bss");
    char * to = __section_end(".bss");

    memset(from, 0x00 , (to - from));

    __iar_data_init3();

    memcpy(__vector_table, (unsigned char *)ROM_VECTOR_LOCATION, VECTOR_TABLE_SIZE);

    __DI(); // Disable interrupts

    SCB_VTOR = (unsigned int) & __vector_table;

    main();

    SCB_VTOR = (uint32_t)ROM_VECTOR_LOCATION;

}

Not there is also a function called __iar_zero_init3() which handles the zeroing of the .bss however on first try it caused my program to crash. I can't imagine it would take much work to get it working.