.m_data_2 not initialized

取消
显示结果 
显示  仅  | 搜索替代 
您的意思是: 
已解决

.m_data_2 not initialized

跳至解决方案
3,224 次查看
kat1
Contributor II

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);
}

 

 

  • On first run after flashing, it correctly prints 123
  • If the board is powercycled, it randomly prints either 108 or 124.
  • If NVIC_SystemReset() is issued the same value gets printed as in the last run.

Here are datasheets, in case they are of any help:

Edit: fixed the MCU part number

标签 (1)
0 项奖励
回复
1 解答
3,122 次查看
bobpaddock
Senior Contributor III

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.

 

 

在原帖中查看解决方案

10 回复数
3,197 次查看
xiangjun_rong
NXP TechSupport
NXP TechSupport

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

0 项奖励
回复
3,187 次查看
kat1
Contributor II

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.

 

0 项奖励
回复
3,179 次查看
xiangjun_rong
NXP TechSupport
NXP TechSupport

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

0 项奖励
回复
3,172 次查看
kat1
Contributor II

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.)

0 项奖励
回复
3,151 次查看
xiangjun_rong
NXP TechSupport
NXP TechSupport

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

 

 

0 项奖励
回复
3,137 次查看
kat1
Contributor II

Hi!

Would you be so kind as to elaborate on the reasons of this difference in handling of those two RAM regions?

0 项奖励
回复
3,130 次查看
bobpaddock
Senior Contributor III
This gets traced back to the 'C' standard.
Initialized variables that are global in scope or marked as 'static' in a function will be placed in a segment typically called 'data' placed in Flash. The start up code knows that it needs to load those 'data' variables.

As there can be any number of segments with arbitrary names, the standard start up code does nothing with them. So the start up code and linker scripts need modified to treat other segments the way they treat the 'data' segment.
3,125 次查看
kat1
Contributor II

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?)

0 项奖励
回复
3,123 次查看
bobpaddock
Senior Contributor III

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.

 

 

3,089 次查看
kat1
Contributor II

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 ), in case anyone stumbles across this thread in the future..

- https://github.com/UltimateHackingKeyboard/KSDK_2.0_MK22FN512xxx12/commit/b1f3446d5e380a3bb851a97d07...
- https://github.com/UltimateHackingKeyboard/firmware/commit/1b1306efa6924ecec4ad9f31f9a47a7f9633abf4

0 项奖励
回复