FreeRTOS Heap with Segmented Kinetis K SRAM

While working on a project for the FRDM-K20D50M, I faced a problem: I was running out of SRAM for my application. The GNU linker reports: “section `.bss’ will not fit in region `m_data'”: 😦

bss will not fit in region m_data

bss will not fit in region m_data

But my device has 16 KByte of SRAM, and I knew I use much less than 10 KByte. So what is the problem?

Kinetis K Memory Split

The Freescale K20 on the FRDM-K20D50M has 16 KByte SRAM. Unfortunately that 16 KByte are splitted up into two 8 KByte memory blocks in the linker file:

MEMORY {
  m_interrupts (RX) : ORIGIN = 0x00000000, LENGTH = 0x000000F8
  m_text      (RX) : ORIGIN = 0x00000410, LENGTH = 0x0001FBF0
  m_data      (RW) : ORIGIN = 0x1FFFE000, LENGTH = 0x00002000
  m_data_20000000 (RW) : ORIGIN = 0x20000000, LENGTH = 0x00002000
  m_cfmprotrom  (RX) : ORIGIN = 0x00000400, LENGTH = 0x00000010

So the linker file defines the m_data and m_data_20000000 range. Because the memory controller of the K20 can access the two areas independently, an object shall not cross that boundary at 0x2000’0000. Consequently, no object allocated by the linker shall cross this magic boundary. The real pain is that the GNU linker is not able to distribute objects into different memory segments :-(. Instead, I need to do this by hand (ahhhrgggg!). The result is that only half of SRAM is easily available on Freescale Kinetis K devices :-(.

❗ The ARM Cortex-M0+ on the Kinetis L series (e.g. FRDM-KL25Z) does not have this memory boundary. There I have the 16 KByte as continuous memory available :-).

The problem is: if I want to have a heap memory like use by FreeRTOS, then by default this gets allocated into the first 8 KByte SRAM, unless I place it with a section attribute into a different area. Luckily, the CodeWarrior engineers have defined a user defined section name .m_data_20000000 in the linker file:

.m_data_20000000 : AT(___m_data_20000000_ROMStart)
{
  . = ALIGN(4);
  ___m_data_20000000_RAMStart = .;
  *(.m_data_20000000) /* This is an User defined section */
  ___m_data_20000000_RAMEnd = .;
  . = ALIGN(4);
} > m_data_20000000

The important name to look at is the name before the AT: “.m_data_20000000”. This is the user section name to be used. That way, if I specify this section name as an attribute name, it ends up in the upper half of memory :-). So what I did is: I have added an optional attribute to the FreeRTOS component :-):

User Heap Section Name in FreeRTOS
User Heap Section Name in FreeRTOS

If enabled, this adds the specified section name to the heap variable definition:

/* Allocate the memory for the heap. */
static unsigned char __attribute__((section (".m_data_20000000"))) ucHeap[configTOTAL_HEAP_SIZE];

Now I can use the upper memory area for the RTOS heap, while using the lower half of memory for my other variables :-).

❗ There is still a problem if my heap would be larger than half of the memory. So with this approach an object cannot be larger than half of the SRAM.

Summary

The splitted memory architecture of the Kinetis K makes it difficult to use variables larger than half of the memory size. This is especially a problem with devices having not much SRAM. But at least now with the added FreeRTOS Processor Expert component attribute I can easily use the upper SRAM for my heap :-). But to the end, I hope that ARM Inc. could implement in the GNU linker the functionality to automatically distribute objects across multiple memory segments. Other linker for embedded targets already do this, as they had to deal with paged or segmented memory on different devices already. So if the GNU linker would be able to deal with this, that would be great! As always, the updated sources and components are available on GitHub. Happy Attributing 🙂

