Stacks and heap, and other memory areas

ChibiOS public support forum for topics related to the STMicroelectronics STM32 family of micro-controllers.

Moderators: barthess, RoccoMarco

king2
Posts: 98
Joined: Mon May 28, 2012 1:57 pm
Been thanked: 2 times

Stacks and heap, and other memory areas

Postby king2 » Mon Apr 17, 2017 1:20 am

Hi!

Sorry for newbie question, but today I met strange situation, which gave me a big kick to know more about STM32 stacks, heaps and how ChibiOS deals with all this. I had irqstack with size of 0x400, placed at start of RAM and everything was fine. But when I have moved it from start of memory, it was placed just after variables and before heap (linker's heap), and this was reason of some strange effects with my firmware. If I place irqstack at start of RAM or increase its size to 0x800 (just as a test) - problem disappeares. Wow, interrupts used more 1k of memory for stack? Hmm, but I do not know anything about how ChibiOS using interrupts, maybe OS uses interrupt stack for storing some bigdata from aliens.. :)

So, ok, I have basic areas in my linker script, placed in RAM_region: IRQSTACK (0x400), DATABSS (variables lives here as I understand, with specific areas for threads, but I'm not sure if thread stacks lives here), HEAP (0x2000), SYSHEAP (without specific size settings, but actually set to size of 0 in map file), CSTACK (0x2000).

ChibiOS has its own heap and memory areas for threads, and I gave up here trying to understand which sizes I should set in linker script for different areas. I have read http://www.chibios.org/dokuwiki/doku.ph ... :kb:stacks, but I need some specific information for STM32 about how to set right sizes to this memory areas.

Can you help me and tell what lives in which areas in case of STM32 port?
Maybe some of this areas just not used with ChibiOS and can be set to zero (like not used SYSHEAP was set by linker)?
Maybe somewhere lives too much (like in IRQSTACK) and I should give more memory there?
Maybe some areas can be moved to CCMRAM (64k, not used at all) to increase memory available for OS heap?

Thank you in advance!

update: I have found another strange thing: increasing irqstack size not solves the problem, but shifts problematic effect to another, lower images, also I have following in MAP file:

Code: Select all

"P2-P4", part 1 of 2:                         0x124c0
  DATABSS                         0x20000000  0x124c0  <Block>
    DATABSS-1                     0x20000000    0x40e  <Init block>
...
  SYSHEAP                         0x200124c0      0x0  <Block>
    SYSHEAP              rw data  0x200124c0      0x0  cstartup.o [1]
                                - 0x200124c0  0x124c0

"P2-P4", part 2 of 2:                          0x3000
  IRQSTACK                        0x200124c0   0x1000  <Block>
    IRQSTACK             uninit   0x200124c0   0x1000  <Block tail>
  HEAP                            0x200134c0   0x2000  <Block>
    HEAP                 uninit   0x200134c0   0x2000  <Block tail>
                                - 0x200154c0   0x3000
...
__heap_base__           0x200124c0           Data  Gb  cstartup.o [1]
__heap_end__            0x2002e000           Data  Gb  cstartup.o [1]

So, ChibiOS initialized its heap at start of sysheap (which size is 0), and irqstack, located at same place. I wonder how it can work :)
But I still cannot understand which of these blocks should be used and which not.

king2
Posts: 98
Joined: Mon May 28, 2012 1:57 pm
Been thanked: 2 times

Re: Stacks and heap, and other memory areas

Postby king2 » Mon Apr 17, 2017 4:19 am

I ended up with following ICF file:

Code: Select all

// define addresses

//define symbol __ICFEDIT_region_FLASH_start__ = 0x08004000;
define symbol __ICFEDIT_region_FLASH_start__  = 0x08000000;
define symbol __ICFEDIT_region_FLASH_end__    = 0x080FFFFF;

define symbol __ICFEDIT_region_CCMRAM_start__ = 0x10000000;
define symbol __ICFEDIT_region_CCMRAM_end__   = 0x1000FFFF;

define symbol __ICFEDIT_region_SRAM_start__   = 0x20000000;
define symbol __ICFEDIT_region_SRAM_end__     = 0x2002FFFF;
                                       
define symbol __ICFEDIT_size_cstack__   = 0x2000;
define symbol __ICFEDIT_size_heap__     = 0x2000;
define symbol __ICFEDIT_size_irqstack__ = 0x400;


// DEFAULTS
define memory mem with size = 4G;
initialize by copy { readwrite };
////initialize by copy with packing = none { section __DLIB_PERTHREAD }; // Required in a multi-threaded application
do not initialize  { section .noinit };
keep { section .intvec };

// BACKUP SRAM
define symbol __ICFEDIT_region_BKPR_start__  = 0x40024000;
define symbol __ICFEDIT_region_BKPR_end__    = 0x40024FFF;
define region BKPR_region  = mem:[from __ICFEDIT_region_BKPR_start__  to __ICFEDIT_region_BKPR_end__ ];
place in BKPR_region   { section .backup_sram }; initialize manually { section .backup_sram };

// SDRAM
define region SDRAM_video  = mem:[from 0xD0000000 size 0x02FFFFF ];
define region SDRAM_vars   = mem:[from 0xD0300000 size 0x04FFFFF ];
place in SDRAM_video   { section .sdram_video }; initialize manually { section .sdram_video };
place in SDRAM_vars    { section .sdram_vars };  initialize manually { section .sdram_vars };

// FLASH
define symbol __ICFEDIT_intvec_start__ = __ICFEDIT_region_FLASH_start__;
place at address mem:__ICFEDIT_intvec_start__ { readonly section .intvec };
define region FLASH_region = mem:[from __ICFEDIT_region_FLASH_start__ to __ICFEDIT_region_FLASH_end__];
define block ROM_CONTENT with fixed order {
    readonly section checksum_start_mark,
    readonly,
    readonly section checksum_end_mark,
    readonly section checksum,
    readonly section firmware_end_mark
};
place in FLASH_region  { block ROM_CONTENT };

// RAM
define region CCMRAM_region = mem:[from __ICFEDIT_region_CCMRAM_start__ to __ICFEDIT_region_CCMRAM_end__];
define region SRAM_region   = mem:[from __ICFEDIT_region_SRAM_start__ to __ICFEDIT_region_SRAM_end__];

define block CSTACK    with alignment = 8, size = __ICFEDIT_size_cstack__   { section CSTACK };
define block IRQSTACK  with alignment = 8, size = __ICFEDIT_size_irqstack__ { section IRQSTACK };
define block HEAP      with alignment = 8, size = __ICFEDIT_size_heap__     { section HEAP };
define block SYSHEAP   with alignment = 8                                   { section SYSHEAP };
define block DATABSS   with alignment = 8 { readwrite, zeroinit };

// place all this
place in CCMRAM_region  { block IRQSTACK, block HEAP, section .ccmram };
define block SRAM_content with fixed order {
    block DATABSS,
    block SYSHEAP
};
place at start of SRAM_region                  { block SRAM_content };
place at end of SRAM_region                    { block CSTACK };

Problem was that SYSHEAP defined as zero size structure, and IAR can place it everywhere it wants, in my case it was placed before IRQSTACK. ChibiOS makes its heap in place between start of SYSHEAP and start of CSTACK, so IRQSTACK place was used by ChibiOS as its heap. I wonder how this was worked, by it was with some strange effects like image distortion in display.

I have placed in main SRAM (192k) DATABSS section followed by SYSHEAP (working as just a marker), and CSTACK at end of this place.
IRQSTACK and HEAP was moved to CCMRAM, and I have created section '.ccmram' there, so I can move there some space consuming variables like this:

Code: Select all

unsigned char shproto_buffer_kbd_rx[256] @ ".ccmram";
unsigned char shproto_buffer_kbd_tx[128] @ ".ccmram";

This will free up more space for ChibiOS heap.
Note that CCMRAM cannot be used with any type of DMA.
Can I place threads buffers there? If yes, how to do this?

As SYSHEAP have zero size and everything works, I know that SYSHEAP is useless with ChibiOS, but I still not sure about HEAP and IRQSTACK. I see some data inside, but I'm not sure who and how uses these areas, and what to expect there :)

User avatar
Giovanni
Site Admin
Posts: 11153
Joined: Wed May 27, 2009 8:48 am
Location: Salerno, Italy
Has thanked: 391 times
Been thanked: 322 times
Contact:

Re: Stacks and heap, and other memory areas

Postby Giovanni » Mon Apr 17, 2017 7:41 am

Hi,

There are three stack types:
Main - For exceptions and interrupts. Interrupts can be nested so you have to plan the size depending on how many interrupt priorities you use.
Process - This is the stack for the main() thread.
Thread - This is the private stack for each thread.

Position is not relevant but alignment and size is, the OS takes care to align things correctly.

About IRQs, you MUST take care to not use priority levels 0...2 because those are able to preempt the kernel, if you use them then you need to not call any OS-provided function or macro.

CCMRAM is perfect for stacks as long you don't use DMA buffers in automatic variables, for sure IRQ stack should go there.

Giovanni

king2
Posts: 98
Joined: Mon May 28, 2012 1:57 pm
Been thanked: 2 times

Re: Stacks and heap, and other memory areas

Postby king2 » Mon Apr 17, 2017 8:08 am

Thanks you for answer!

So, main stack is a CSTACK, as I understand, process stack is a CSTACK too in this case, and thread stack is a stack located in thread variable, right?
What is HEAP and who uses it?

User avatar
Giovanni
Site Admin
Posts: 11153
Joined: Wed May 27, 2009 8:48 am
Location: Salerno, Italy
Has thanked: 391 times
Been thanked: 322 times
Contact:

Re: Stacks and heap, and other memory areas

Postby Giovanni » Mon Apr 17, 2017 8:15 am

Heap is used by the OS memory allocators, if enabled.

Giovanni


Return to “STM32 Support”

Who is online

Users browsing this forum: No registered users and 3 guests