1

In the Keil RTX RTOS configuration file, user could configure the default user thread stack size. In general, the stack holds auto/local variables. The "ZI data" section holds uninitialized global variables.

So if I change the user thread stack size in the RTX configuration file, the stack size will increase and the "ZI data" section size will not increase.

I test it, the test result shows that if I increase user thread stack size. The "ZI data" section size will increase synchronously with the same size.

In my test program, there is 6 threads and each has 600 bytes stack. I use Keil to build the program and it shows me that:

      Code (inc. data)   RO Data    RW Data    ZI Data      Debug   

     36810       4052       1226        380       6484     518461   Grand Totals
     36810       4052       1226        132       6484     518461   ELF Image Totals (compressed)
     36810       4052       1226        132          0          0   ROM Totals

==============================================================================

    Total RO  Size (Code + RO Data)                38036 (  37.14kB)
    Total RW  Size (RW Data + ZI Data)              6864 (   6.70kB)
    Total ROM Size (Code + RO Data + RW Data)      38168 (  37.27kB)  

But if I changed each thread stack size to 800 bytes. Keil shows me as follows:

==============================================================================


      Code (inc. data)   RO Data    RW Data    ZI Data      Debug   

     36810       4052       1226        380       7684     518461   Grand Totals
     36810       4052       1226        132       7684     518461   ELF Image Totals (compressed)
     36810       4052       1226        132          0          0   ROM Totals

==============================================================================

    Total RO  Size (Code + RO Data)                38036 (  37.14kB)
    Total RW  Size (RW Data + ZI Data)              8064 (   7.88kB)
    Total ROM Size (Code + RO Data + RW Data)      38168 (  37.27kB)

==============================================================================

The "ZI data" section size increase from 6484 to 7684 bytes. 7684 - 6484 = 1200 = 6 * 200. And 800 - 600 = 200. So I see the thread stack is put in "ZI Data" section.

My question is: Does it mean auto/local variables in the thread will be put in "ZI Data" section, when thread stack is put in "ZI data" section in RAM ? If it's true, it means there is no stack section at all. There are only "RO/RW/ZI Data" and heap sections at all.

This article gives me the different answer. And I am a little confused about it now. https://developer.mbed.org/handbook/RTOS-Memory-Model

lrouter
  • 349
  • 1
  • 5
  • 20
  • _"the stack holds auto/local variables"_ - from the perspective of a running thread, where it is "the" stack, sure. I see no reason that those stacks couldn't be statically-allocated variables from the point of view of the OS, though. You've merely presented an observation here; what's the specific question? – Notlikethat Aug 19 '16 at 08:18

2 Answers2

1

The linker determines what memory sections exist. The linker creates some memory sections by default. In your case, three of those default sections are apparently named "RO Data", "RW Data", and "ZI Data". If you don't explicitly specify which section a variable should be located in then the linker will assign it to one of these default sections based on whether the variable is declared const, initialized, or uninitialized.

The linker is not automatically aware that you are using an RTOS. And it has no special knowledge of which variables you intend to use as thread stacks. So the linker does not automatically create independent memory sections for your thread stacks. Rather, the linker will treat the stack variables like any other variable and include them in one of the default memory sections. In your case the thread stacks are apparently being put into the ZI Data section by the linker.

If you want the linker to create special independent memory sections for your thread stacks then you have to explicitly tell the linker to do so via the linker command file. And then you also have to specify that the stack variables should be located in your custom sections. Consult the linker manual for details on how to do this.

kkrambo
  • 6,643
  • 1
  • 17
  • 30
  • Thanks. Generally there are some default sections: "RO Data", "RW Data", and "ZI Data", "stack", "heap". The linker determines flash memory and ram memory layout. If thread stack is put in to "ZI Data", does it mean all auto variables of functions called in the thread would be in "ZI Data" section ? Then what's in the "stack" section ? – lrouter Aug 20 '16 at 14:03
  • There is a stack for the main program. This is the stack that is in use when main() is called, and before the RTOS is started. Your linker command file may explicitly specify a memory section for the main stack. Each thread has it's own stack separate from the main stack. Your linker is locating these thread stacks in the ZI Data section. Once the RTOS is running, thread local variables will be created on the thread stack. Yes, thread local variables will be in ZI Data because the thread stack is in ZI Data. The main stack is where local variables are located before the RTOS is running. – kkrambo Aug 20 '16 at 16:02
  • After the RTOS is running, the "main function" would never be called again. So the main stack would never be used once the RTOS is ruining. To save memory, it means that the main stack and thread stack memory space would be overlapped. – lrouter Aug 21 '16 at 04:56
  • Yes, typically the RTOS does not return to main so the main stack may be unused after starting the RTOS. You should be able to make the main stack size relatively small. Theoretically I suppose you could arrange for one of the thread stacks to overrun the main stack so that the main stack memory is reused after starting the RTOS. But practically that seems like a complicated maneuver to save maybe a couple hundred words of RAM. YAGNI. I'd recommend that you keep things simple and keep the stacks separate. That will make debugging and maintenance easier in the long run. – kkrambo Aug 22 '16 at 00:48
  • Yes, you are right. And I forgot that the main stack would be used by RTOS kernel. – lrouter Aug 22 '16 at 02:35
  • On a lot of Cortex-M RTOS ports, the linker defined stack (that is referenced as the first item in the vector table) will end up becoming the MSP (interrupt stack) once the scheduler starts. There are some RTOS (ChibiOS is the only one that comes to mind) where the call to start the scheduler returns, and that thread of execution becomes the "main task" using the original stack. – rjp Aug 30 '16 at 19:11
0

Tasks stacks have to come from somewhere - in RTX by default they are allocated statically and are of fixed size.

The os_tsk_create_user() allows the caller to supply a stack that could be allocated in any manner (statically or from the heap; allocating from the caller stack is possible, but unusual, probably pointless and certainly dangerous) so long as it has 8 byte alignment. I find RTX's automatic stack allocation almost useless and seldom appropriate in all but the most trivial application.

Clifford
  • 88,407
  • 13
  • 85
  • 165