Kinetis memory map addressing and use

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

Kinetis memory map addressing and use

1,961 Views
mariospelekis
Contributor III

Hi,

Currently I am have troubles on understanding and use efficiently the Memory map of the kinetis.

Actually I had already finished the development of one of our products but I had to look back again since after some days of normal working mode the system seems to have strange behavior.

Looking forward to understand and handle the kinetis memory map with the best way I would like to write down some thoughts and considarations.

Useful informations:

MCU : MK22FN512VLH12

IDE: KDS 3

SDK : 2.2

Debuger : P&E (Multilink universal)

  1. Curent MCU has 2 pages of SRAM name SRAM_L and SRAM_U with 0xFFFF size each. My program requires use of malloc() functions and so proper Heap size management should be done. After calculating real size for every variable that malloc() function will ocupy in the RAM I got the number 47436 (0xB94C)Bytes. So I change the *.ld file acoording to my requirments and so on the Heap size to the calculated.
    /*************************************************************************************************************/
    HEAP_SIZE  = DEFINED(__heap_size__)  ? __heap_size__  : 0xB94C;       
    STACK_SIZE = DEFINED(__stack_size__) ? __stack_size__ : 0x0400;
    M_VECTOR_RAM_SIZE = DEFINED(__ram_vector_table__) ? 0x0400 : 0x0;
    /*************************************************************************************************************/
    But on the debug some of the last malloc() calls seems not to work. So after many tries I figure out the actual Heap size(0xB994) that my application needs is 72(0x48)Bytes more than the calculated .
    Why this could happen? Is there something that I miss?
  2. After that I noticed that both Heap and Stack are placed into the "m_data_2" place of memory and so at the SRAM_U.
    According to the old school way Stack is located at the very end of the Ram.
    Is this true? Can you confirm this for kinetis series also?
  3. With proper Heap size and stack I debuged my code and noticed that the very first malloc(); function executed, set my variable at 0x2000 0008 location and not at 0x2000 0000 as excpected. After several tries nothing was good enough to set my variable at the start of SRAM_U.
    Why this happens? In what way malloc(); use Heap Size?
  4. Considering that the malfunction of my code could may appear from Stack handling I changed the Stack Size to 2048(0x0800). But searching around the internet,community and the manuals I wasn't able to identify if this Stack limit is able to get overflowed ( under application needs) and what is the expected behavior if this happens (Hard Fault Error OR Memory overwrite).

  5. Finally, and assuming the fact that Stack is on the very end of the SRAM_U page. I realzed that under my own modification on the *.ld file I have let a free space of RAM between Heap and Stack sizes for the program to put working variable there. So in order to prevent wrong behavior I tried to occupy this free RAM space by extending the Stack size and then I realize that something goes Wrong. If you try to set
    Heap size = 0xB994
    Stack size = 0x466B    So 0xB994 + 0x466B = 0xFFFF
    In order to get the maximum of the SRAM_U size(0xFFFF), the compiler is complaining for "m_data_2" overflowd.
    What going on wrong here and what am I missing?

Concluding I would like to mention that I do memory allocation on pointers and according uploaded topics on community (Using pointers, malloc in Kinetis Microcontroller ) there big posibility of memory allocated pointers runs out of Heap size and overwrites Stack content. So according to your thoughts what the most posible scenario of this malfunction (Stack Overflow or pointer overun).