56 thoughts on “FreeRTOS Heap with Segmented Kinetis K SRAM

  1. Hi,

    I am using the FreeRTOS component on K20D50 with success, and as soon as I have seen your post I downloaded your updated components and proceeded with the update in CodeWarrior but unfortunately I can’t see the new option for the memory segment. Is there anything I’m doing wrong in the update/configuration of the new FreeRTOS component?

    Like

  2. Hi Erich,
    I encountered this problem recently, but came up with a different solution. Instead, I collapsed the two linker memory regions into one. In Processor Expert, check out Cpu component->Component Inspector->Build options. Decrement the number of ROM/RAM areas to eliminate m_data_20000000, then adjust the size of the m_data section

    Like

      • I ran into this on another chip I had selected because it advertises 192K of RAM. Only after I started coding did I discover it’s in a 128K and a 64K piece with a big hole in between. So much for doing that great big malloc() I had intended.

        Punchline for me — read more carefully before soldering!

        Like

    • Hi Kevin,
      FreeRTOS is using the heap for the task stacks. But yes, for the SP during the normal startup code, it would be better if the stack does not cross that memory boundary.

      Like

  3. while i using freertos component with eclipse PE IAR complier, there is a problem,
    looks like iar do not support __attribute__(***) , is there an another for using bank ram in iar ?

    Like

    • maybe can replaced by :

      #pragma language=extended
      #pragma location = “m_data_20000000”

      /* Allocate the memory for the heap. */
      #if configUSE_HEAP_SECTION_NAME
      static unsigned char ucHeap[configTOTAL_HEAP_SIZE] @ “m_data_20000000”;
      #else
      static unsigned char ucHeap[ configTOTAL_HEAP_SIZE ];
      #endif

      Like

      • Hi Kevin,
        indeed, I need to change the syntax for IAR :-(. I followed your example. Now it compiles, but somehow the linker does not place the code in the upper SRAM region. What is missing in the linker file?

        Like

  4. Hi Erich,

    I copyed from map file :
    “P4”: 0x800
    m_data_20000000 zero 0x20000000 0x800 heap_2.o [1]
    – 0x20000800 0x800

    it seems placed in to up sram region

    Like

    • Hi Erich,

      I checked the new update from your component, maybe in the freertosconfig.h file ,
      “.m_data_20000000”
      change to
      “m_data_20000000”

      remove the dot

      Like

      • Yes, I just saw that it was not using the name from the properties in the component :-(. I have fixed this now. So it uses now whatever you specify in the settings.
        Still, for my project it does not place it in the upper SRAM region. Not sure what is wrong.

        Like

  5. Hi Erich,

    Thanks for all the great components .

    I found a little problem in the PDG component which drive nokia lcd, if we use freertos and pdg both, there is a little problem in the pdg init, first we disable the interrupt by rtos, then we call the pdg init function following , but pdg init function need interupt enabled by spi, so we will stop on this .
    Can pdg component add the chiose to chose init the driver in PE or not , we can call the init function in gui task.

    Like

  6. Hi Erich,
    how is possible to do this on the FRDM kl25 because in the linker files is not present the :
    .m_data_20000000 : AT(___m_data_20000000_ROMStart)
    {
    . = ALIGN(4);
    ___m_data_20000000_RAMStart = .;
    *(.m_data_20000000) /* This is an User defined section */
    ___m_data_20000000_RAMEnd = .;
    . = ALIGN(4);
    } > m_data_20000000
    because 8192 byte are too low for my application, i have an LCD and a SDCard so i need more space

    Thanks

    Like

    • Hi Daniele,
      you don’t have this for the KL25Z, as on the L series the memory is not segmented. So for the KL25Z128 you have 16 kByte of continous RAM, no need to have this.

      Like

      • Ok, thanks. Another question is why when i do this
        freeheap = FRTOS1_xPortGetFreeHeapSize();

        if (FRTOS1_xTaskCreate(
        Task_LCD, /* pointer to the task */
        “Task_LCD”, /* task name for kernel awareness debugging */
        (unsigned portSHORT)1024, /* task stack size */
        NULL, /* optional task startup argument */
        tskIDLE_PRIORITY, /* initial priority */
        NULL /* optional task handle to create */
        ) != pdPASS ) {
        for (;;) {}; /* Out of heap memory? */
        }

        freeheap = FRTOS1_xPortGetFreeHeapSize();

        if (FRTOS1_xTaskCreate(
        Task_USB, /* pointer to the task */
        “Task_USB”, /* task name for kernel awareness debugging */
        (unsigned portSHORT)1024, /* task stack size */
        NULL, /* optional task startup argument */
        tskIDLE_PRIORITY, /* initial priority */
        NULL /* optional task handle to create */
        ) != pdPASS ) {
        for (;;) {}; /* Out of heap memory */
        }

        freeheap = FRTOS1_xPortGetFreeHeapSize();

        i see that freeheap value is : for first approximately
        the size of total heap size (8184), after the first task declaration 4000, and at the end i have a FRTOS1_vApplicationMallocFailedHook. Why one task take more than 4000kb if the stack size is 1024?
        If i put a total heap size of 15360kb (or similar) instead i have a :
        Description Resource Path Location Type
        MSDCustom.elf section `.bss’ will not fit in region `m_data’ Firmware UpSens FREERTOS C/C++ Problem
        Description Resource Path Location Type
        region `m_data’ overflowed by 3888 bytes Firmware UpSens FREERTOS C/C++ Problem

        Thanks

        Like

        • Hi Daniele,
          in FreeRTOS, the task stack size argument is *not* number of bytes, it is ‘number of stack adressable units’. The size of a ‘unit’ depends on the architecture. For an 8bit architecture this is a byte, but for ARM Cortex this is a 32bit entity. So if you assign 1024, then this means 4*1024 bytes. Typical values I use are 150 or 200. 1024 is a lot of stack (you will easily run out of RAM as you have seen).

          Like

  7. I have a FreeRTOS problem, which means my s/w won’t run when I add a new call to FRTOS1_xTaskCreate().

    I found this post and although I was not getting the same error message as you, I tried the mechanism you suggest, with the same FreeRTOS component settings and a KL25Z. I get this error:

    c:/freescale/cw mcu v10.5/cross_tools/arm-none-eabi-gcc-4_7_3/bin/../lib/gcc/arm-none-eabi/4.7.3/../../../../arm-none-eabi/bin/ld.exe: section .m_data_20000000 loaded at [00004708,00006707] overlaps section .romp loaded at [00004708,0000472b]

    Explanation?

    Like

    • Hi Charles,
      For the KL25Z you do not need to apply these settings: the KL25Z does not have a segmented memory like the K20. If your software does not run after a xTaskCreate(), this sounds like you are running out of heap memory? What is your RTOS heap size? Have you debugged and stepped through your code? Maybe you end up in a out of heap hook?

      Like

    • Ignore this. (a) I read that this fix is not required for the KL25. (b) My bug that seemed to be a FreeRTOS memory problem was actually elsewhere.

      Like

  8. Hi Erich

    according to your previous reply
    “Hi Daniele,
    you don’t have this for the KL25Z, as on the L series the memory is not segmented. So for the KL25Z128 you have 16 kByte of continous RAM, no need to have this.”

    but I have observed after getting passed few minor errors in “Freedom_USBHostMSD” of yours
    It compiles OK but has error in linking.
    I got exactly same linker error as above
    “Building target: PE_Blinky.elf
    Invoking: Cross ARM C++ Linker
    arm-none-eabi-g++ -mcpu=cortex-m0plus -mthumb -O0 -fmessage-length=0 -fsigned-char -ffunction-sections -fdata-sections -g3 -T “C:/Freescale/workspace/PE_Blinky/Project_Settings/Linker_Files/ProcessorExpert.ld” -Xlinker –gc-sections -L”C:/Freescale/workspace/PE_Blinky/Project_Settings/Linker_Files” -Wl,-Map,”PE_Blinky.map” -o “PE_Blinky.elf” ./Sources/Application.o ./Sources/Events.o ./Sources/Shell.o ./Sources/host.o ./Sources/main.o ./Project_Settings/Startup_Code/startup.o ./Generated_Code/AS1.o ./Generated_Code/ASerialLdd1.o ./Generated_Code/BitIoLdd1.o ./Generated_Code/BitIoLdd2.o ./Generated_Code/BitIoLdd3.o ./Generated_Code/CLS1.o ./Generated_Code/CS1.o ./Generated_Code/Cpu.o ./Generated_Code/FAT1.o ./Generated_Code/FRTOS1.o ./Generated_Code/FsMSD1.o ./Generated_Code/HF1.o ./Generated_Code/LEDB.o ./Generated_Code/LEDG.o ./Generated_Code/LEDR.o ./Generated_Code/LEDpin1.o ./Generated_Code/LEDpin2.o ./Generated_Code/LEDpin3.o ./Generated_Code/MSD1.o ./Generated_Code/PE_LDD.o ./Generated_Code/TI1.o ./Generated_Code/TU1.o ./Generated_Code/TimerIntLdd1.o ./Generated_Code/TmDt1.o ./Generated_Code/USB0.o ./Generated_Code/USB1.o ./Generated_Code/UTIL1.o ./Generated_Code/Vectors.o ./Generated_Code/WAIT1.o ./Generated_Code/croutine.o ./Generated_Code/event_groups.o ./Generated_Code/ff.o ./Generated_Code/heap_1.o ./Generated_Code/heap_2.o ./Generated_Code/heap_3.o ./Generated_Code/heap_4.o ./Generated_Code/host_ch9.o ./Generated_Code/host_close.o ./Generated_Code/host_cnl.o ./Generated_Code/host_common.o ./Generated_Code/host_dev_list.o ./Generated_Code/host_driver.o ./Generated_Code/host_main.o ./Generated_Code/host_rcv.o ./Generated_Code/host_shut.o ./Generated_Code/host_snd.o ./Generated_Code/khci_kinetis.o ./Generated_Code/list.o ./Generated_Code/mem_util.o ./Generated_Code/poll.o ./Generated_Code/port.o ./Generated_Code/queue.o ./Generated_Code/tasks.o ./Generated_Code/timers.o ./Generated_Code/usb_classes.o ./Generated_Code/usb_host_hub.o ./Generated_Code/usb_host_hub_sm.o ./Generated_Code/usb_host_msd_bo.o ./Generated_Code/usb_host_msd_queue.o ./Generated_Code/usb_host_msd_ufi.o ./Generated_Code/usbevent.o ./Generated_Code/usbmsgq.o ./Generated_Code/usbsem.o
    c:/program files/gnu tools arm embedded/4.8 2013q4/bin/../lib/gcc/arm-none-eabi/4.8.3/../../../../arm-none-eabi/bin/ld.exe: PE_Blinky.elf section `.bss’ will not fit in region `m_data’
    c:/program files/gnu tools arm embedded/4.8 2013q4/bin/../lib/gcc/arm-none-eabi/4.8.3/../../../../arm-none-eabi/bin/ld.exe: region `m_data’ overflowed by 1076 bytes
    ./Generated_Code/FsMSD1.o: In function `time_delay’:
    C:\Freescale\workspace\PE_Blinky\Debug/../Generated_Code/FsMSD1.c:126: undefined reference to `delay_count’
    c:/program files/gnu tools arm embedded/4.8 2013q4/bin/../lib/gcc/arm-none-eabi/4.8.3/../../../../arm-none-eabi/lib/armv6-m\libg.a(lib_a-sbrkr.o): In function `_sbrk_r’:
    sbrkr.c:(.text._sbrk_r+0xc): undefined reference to `_sbrk’
    collect2.exe: error: ld returned 1 exit status
    make: *** [PE_Blinky.elf] Error 1

    and linker file has following memory code
    “MEMORY {
    m_interrupts (RX) : ORIGIN = 0x00000000, LENGTH = 0x000000C0
    m_text (RX) : ORIGIN = 0x00000410, LENGTH = 0x0001FBF0
    m_data (RW) : ORIGIN = 0x1FFFF000, LENGTH = 0x00004000
    m_cfmprotrom (RX) : ORIGIN = 0x00000400, LENGTH = 0x00000010
    }”

    so why this problem occurring in my project
    I have no idea how to tackle this

    Like

    • Hi Devidas,
      Your linker file clearly shows that the 16 KByte of RAM are in one piece:
      m_data (RW) : ORIGIN = 0x1FFFF000, LENGTH = 0×00004000
      🙂
      But I think the real issue is this (from your output):
      `m_data’ overflowed by 1076 bytes
      This means somehow you use too much of that 16 KByte of RAM.
      I checked my Freedom_USBHostMSD project from GitHub, and that compiles and links fine:
      ‘Invoking: ARM Ltd Windows GNU Print Size’
      “C:/Freescale/CW MCU v10.6/Cross_Tools/arm-none-eabi-gcc-4_7_3/bin/arm-none-eabi-size” –format=berkeley Freedom_USBHostMSD.elf
      text data bss dec hex filename
      76120 52 14868 91040 163a0 Freedom_USBHostMSD.elf

      So: do you have some extra variables? That project already is using 14868 bytes of RAM. 10000 are reserved for the RTOS, so you might reduce that by 1 KByte so you can link again?

      Like

      • i will try again and link this code.
        this time i will download fresh code from git-hub and try again and let you know soon.
        thanx for reply

        Like

  9. Pingback: RAM Target with Kinetis Design Studio and FRDM-K64F | MCU on Eclipse

  10. Eric

    I am curious as to this:
    “The memory on the Freescale Kinetis-K devices is *not* continuous! There is a memory barrier at 0x2000’0000 which segments the memory, so you cannot use that memory in one single piece!”

    As far as I know the only restrictions are that bit-banding is limited to one of them and it is not possible to read/write misaligned addresses across the boundary, nor to perform burst access across it.
    You write about ‘objects’ but what are these exactly? In the case of variables and structs that are correctly aligned general read/write operations should be possible and so allow the complete memory to be used as if it were contiguous. Which “operations” on which ‘objects’ thus need to actually be avoided??

    Regards

    Mark

    Like

    • Hi Mark,
      there is no bit-banding on Cortex-M4(F), bit-banding is a feature of Cortex-M3. And I refer to ‘objects’ from the linker perspective: variables and functions (memory objects with a size >0).
      Erich

      Like

      • Eric
        According to section 4.2.1 of the K64F user’s manual:
        “The SRAM_U, AIPS-Lite, and general purpose input/output (GPIO) module resources reside in the Cortex-M4 processor bit-band regions.”
        Section 9.7 “AHB-AP can performed unaligned and bit-band transaction”
        Table 4.1:
        “0x1fff_0000-0x1fff_ffff SRAM_L:Lower SRAM (ICODE/DCODE) All masters
        0x2000_0000-0x2000_2fff SRAM_U:Upper SRAM bitband
        region All masters
        0x2200_0000-0x23ff_ffff Aliased to TCMU SRAM bitband

        If I write 0 to 22000000 bit 0 of 20000000 is set to ‘0’
        If I write 1 to 22000000 bit 0 of 20000000 is set to ‘1’.
        Therefore I am pretty sure that there is bit-banding (limited to SRAM_U).

        Regards

        Mark

        Like

      • Eric

        If your objects are bytes then there is no problem. If they are aligned short words there is no problem and if they are aligned long words there is no problem. Objects made up of these and also aligned are also no problem.
        See the following simple test with a memory debugger.

        1. This shows a memory dump across the boundary with a pattern prepared so that the content is easily recognisable:
        #md 1ffffff0 l 8
        Memory Display
        0x1ffffff0 12345678 89abcdef 87654321 fedcba98 .4Vx…..eC!….
        0x20000000 12345678 89abcdef 87654321 fedcba98 .4Vx…..eC!….

        2. A long word write is made at the end of SRAM_L:
        #mm 1ffffffc l 55555555
        Write

        md 1ffffff0 l 8
        Memory Display
        0x1ffffff0 12345678 89abcdef 87654321 55555555 .4Vx…..eC!UUUU
        0x20000000 12345678 89abcdef 87654321 fedcba98 .4Vx…..eC!….

        3. A lond word write is made at the start of SRAM_U:
        #mm 20000000 l aaaaaaaa
        Write

        md 1ffffff0 l 8
        Memory Display
        0x1ffffff0 12345678 89abcdef 87654321 55555555 .4Vx…..eC!UUUU
        0x20000000 aaaaaaaa 89abcdef 87654321 fedcba98 ………eC!….

        4. A misaligned long word write in the last but one long word of SRAM_L:
        #mm 1ffffffb l bbccddee
        Write

        md 1ffffff0 l 8
        Memory Display
        0x1ffffff0 12345678 89abcdef ee654321 55bbccdd .4Vx…..eC!U…
        0x20000000 aaaaaaaa 89abcdef 87654321 fedcba98 ………eC!….

        5. A misaligned long word write in the final long word of SRAM_L:
        mm 1ffffffd l 66666666
        Write

        md 1ffffff0 l 8
        Memory Display
        0x1ffffff0 12345678 89abcdef ee654321 666666dd .4Vx…..eC!fff.
        0x20000000 aaaaaaaa 89abcdef 87654321 33dcba98 ………eC!3…

        Only case 5 fails because one bytes of the mis-aligned write is not made in SRAM_U.

        It also fails for the equivalent mis-aligned long word read across the boundary.

        This means that there is only a problem when objects contain non-bytes and these are misaligned across the boundary. Although misaligned non-bytes work on the M4 they are not recommended since they slow down the speed of access. Most SW will avoid misaligning such things (it would not be portable code and fail on HW that doesn’t support misaligments) and so most code will have no problem using SRAM_L and SRAM_U as a single block. Code that can’t is essentially non-portable and badly designed code.

        Regards

        Mark

        Like

  11. Hi Erich,

    I’m using kl25z controller with freeRTOS and I have exceeded the .m_data limit. So as you suggested I have tried to enable user heap area for freeRTOS. But I am getting the below error

    “section .m_data_20000000 loaded at [0000a758,0000d637] overlaps section .romp loaded at [0000a758,0000a76f]”

    Kindly help in solving this issue

    regards,
    Durgesh

    Like

    • Hi Durgesh,
      The KL25Z is a Freescale ARM Cortex-M0+, and does *not* have this segmented memory! Therefore, this post does not apply to this (it only applies to Freescale Kinetis M4(F) microcontrollers.
      So in your case, you probably just exceeded the 16 KByte RAM you have on the KL25Z. I suggest that you reduce the RAM amount used.

      Erich

      Like

      • Unfortunately, with all my respect, Erich, you’re *wrong* about this. Please read KL25P80M48SF0RM.pdf “KL25 Sub-Family Reference Manual” at page#75 Chapter#3.6.3 SRAM Configuration and please fix your public pages.

        Like

      • @Angel G.
        All Kinetis processors (K, KL, KV, KW, KE, KEA, KM) have SRAM that is partitioned as SRAM_L and SRAM_H, with the partition boundary at 0x20000000.
        The M4 based parts have different connections with respet to bus master usage of the two partitions and so have different restrictions to the KL parts, which don’t have the same bus architecture.

        Therefore it is difficult to say what is wrong and what is right because some restrictions are indeen not relevant to the KL RAM. Therefore in some respects it is also correct to state that the segments are irrelevant to one but are relevant for the other.

        However I think that this topic may be basically misleading because it has its roots in a linker script file which divides the SRAM into two areas, which makes it difficult to handle (by some compilers/linkers). The fact that the linker script had this is another question because in 99.9999% of correct software it is also completely irrelevent to split it, whether working with M4 or M0+.

        The fact is however that the M4 supports non-aligned RAM access and so splitting the SRAM into two areas allows this to be used without a risk of data corruption since it automatically avoids data structures that ‘straddle’ the two areas, where the M4 ‘also’ doesn’t handle misaligned accesses.

        Why anyone would want to use misaligned data is a further question since it reduces data access efficiency and generally is bad software design. So my view is that the original linker script was also basically bad linker script design since it was adhering to poor software design. If this had not been there in the first place the compete topic may even have been irrelevant for 99.999% of programmers anyway (exceptions being DMA users doing burst accesses across partitions).

        The M0+, on the other hand, doesn’t support misaligned access (it will generate a hard-fault if tried) so for such devices the whole discussion is more or less redundant. Misaligned data structures won’t work at on on these parts….

        Regards

        Mark

        Like

      • @Mark: Wrong is *exactly* the above claim i replied to: “The KL25Z is a Freescale ARM Cortex-M0+, and does *not* have this segmented memory!…”
        Because as you replied, ALL Kinetis MCU have partitioned SRAM.
        The the alignment at 32-bit boundary does not guarantee that an array, which is used as DMA buffer won’t cross it.

        Like

      • Moreover, I read that the SRAM_L has single-cycle access (from the core), (reminds me the STM32 CCM) while SRAM_U has 2-cycle. So they’re not exactly equal. There is an AN from Freescale on the performance, where their employee recommends SRAM_L to be used for critical code which runs from sram and SRAM_U – for the data.

        Like

      • @Angel G

        OK, I agree that it is not correct to state that the KL25 doesn’t have segmented memory.
        I also think that the linker script file is not the place to restrict data structures from crossing the boundary:
        1 – it is a ‘big-hammer’ solution that causes other possibly negative effects (and nasty awkwardness to unrelated things) and still doesn’t guarantee any avoidance of the situation.
        2. As you point out, it won’t 100% guarantee that DMA burst transfers can’t occur across the boundary since many SW designs will use such data structures in HEAP (although restricting heap into one the partictions would).
        3. I believe that programmers who are making use of more advanced techniques, such as DMA, should be aware of any chip/architectural restictions and control/solve it intelligently (there are many other things to consider when designing with these devices that the SRAM partition) without resorting to a linker script ‘cludge’.

        Regards

        Mark

        Like

      • Thank you for understanding :-). About your opinion on the linker script one could argue, that there’s no other alternative. If It’s syntax could allow a “block” to have 2 or more parts (with another block in the middle), we would not have a problem. Personally, (KL26 w/o OS), I applied the following (ugly?) solution:
        – Modified my linker to move the .bss in SRAM_U (6KB on my device). There are also the stack and heap (heap not used, C-code w/o classes, printf doesn’t use malloc()).
        – In SRAM_L, I defined 3 blocks – 1st – for interrupt vectors table (192 bytes long),
        2nd – for initialized data (“data”) and the 3rd is for my .SRAM_L_BSS section. In the 3rd, I forced some data buffers with help of the information, provided by Eric on how to do that @https://mcuoneclipse.com/2014/04/19/gnu-linker-can-you-not-initialize-my-variable/

        Like

  12. Hi,

    I am using MK22FN512VLH12 on a simple custom board. I am using KDS with PE components. The compiler went through without any error but linker cause section `.bss’ will not fit in region `m_data’ error. I am not using FreeRTOS to use the configuration mentioned in this post.

    Could you please let me know how can I address this RAM problem.

    Sincerely,
    Kasra

    Like

      • Hi Erich,

        Thanks for your kind reply.

        The only option that I see for changing memory setting is from PE CPU component setting/build options/generate linker file/ROM/RAM Areas. There exist m_interrupt, m_text, m_data_1FFF0400 and m_data. Which one(s) should I change?

        Sincerely,
        Kasra

        Like

  13. Hi Erich,
    I am using K22F. It has total of 128KB SRAM.

    Does this mean that if I do not enable _user_heap_section, I will be able to use 64KB at the max? Will the rest of 64 KB go waste?

    Also what if I enable? RTOS uses upper 64KB and the other global variables, etc will use lower 64KB. Am I right?

    Like

    • As discussed in the comments here, it is possible that you change the linker file to have one piece of memory (128 kB). If you enable that FreeRTOS option to put the memory into its own dedicated heap section, it only will move the heap into that section. Everything else remains the same. So ‘normal’ global variables end up in the lower 64 kByte. You might consider as well the FreeRTOS heap 5 scheme which allows you to have multiple heap areas too.

      Like

  14. Pingback: Using Multiple Memory Regions with the FreeRTOS Heap | MCU on Eclipse

  15. Pingback: Overview of MCUXpresso IDE v10.2.0 | MCU on Eclipse

  16. Hi Erich,

    Firstly, thank you for your amazing content. Quite new to the embedded field, I’m still learning the ropes and your posts are quite instructive.

    I have some fundamental questions on memory allocation for freeRTOS.

    So I use a FRDM-KL25 having 0x4000 SRAM space and inside the Project Properties->Settings->Managed Linker Script, I see the Heap and Stack sizes located in the default region (SRAM) and given default sizes 0x400(1KB).
    However in the FreeRTOSConfig.h file, I am giving configTOTAL_HEAP_SIZE as 0x2800, using heap4.c type I know that freeRTOS manages its heap memory allocation by creating a static array inside SRAM. And although the build says I’ve used up 96% of SRAM (due to this freeRTOS allocation), my application runs! My questions are:
    1. Why is the application able to run even though I’ve assigned in the Linker only 0x400 size stack area, much lesser than the demanded 0x2800 size?
    2. (maybe related to question 1): If I’ve only defined 0x400 size in Project Linker, then how is FreeRTOS heap able to access 0x2800 size memory?
    3. If FreeRTOS isn’t using this linker-defined stack area in the SRAM, then who is?

    I think you might see my struggle about this apparant mismatch as I’m trying to map/piece together NXP’s assignment of memory with FreeRTOS!

    Thank you very much again. Grateful for your work to the community.

    Like

    • Hi John,
      thanks for your questions!
      You are correct that for the Heap 4 in FreeRTOS, the Kernel allocates a static array of that size in RAM.
      1) You need to know that what you allocate as ‘stack’ in the linker, is the stack used by the MSP. Basically this is used for Interrupts and for starting the processor (see https://mcuoneclipse.com/2016/08/28/arm-cortex-m-interrupts-and-freertos-part-3/) and has nothing to do with FreeRTOS itself.
      2) The FreeRTOS task stacks are inside the FreeRTOS heap, and have nothing to do with the ‘stack’ and ‘heap’ you have in the linker file (except for the heap, if you are going to use heap scheme 3 which is using the standard library heap).
      3) See point one: it is used by the MSP, means it is used by the code of the startup and your main() until it starts the scheduler. And it is used afterwards by the interrupt stack too.
      I hope this helps?

      Like

      • Thank you for your answers. Yes it helps! Some follow ups:

        1. So total space in SRAM consumed (that I see in the console after build) would be: linker-defined stack&heap size + freeRTOS heap size + variables in .data and .bss?
        2. How does the freeRTOS allocated heap know which memory area in SRAM to use and avoid stepping into the linker-defined stack/heap space, if this freeRTOS heap memory region isn’t defined in the Linker? Let me guess: the static array ucHeap[ configTOTAL_HEAP_SIZE ] (used for FreeRTOS memory management) is treated to be in the .bss layer and hence allocated in the .bss space in the SRAM?

        Thank you again!

        John

        Like

        • 1. yes.
          2. The FreeRTOS heap is a variable like others too. If you are not assigning it a special section, it will treated as such.

          How exactly things are allocated and where, depends on how the linker file is written.

          Like

What do you think?

This site uses Akismet to reduce spam. Learn how your comment data is processed.