This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

TMS320F28388D: Stack memory utilization by FreeRTOS tasks

Part Number: TMS320F28388D
Other Parts Discussed in Thread: SYSCONFIG

Hello,

I need some assistance in figuring out the stack memory utilization by FreeRTOS tasks in TMS320F28388D and optimization for the same.
I have configured the FreeRTOS configuration in SysConfig  and defined some periodic tasks as mentioned in below table.
Once the project is compiled, I monitored the stack usage of these tasks using Stack Usage View in CCS (ti.com) and during runtime, I printed the stack usage of each tasks using uxTaskGetStackHighWaterMark
Based on these, I had some observations as shown below -

FreeRTOS Tasks​

Task Priority

Stack memory assigned​ (Words)

Stack usage view in CCS (TI) after compiling code (Words)

Runtime memory (Words) (Without Hardware interrupts)

Runtime memory (Words) (With Hardware Interrupts)

Task A

5

512​​

44​

58​

186​

Task B

5

512​​

32​

58​

154​

Task C

4

512​​

24​

68​

218​

Task D

3

512​​

120​

124​

316​

Task E

2

512​​

24​

68​

216​

Task F

1

512​​

26​

70​

210​

Based on the observations, I found out that the stack memory utilization by FreeRTOS tasks is more when hardware interrupts are enabled and it seems that these hardware interrupts is utilizing same FreeRTOS tasks stack memory for context switch/restoring. On investigating further, I found TI FreeRTOS support (Link - TI Free RTOS documentation) and a  FreeRTOS form (Link - Porting Problem: System stack vs Task stacks - FreeRTOS) which mentions -



So, I need to understand how c28x FreeRTOS port handles FreeRTOS tasks when hardware interrupts occurs and how the stack memory is utilized. Also, Kindly let me know if the above observations are expected or the stack memory utilization can be further optimized using FreeRTOS configuration.

Thanks!

  • In C28 devices, the ISR uses the task stack.

    Regards,

    Veena

  • Hello Veena,

    Could you please be more specific and explanatory for the customer?

    Thank you kindly.

    Regards,

    Chris

  • So, kindly let me know the mechanism or steps to determine the stack usage by these tasks as Stack Usage View in CCS (ti.com) will not provide correct estimation of stack usage by these tasks. Currently, as shown in table, some tasks are assigned with almost 10x stack size than initially determined by stack usage view. Is there any application note that I can look into for calculating stack usage by these tasks?

  • Hi Shivang,

    The stack view in CCS computes the stack requirement based on function calls. Since CCS does not have the knowledge on when the interrupt occurs, it cannot get you the actual stack size you need to allocate. You can get the stack size requirement for every ISR. So basically, you can add the max of that to your stack size. But if you are using interrupt nesting, it gets bit tricky.

    I am also checking with the experts here on the possibility of having a separate stack for ISRs. So you need not allocate that buffer to all the task stacks. Even with this solution, finding the exact stack requirement with interrupt nesting might still be difficult. But it solves the issue of allocating that in every task stack.

    I will get back to you in a day.

    Regards,

    Veena

  • Hi Veena,

    Sure. My initial understanding was ISRs will utilize system stack and allocated size accordingly. But while CCS debugging, I found out (in Memory browser) that system stack is hardly utilized (Approx. 4% of assigned size). 
    If it is possible to have separate stack for ISR, then I can allocate some part of system stack for ISRs and it will optimize the overall stack usage.
    Do let us know about the same. Awaiting for the response!
    Thanks! 

  • System stack is used for main , and is only used till scheduler starts. There is no stack reassignment happening when an interrupt occurs, hence the ISR continues using the stack it was last using.

    To reduce the total memory allocation, you can update the ISR and map the stack pointer to the system stack and remap it back at the end of the ISR. Currently we do not have an example that showcases this.

    Example pseudo code :

    ISR :

      save SP

      SP = ISR Stack pointer

      --ISR code--

      restore SP

    If you are using interrupt nesting, you need use some global to keep track of nesting and ensure and SP value is updated only during the first interrupt and remains unchanged when an interrupt nests.

    Eg:

    ISR :

      if intNesting == 0 :

           save SP

           SP = ISR Stack pointer

      intNesting++

      Enable interrupt nesting

      --ISR code--

      Disable interrupts

      intNesting--

      if intNesting == 0 :

         restore SP

    SP can only be updated using assembly instruction. And this needs to be the first instruction in the ISR. Compiler inserts some startup code for the ISR functions and uses the stack pointer for saving the registers and for allocating local variables. Let me check with compiler team if there is a way to add custom code before this. At present, this can be implemented in assembly.

    Regards,

    Veena

  • Are you using nested interrupts?

    Regards,

    Veena

  • Yes, I have implemented Interrupt Nesting. 

    If possible, kindly provide snippet of assembly instruction to save, restore and map SP to system stack during ISR execution.

    Regarding startup code for ISR functions, I am referring TMS320C28x Optimizing C/C++ Compiler v22.6.0.LTS User's Guide (Rev. Z) (Section 7.7) and it seems compiler does not generate code that is specific to interrupt as shown below -



    But kindly check with the team and let me know about the same. 

    Thanks!

  • What I meant was, compiler inserts some register save and restore code at the start and end of the ISR function. It does not add any interrupt channel specific code. This register save and restore happens on the stack. So we should make the SP switch before this.

    Eg : 

    I am having some discussion with compiler team on how to implement this. I would prefer having some kind of compiler attribute to automatically add this rather than users adding assembly code to do so for every ISR. Will get back to you in few days.

    There are few alternate solutions  - 

    1) Have a common ISR for all the interrupts which does the SP switch and then branch to user ISR function. This common ISR can be implemented in assembly

    2) Implement the ISR functionality in a task. In the ISR function, you just post a semaphore or task notify to the respective task.

    Would you be interested in exploring these options further?

    Regards,

    Veena

  • I see. Thanks for the clarification and providing alternate solutions. 
    I would rather prefer to have initial solution of having some kind of compiler attribute to change SP during ISR execution. 
    Do let me know once you get updates from the compiler team for its implementation.
    Looking forward for your response!

    Thanks!

  • I too recommend the initial solution. But this is an enhancement to the compiler and might take some time to get implemented. I will keep you posted on the estimated timeline.

    Regards,

    Veena