.m_data_2 not initialized

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

.m_data_2 not initialized

Jump to solution
3,226 Views
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

Labels (1)
0 Kudos
Reply
1 Solution
3,124 Views
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.

 

 

View solution in original post

10 Replies
3,199 Views
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 Kudos
Reply
3,189 Views
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 Kudos
Reply
3,181 Views
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 Kudos
Reply
3,174 Views
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 Kudos
Reply
3,153 Views
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 Kudos
Reply
3,139 Views
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 Kudos
Reply
3,132 Views
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,127 Views
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 Kudos
Reply
3,125 Views
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,091 Views
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 Kudos
Reply