Ps. Discusion created after remaining problem on my project that is posted here
(https://community.nxp.com/message/912130 ).

Best Regards,

Pelekis Marios

Labels (1)
3 Replies

936 Views
mjbcswitzerland
Specialist V

Hi

Just four general comments:

1. malloc() has its own overhead since it needs to track the memory that it has allocated. This will change between malloc() implementations (in the library) but the 8 as first address is probably because malloc() has located its own markers in the memory before giving back a pointer to the RAM that you requested.

2. Since malloc() has its own overhead, which is presumably stored also on the heap, you will not be able to allocate all of the HEAP size that is defined. The more small chunks of memory taken, the more overhead and thus the less efficient it will be (requires larger heap size to be able to use a certain part of it).


3. Depending on the use of malloc() holes can develop that can't be reused until they can be re-combined to a single hole again. This can cause malloc() to fail after a certain time if the way that it is used leads to this. I believe that malloc() is forbidden to be used in systems requiring conformance to safety standards due to such potential effects.


4. When stack is located towards the end of RAM it will tend to overrun heap and/or variables in case it grows too large. This leads to unpredictable behavior or failure that can't be classified specifically. There should always be some monitoring in place to ensure that the worst case stack usage is known to ensure a safety margin.
Some people locate the stack below variables and such so that any overflow will result in a hard fault occurring and try to recover from it. Personally I prefer the standard method since it is not a hard stack size and in any case the developer of any embedded project should always have an accurate idea of the memory utilisation (variables, stack, heap and any other special areas) and be able to predict/calculate the worst case safety margin. If this is not the case it is negligence on part of the developer (or company) which can even - in case of injuries - lead to a law suit against the manufacturer of products (for example a stack overflow that should have been anticipated in a safety system cost Toyota $1 billion in compensation two years ago in the case of some cars unpredicatably accelerating due to the errors that it provoked)

Regards

Mark

936 Views
mariospelekis
Contributor III

Hi, Mark

Thanks a lot for the response. You gave ,indeed, some usefull information here.

I just wanted to do a supplementray question on your respnse.

According to your tolken the Stack size can be overflowed even if we have set the Stack size(considered as limit for me).

But why is given us the oportunity to set "Stack size" if it's not for preventing such malfunctions.

Furthermore, in my situation "IF" the problem comes from the Stack side, I can imagine that is not its size that creates the problem but some variable increment that overflows the Stack size after several period.overwiting heap and ram space's variables.

I mention this cause If there was just the bad calculated Stack size I believe results could be apeared earlier and not after 2 or 3 days.

Regards,

Pelekis Marios

0 Kudos

936 Views
mjbcswitzerland
Specialist V

Hi

The stack size that you set in the linker script is just telling the linker to keep this space free. It doesn't protect anything outside of this space.

If you are using a multitasking operation system there will be also stack sizes for each task.

All of these are basically just sizes to reserve for each stack usage and if the processor (code, task etc.) use more that this there is basically a serious error that is likely.
The operation is not protected against (although it may be monitored) and generally can't be protected against without large restraints of the processor's operation (scripting languages may protect but I doubt that even the most sophisticated embedded operating system will even try to do so due to the overhead involved which would greatly slow all operation).

You need to check and know the greatest level of subroutine and interrupt depth on the main stack and the worst case paths that may temporarily allocate more temporary variable. You also need to be sure that you know any heap allocation limits. It is a good idea to avoid malloc()/free() environments where possible (especially in small embedded systems) due to potential holes developing and also small memory leaks (forgetting to return memory to the stack after use for example):
- a few years ago I worked on resolving problems with the train monitoring system at one of the busiest stations in Paris which would crash about once a month and potentially cause major service disruption when it happened at rush hours. By recording the train logging information over a period and simulating the system based on this information (but much faster) it was possible to reproduce the crash in 20 minutes. By building in a heap monitoring system into the code it was then possible to identify the heap usage and the modules that the heap belonged to. Quickly it could be shown that a single module was slowly becoming the main user of heap memory, and later that a simple routine that was monitoring trains entering and leaving the region was taking just a few bytes of memory and then never returning them. Typically after a months the heap was depleted and the system dead.
The fix then took just a few minutes but the software error had already cost a huge amount of money to the operator and the original manufacturer (as well as damage to their reputations).

Basically if you use malloc() you are responsible for the memory you request and also for cleaning it up. Software errors can be difficult to find but can be serious in nature and sometimes life-threatening. In small embedded systems there is usually little advantage of designing with such heap and better (more reliable and safer) to know the worst case and ensure that static memory is available for it (heap use will tend to have the same physical limits but make its monitoring much more complicated).

From your description there is no specific indication that you have a memory problem but it also can't be excluded. Often problems are also due to not correctly protecting variables that can be modified by both code and interrupts (or not protected from other tasks) since everything looks to work for a certain amount of time but the chance of corruption means that failure may take place after a period of time simply due to the chance of it happening increasing with time. Also DMA operation that runs away, writing over the end of an array (by one location) and many other typical such coding errors are possible.

At the end of the day it will certainly be a software error and so you will need to use the available debugging tools and techniques to home in on the reason it happens each time it takes place until the reason is known and understood, and then learn from the mistake(s) to avoid repetition in the future.

Regards

Mark

0 Kudos