Hi!
Long story short: .m_data_2 memory segment is correctly initialized right after flashing, but is not getting initialized after powercycling.
This is with Kinetis MK22FN512VLH12 ARM Cortex-M4.
Long story:
I have inherited the responsibility for dealing with issues at https://github.com/UltimateHackingKeyboard/firmware, while not having much actual experience setting toolchains for embedded/bare-metal C...
The MCU in question (Kinetis MK22FN512VLH12) has RAM divided into two data segments: m_data and m_data_2.
Assume following code:
__attribute__((section (".m_data_2"))) uint8_t foo = 123;
int main(void)
{
PRINT(foo);
}
Here are datasheets, in case they are of any help:
Edit: fixed the MCU part number
已解决! 转到解答。
The answer depends on the tool set you are using and its age.
What you are looking for is the code that happens right out of 'reset'.
Older code would be in assembler and end with .S.
Newer code is often .c file.
GCC linker scripts generally end with .ld.
I can't be more detailed because each tool, and generation of the tool, calls them something different in different locations.
Hi,
I suppose that the line has issue.
__attribute__((section (".m_data_2"))) uint8_t foo = 123;
The above line declares a variable uint8_t foo, and save it in SRAM section .m_data_2. But as you know that the data in SRAM will be lost after power off, so the value 123 is lost after power off.
If you want to keep the value 123, the 123 must be saved in flash and copy to RAM.
1)you can define:
__attribute__((section (".m_data_2"))) uint8_t foo;
int main(void)
{
foo=123;
PRINT(foo);
}
2)you can use the line:
uint8_t foo=123;
int main(void)
{
PRINT(foo);
}
3)const uint8_t var=123;
__attribute__((section (".m_data_2"))) uint8_t foo;
int main(void)
{
foo=var;
PRINT(foo);
}
Hope it can help you
BR
XiangJun Rong
Thanks for reply!
So I take it that the .m_data_2 cannot be initialized on bootup automatically just as .m_data is?
I am still confused as to why that is so. I would expect that to be the default behavior, automatically inserted by the compiler somewhere before the main is called.
Hi,
The basic theory is that the RAM data is lost when the chip power off and on, that is why that the constant must be saved in flash. If it is a variable saved in RAM with an initialized constant, there is a copy from flash to RAM.
You can not declare a variable in RAM with initialized constant data.
BR
XiangJun Rong
Yeah, but how/why is that different from simply declaring it as follows?
uint8_t foo = 123;
This foo is also declared in RAM, yet after power on it gets automatically assigned to 123. (If I am not mistaken, compiler inserts additional code that either assigns the value as an immediate, or copies the entire segment from flash.)
Hi,
For the global variable
uint8_t foo = 123;
The compiler will save the 123 in flash, the foo is allocated in RAM, before calling main(), the 123 in flash is copied to foo in RAM by initializing code.
Hope it can help you
BR
XiangJun Rong
Ah, thank you very much!
> So the start up code and linker scripts need modified
Any pointers on how to do that?
By "start up code", you mean a compiler-generated code, or an actual file which I need to modify by hand? (How do I indentify it?)
The answer depends on the tool set you are using and its age.
What you are looking for is the code that happens right out of 'reset'.
Older code would be in assembler and end with .S.
Newer code is often .c file.
GCC linker scripts generally end with .ld.
I can't be more detailed because each tool, and generation of the tool, calls them something different in different locations.
You are the best!
Took a while of further searching, experimenting and digging, but following two commits seem to have done the trick (at least nothing seems broken so far
- https://github.com/UltimateHackingKeyboard/KSDK_2.0_MK22FN512xxx12/commit/b1f3446d5e380a3bb851a97d07...
- https://github.com/UltimateHackingKeyboard/firmware/commit/1b1306efa6924ecec4ad9f31f9a47a7f9633abf4