Search code examples
memoryembeddediarmicrium

IAR for ARM running Micrium OS-III - Understanding memory usage


  • How can I determine the stack size being used by the tasks through the MAP file generated?
  • How to determine the sizes of the stack and heap in the RAM of ARM
  • How to determine if more stack size is required to be assigned for the tasks?

Solution

  • If you are running the latest version of IAR EWARM, there is a built in tool that you will find very helpful with these questions.

    1. How can I determine the stack size being used by the tasks through the MAP file generated?

    For your first question, you will need to search in the map file for the name of each task's stack. In this case, the map file isn't that helpful, as you would likely be better off searching your project for the CPU_STK type, as that will give you results with all properly defined stacks. If you do look in the map file, you may see a line like this:

    MainStack               0x20000000  0x1000  Data  Lc  main.o [1]
    

    This means that MainStack (presumably a stack for a MainTask) is sized as 0x1000 or 4096 bytes. The first column is symbol name, the second is location in the address space, the third is size, the fourth is type (Data, Code), the fifth is scope (Lc = local, Gb = Global), and the last column is object module it is located in.

    If instead you search the project for instances of CPU_STK you would find the following:

    static  CPU_STK          MainStack[4096];
    

    This gives you the same information that MainStack is size 4096, but by searching for CPU_STK, it will also give you results for other tasks, so you may actually see the following in your results:

    static  CPU_STK          MainStack[4096];
    static  CPU_STK          AuxStack[512];
    

    So, now you can see that there's also an AuxStack (presumably for an AuxTask), and it is 512 bytes. This would require to searches in the map file for specific stack names to get results, so I would find this easier.

    1. How to determine the sizes of the stack and heap in the RAM of ARM?

    For this one, you'll want to dig into either the linker configuration file, or the linker section in the options. The easier way is through the options. Go to your project options, and then the Linker item on the left. Under the configuration tab, select Edit..., and then go to the Stack/Heap tab. This will give you easy access to the sizes that IAR will use to allocate the HEAP and CSTACK memory regions in the linker.

    Alternatively, you can dig into the .icf file and you may find a set of lines like so:

    /*-Sizes-*/
    define symbol __ICFEDIT_size_cstack__ = 0x400;
    define symbol __ICFEDIT_size_heap__   = 0x400;
    
    define block CSTACK    with alignment = 8, size = __ICFEDIT_size_cstack__   { };
    define block HEAP      with alignment = 8, size = __ICFEDIT_size_heap__     { };
    

    It could also look completely different! It's hard to give a generalized answer for this one, so you're best off looking in the options. In the code above, though, you can see CSTACK and HEAP have their sizes defined by the symbols defined earlier in the file. You can follow these definitions to get the size. Your linker file could be very different from this, though, so as I said, it's really hard to give a general answer.

    1. How to determine if more stack size is required to be assigned for the tasks?

    Newer versions of IAR have a great utility that can determine the stack depth required by any function. In project options, under Linker in the Advanced tab, you can check "Enable stack usage analysis". When you enable this, your map file will contain root functions and their maximum call chain. For example, my MainTask looks like this:

    Uncalled function
      "MainTask" in main.o [1]: 0x0000ac41
      Maximum call chain                            *?* 396 bytes
    

    So, this is telling me that MainTask is an uncalled function (which it is not called directly, but by function pointer, which IAR cannot resolve automatically), and it requires 396 bytes of stack. Below it, it will show you the call chain that adds up to 396 bytes.

    Of note with this tool is that if you use function pointers and indirect calls, IAR cannot automatically figure out where these lead. There are a set of pragma directives that can be used to tell it what possible functions are called at an indirect calling point, and you'll need to put these in to get a 100% accurate stack depth.

    An alternative is to run the program on your hardware, but let the OS monitor for stack overflows. Micrium has a page about detecting stack overflows here: Detecting Task Stack Overflows. Additionally, here is the documentation on a function to get information about a task's stack usage: OSTaskStkChk()