Best practice for Memory management and RTOS tasks

reza_neam
Posts: 12
Joined: Thu Dec 31, 2020 9:19 pm

Best practice for Memory management and RTOS tasks

Postby reza_neam » Thu Apr 29, 2021 4:23 pm

Hi everyone,

I am writing an app that is highly dependent on the big objects/classes stored in the external PS-RAM.
Since I can't have the classes as a static variable so I need to find the best way to pass-in the object.

my first thought was to make a static pointer pointing to the class in the PS-RAM and then use inside the TaskFunction or it would be much best if I pass the pointer to the object when creating the TaskHandle (xTaskCreatePinnedToCore)?

thanks,

chegewara
Posts: 2364
Joined: Wed Jun 14, 2017 9:00 pm

Re: Best practice for Memory management and RTOS tasks

Postby chegewara » Thu Apr 29, 2021 4:32 pm

https://www.freertos.org/xTaskCreateStatic.html

To use this function you have to enable option in menuconfig (i am not sure if it is still possible).
https://github.com/espressif/esp-idf/issues/6264

reza_neam
Posts: 12
Joined: Thu Dec 31, 2020 9:19 pm

Re: Best practice for Memory management and RTOS tasks

Postby reza_neam » Thu Apr 29, 2021 5:38 pm

@chegewarta thanks for your reply.
If I understood correctly, the xTaskCreateStatic is storing on top of the stack.

in my case, I can store Task on the internal heap but it needs to have access to the data stored on external ps-ram.

chegewara
Posts: 2364
Joined: Wed Jun 14, 2017 9:00 pm

Re: Best practice for Memory management and RTOS tasks

Postby chegewara » Thu Apr 29, 2021 6:06 pm

xTaskCreate and xTaskCreatePinnedToCore are allocating stack from internal memory. We also have xTaskCreateStatic, which is using stack passed by programmer and can be created in both, internal memory and PSRAM.
Example:
  1. #include "freertos/FreeRTOS.h"
  2. #include "freertos/task.h"
  3. #include <stdio.h>
  4.  
  5. #define STACK_SIZE 200
  6. StaticTask_t xTaskBuffer;
  7. StackType_t *xStack;
  8.  
  9. void test_task(void*p)
  10. {
  11.     while(1)
  12.     {
  13.         vTaskDelay(100);
  14.     }
  15. }
  16.  
  17. void app_main(void)
  18. {
  19.   xStack = (uint8_t*)heap_caps_calloc(1, 10*1024, MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT | MALLOC_CAP_32BIT);
  20.   xTaskCreateStatic(test_task, "test", 10*1024, NULL, 6, xStack, &xTaskBuffer);
  21. }

reza_neam
Posts: 12
Joined: Thu Dec 31, 2020 9:19 pm

Re: Best practice for Memory management and RTOS tasks

Postby reza_neam » Fri Apr 30, 2021 3:56 pm

@chegewarta thanks for your message. Now everything looks more clear.
So, as I said I need to have access to a non-static variable (big_class here) inside the task function.
Not having the task stored in the psram.

I thought the following code might work without using the internal heap.

Code: Select all

volatile BigClass* big_class = (BigClass*)ps_calloc(1, sizeof(BigClass));
 
void test_function(void*p)
{
    while(1)
    {
    	BigClass* local_big_class= (BigClass*)p;
    	local_big_class->doSomthing();
        vTaskDelay(100);
    }
}
 
void setup(void)
{
  xTaskCreatePinnedToCore(test_function, "test", 1024, (void *)&big_class , 6, NULL, 1);
}
The other solution I was thinking of is something like this.

Code: Select all

static BigClass* big_class_ptr;
BigClass* big_class = (BigClass*)ps_calloc(1, sizeof(BigClass));
 
void test_function(void*p)
{
    while(1)
    {
    	//big_class->doSomthing();
    	big_class_ptr->doSomthing();
        vTaskDelay(100);
    }
}
 
void setup(void)
{
big_class_ptr = big_class;
  xTaskCreatePinnedToCore(test_function, "test", 1024, NULL, 6, NULL, 1);
}

chegewara
Posts: 2364
Joined: Wed Jun 14, 2017 9:00 pm

Re: Best practice for Memory management and RTOS tasks

Postby chegewara » Fri Apr 30, 2021 4:26 pm

1. Sorry, i missed the fact you are using arduino
2. I am not C++ expert, but as far as i know you cant use code like this, because instantiating class object in C++ is more than just allocating memory

Code: Select all

volatile BigClass* big_class = (BigClass*)ps_calloc(1, sizeof(BigClass));
3. You can try code like this, which will create instance of class on task stack (im not 100% sure about it):
  1. #include "freertos/FreeRTOS.h"
  2. #include "freertos/task.h"
  3. #include <stdio.h>
  4.  
  5. #define STACK_SIZE 200
  6. StaticTask_t xTaskBuffer;
  7. StackType_t *xStack;
  8.  
  9. void test_task(void*p)
  10. {
  11.     BigClass* big_class = new BigClass(); // instantiate object in task stack, but i am not 100% sure
  12.     while(1)
  13.     {
  14.         local_big_class->doSomthing();
  15.         vTaskDelay(100);
  16.     }
  17. }
  18.  
  19. void setup() {
  20.   // put your setup code here, to run once:
  21.   xStack = (uint8_t*)heap_caps_calloc(1, 100*1024, MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT | MALLOC_CAP_32BIT);
  22.   xTaskCreateStatic(test_task, "test", 100*1024, NULL, 1, xStack, &xTaskBuffer);
  23. }
  24.  
  25. void loop() {
  26.   // put your main code here, to run repeatedly:
  27. }
As you can see task stack is allocated from PSRAM, not internal memory and can be very big (100kB in example).

4. Another idea i have, because i dont know your code, especially BigClass, but i am assuming it is using some arrays, can be using variable in class as a pointers and in constructor allocate memory for such big variables with ps_malloc. This is option i would start with.

reza_neam
Posts: 12
Joined: Thu Dec 31, 2020 9:19 pm

Re: Best practice for Memory management and RTOS tasks

Postby reza_neam » Fri Apr 30, 2021 6:45 pm

Thanks for pointing out the problems. I don't claim any good skills in c++ just want to get things done. :D
I am also a bit puzzled about how new would work in this context. not very certain if it calls ps_malloc or malloc! :? This can also be true in a class with members initialize by new!

Truly, the class is supposed to be instantiated in setup/app_main and I need to keep it alive outside of test_task. So, I should pass it in the test_task (as far as I can imagine).

chegewara
Posts: 2364
Joined: Wed Jun 14, 2017 9:00 pm

Re: Best practice for Memory management and RTOS tasks

Postby chegewara » Fri Apr 30, 2021 6:55 pm

reza_neam wrote: Truly, the class is supposed to be instantiated in setup/app_main and I need to keep it alive outside of test_task. So, I should pass it in the test_task (as far as I can imagine).
That is not that big issue. What you can do is to adapt code i posted earlier, delete setup/loop task and use new task as if it would be a setup and loop, but like i mentioned earlier in point 4, better way would be to refactor class and allocate all bigger variables in constructor from PSRAM. Usual there is few ways to achieve the same result, all depends on skills and preference.

reza_neam
Posts: 12
Joined: Thu Dec 31, 2020 9:19 pm

Re: Best practice for Memory management and RTOS tasks

Postby reza_neam » Fri Apr 30, 2021 7:38 pm

Many Thanks for your help, I got the idea.
I definitely delete setup and loop after setting up queues and tasks.

Who is online

Users browsing this forum: No registered users and 101 guests