Static and Restricted task creation pinned to core

Dario Lobos
Posts: 8
Joined: Wed Sep 10, 2025 6:24 pm

Static and Restricted task creation pinned to core

Postby Dario Lobos » Thu Sep 11, 2025 1:25 am

I am reading FreeRtos (IDF) ESP32 documentation.
Some issues I have to clarify the reading.
I understood that IDF ESP32 port use bytes instead of words in memory allocation.
When is dynamically allocated is understood that change does not affect, but as is said this is the lazy memory allocation. Basically I understood that each context switch must save and restore all data in each task. So are versions to do task allocated statically that will reduce, if my appreciation is correct, the time of each context switch considerably if have enough memory to work with. Also will have less conflict of both cores using memory under switch.
In the documentation is not described TaskCreatepinnedToCore and TaskCreatepinnedToCoreStstic AND DON'T MENTION IF EXISTS TaskCreatePinnedToCoreRestricted
The documentation of Static creation use an Array and code is copied from FreeRtos Reference Manual in which depth is handled in words and have this detailed example

/* Dimensions the buffer that the task being created will use as its stack. NOTE: This is the
number of words the stack will hold, not the number of bytes. For example, if each stack item
is 32-bits, and this is set to 100, then 400 bytes (100 * 32-bits) will be allocated. */
#define STACK_SIZE 200
/* Structure that will hold the TCB of the task being created. */
StaticTask_t xTaskBuffer;
/* Buffer that the task being created will use as its stack. Note this is an array of
StackType_t variables. The size of StackType_t is dependent on the RTOS port. */
StackType_t xStack[ STACK_SIZE ];

THE IDF ESP32 DOCUMENTATION DON'T HAVE THE FIRST LINE EXPLANATION AND ARRAY SEENS TO BE IN BYTES BEING CORRECT THE DOCUMENTATION AND ARRAY FOR MEMORY ALLOCATION IS ALIGNED BY BYTE.
BUT THE DETAILS OF PINNED TO CORE PARAMETERS IS NOT SHOWN.

IS USAGE OF NOTIFICATIONS IS POSSIBLE BETWEEN STATIC DEFINED TASK?

The restricted memory pinned to core is not described. DOES IT EXIST?

Is mentioned task creation restricted but in other way as in FreeRtos Reference Manual. In thid reference manual is required memory allocation depending on compiler, GCC for example


char cTaskStack[ 1024 ] __attribute__((align(1024));

That is a byte array ALIGNED.

Then requires two structures OUT OF THE MAIN OR ANY FUNCTION to be statically allocated

/* Declare the stack that will be used by the protected task being created. The stack alignment
must match its size, and be a power of 2. So, if 128 words are reserved for the stack then it
must be aligned on a ( 128 * 4 ) byte boundary. This example uses GCC syntax. */
static portSTACK_TYPE xTaskStack[ 128 ] __attribute__((aligned(128*4)));
/* Declare an array that will be accessed by the protected task being created. The task should
only be able to read from the array, and not write to it. */
char cReadOnlyArray[ 512 ] __attribute__((aligned(512)));
/* Fill in a TaskParameters_t structure to define the task - this is the structure passed to the
xTaskCreateRestricted() function. */
static const TaskParameters_t xTaskDefinition =
{
vTaskFunction, /* pvTaskCode */
"A task", /* pcName */
128, /* usStackDepth - defined in words, not bytes. */
NULL, /* pvParameters */
1, /* uxPriority - priority 1, start in User mode. */
xTaskStack, /* puxStackBuffer - the array to use as the task stack. */
/* xRegions - In this case only one of the three user definable regions is actually used.
The parameters are used to set the region to read only. */
{
/* Base address Length Parameters */
{ cReadOnlyArray, 512, portMPU_REGION_READ_ONLY },
{ 0, 0, 0 },
{ 0, 0, 0 },
}
};

THEN IN MAIN IS CREATED THE STATIC RESTRICTED TASK

void main( void )
{
/* Create the task defined by xTaskDefinition. NULL is used as the second parameter as a
task handle is not required. */
xTaskCreateRestricted( &xTaskDefinition, NULL );

In the IDF ESP 32 ALLOCATION IS INSIDE OF THE HANDLE OF A TASK THAT IT SUPPOSED TO BE CREATED RESTRICTED AND ALLOCATE MEMORY

static const MemoryRegion_t xAltRegions[ portNUM_CONFIGURABLE_REGIONS ] =
{
// Base address Length Parameters
{ ucOneKByte, 1024, portMPU_REGION_READ_WRITE },
{ 0, 0, 0 },
{ 0, 0, 0 }
};
void vATask( void *pvParameters )
{
// This task was created such that it has access to certain regions of
// memory as defined by the MPU configuration. At some point it is
// desired that these MPU regions are replaced with that defined in the
// xAltRegions const struct above. Use a call to vTaskAllocateMPURegions()
// for this purpose. NULL is used as the task handle to indicate that this
// function should modify the MPU regions of the calling task.
vTaskAllocateMPURegions( NULL, xAltRegions );

SO IS MISSING AN EXPLANATION FOR RESTRICTED MEMORY ALLOCATION AND ONLY SHOWS A RELOCATION OF A PREVIOUSLY ALLOCATED MEMORY INSIDE OF A HANDLER. IS IT CORRECT OR SHOULD BE DONE OUT OF MAIN AND DOING AN ALIGNED ARRAY?

IS IT POSSIBLE DO THIS PINNED TO A CORE?

Many thanks in advance for your comments.

Sprite
Espressif staff
Espressif staff
Posts: 10599
Joined: Thu Nov 26, 2015 4:08 am

Re: Static and Restricted task creation pinned to core

Postby Sprite » Thu Sep 11, 2025 5:29 am

When is dynamically allocated is understood that change does not affect, but as is said this is the lazy memory allocation. Basically I understood that each context switch must save and restore all data in each task. So are versions to do task allocated statically that will reduce, if my appreciation is correct, the time of each context switch considerably if have enough memory to work with. Also will have less conflict of both cores using memory under switch.
This is not true. Each context switch needs to save the state of the CPU, in other words, the CPU registers. One of those is the stack pointer, and that will be saved (rather than the entire stack), but the stack itself stays exactly where it is in memory. In other words: the work done in a context switch is (more-or-less) constant, and not dependent on the amount of stack allocated at all.
In the documentation is not described TaskCreatepinnedToCore and TaskCreatepinnedToCoreStstic AND DON'T MENTION IF EXISTS TaskCreatePinnedToCoreRestricted
This is because these are functions that are specific to ESP-IDF and are not part of the base FreeRTOS API. Furthermore, ESP-IDF does not support the Task...Restrict API as it doesn't have a (compatible) MPU for this. TaskCreatePinnedToCoreRestricted does not exist because it cannot be part of the base FreeRTOS API (because no PinnedToCore support there) and also not part of the ESP-IDF extensions (because no ...Restrict support there).

THE IDF ESP32 DOCUMENTATION DON'T HAVE THE FIRST LINE EXPLANATION AND ARRAY SEENS TO BE IN BYTES BEING CORRECT
Yes.
IS USAGE OF NOTIFICATIONS IS POSSIBLE BETWEEN STATIC DEFINED TASK?
Sure. Note that there is no such thing as a 'static task'. Task*AllocateStatic() allocates a task in static memory, but it will create a normal FreeRTOS task in any other way.

MicroController
Posts: 2663
Joined: Mon Oct 17, 2022 7:38 pm
Location: Europe, Germany

Re: Static and Restricted task creation pinned to core

Postby MicroController » Thu Sep 11, 2025 8:32 am

I.o.w, xTaskCreate(...) will allocate the memory needed for the task dynamically from the heap when the task is created, and it will be freed/released when the task is deleted; xTaskCreateStatic(...) does not allocate memory for the task but the memory is provided by the application which means that it can be statically allocated.

Dario Lobos
Posts: 8
Joined: Wed Sep 10, 2025 6:24 pm

Re: Static and Restricted task creation pinned to core

Postby Dario Lobos » Thu Sep 11, 2025 2:21 pm

Many thanks for your answers..I supposed that statically saved only was necessary to save the register or PC program counter and stack pointer because all variables should be static in a memory region and not in registers.
The question about pinned to core restricted is because can be defined the array. Two task use same region one read only for example the other read/write

Is still valid in static handle the array with
vTaskAllocateMPURegions( );?

This can hold 3 regions. I was thinking if it is possible share one static (the same array) buffer to two tasks and for example one stream buffer. Using
xStreamBufferGetStaticBuffers() . Receive can be stored in a pointer rater than a variable and process it in other core. Receive and send are used to block the update of the stream buffer until peripherals receive it.
For example data to display in one core, send to peripherals in other.

In any case maybe I can use restricted and don't pinned to any core. But maybe always will work in core 0. Isn't it?

I just starting to learn this thank for your explanation.
Last edited by Dario Lobos on Thu Sep 11, 2025 2:23 pm, edited 1 time in total.

Sprite
Espressif staff
Espressif staff
Posts: 10599
Joined: Thu Nov 26, 2015 4:08 am

Re: Static and Restricted task creation pinned to core

Postby Sprite » Fri Sep 12, 2025 12:05 am

The question about pinned to core restricted is because can be defined the array. Two task use same region one read only for example the other read/write

Is still valid in static handle the array with
vTaskAllocateMPURegions( );?
The ESP-IDF FreeRTOS as running on ESP32 devices does not have MPU support, so that call will not work to begin with.

MicroController
Posts: 2663
Joined: Mon Oct 17, 2022 7:38 pm
Location: Europe, Germany

Re: Static and Restricted task creation pinned to core

Postby MicroController » Fri Sep 12, 2025 8:26 am

I.o.w., every task in an IDF application can freely access all memory. Tasks can share any memory in any way they like.

In order to avoid issues with multiple tasks reading+writing the same memory concurrently, you should be making use of the FreeRTOS synchronization primitives like mutexes and semaphores, queues, stream/message buffers, or ringbuffers.

The memory allocated by xTaskCreate(...) or provided to xTaskCreateStatic(...) becomes "owned" by FreeRTOS and must not be used by application code as long as the task is not yet deleted.

Dario Lobos
Posts: 8
Joined: Wed Sep 10, 2025 6:24 pm

Re: Static and Restricted task creation pinned to core

Postby Dario Lobos » Wed Sep 17, 2025 4:47 pm

I.o.w., every task in an IDF application can freely access all memory. Tasks can share any memory in any way they like.

In order to avoid issues with multiple tasks reading+writing the same memory concurrently, you should be making use of the FreeRTOS synchronization primitives like mutexes and semaphores, queues, stream/message buffers, or ringbuffers.

The memory allocated by xTaskCreate(...) or provided to xTaskCreateStatic(...) becomes "owned" by FreeRTOS and must not be used by application code as long as the task is not yet deleted.
The read only is an attribute of FreeRtos x taskcreate restricted. In it can be allocated 3 memory regions with
As is shown in FreeRtos IDF

Systems that include MPU support can alternatively create an
MPU constrained task using xTaskCreateRestricted().

static const MemoryRegion_t xAltRegions[ portNUM_CONFIGURABLE_REGIONS ] =
{
// Base address Length Parameters
{ ucOneKByte, 1024, portMPU_REGION_READ_WRITE },
{ 0, 0, 0 },
{ 0, 0, 0 }
};
void vATask( void *pvParameters )
{
// This task was created such that it has access to certain regions of
// memory as defined by the MPU configuration. At some point it is
// desired that these MPU regions are replaced with that defined in the
// xAltRegions const struct above. Use a call to vTaskAllocateMPURegions()
// for this purpose. NULL is used as the task handle to indicate that this
// function should modify the MPU regions of the calling task.
vTaskAllocateMPURegions( NULL, xAltRegions );

The FreeRtos Reference Manual define the Task memory handling as

ulParameters defines how the task is permitted to access the memory region being defined,
and can take the bitwise OR of the following values:
• portMPU_REGION_READ_WRITE
• portMPU_REGION_PRIVILEGED_READ_ONLY
• portMPU_REGION_READ_ONLY
• portMPU_REGION_PRIVILEGED_READ_WRITE
• portMPU_REGION_CACHEABLE_BUFFERABLE
• portMPU_REGION_EXECUTE_NEVER


The question is I will try to do an array with a background of an LCD spi and some other to overlap with user keypad each pixel array is allocated not cero initialized

EXT_RAM_BSS_ATTR static uint16t Arrayscreen[C][R]={,,}
(Can also be uint8t if not possible uint16)

This I will include in the MPU regions in both task as second array.

And another cero initialized as first one.

The same array I will try to use it xStreamBuffer in one task, to receive in other. One task is what handle interrupt to choose which pixel map use. The other receive the constant buffer just to send it to spi. The stream buffer is just to do mutual EXCLUSION and not to save or store.

I seen an answer that tasks in Esp32 IDF don't support MPU, but is in the documentation.

Since I don't have any experience in it I am consulting about it. The question of permissions of memory and usage of cores doing something like this also I what I am trying to ask about because task created restricted is not pinned to core and I suppose that run in core 0.

To do the image array I use this

https://sourceforge.net/projects/lcd-image-converter/

This to reduce

http://www.faststone.org/FSResizerDownload.htm

And this to fonts

https://www.ramtex.dk/iconedit/fonts-as ... e-code.htm

Thank for your comments.
Last edited by Dario Lobos on Wed Sep 17, 2025 5:06 pm, edited 1 time in total.

Dario Lobos
Posts: 8
Joined: Wed Sep 10, 2025 6:24 pm

Re: Static and Restricted task creation pinned to core

Postby Dario Lobos » Wed Sep 17, 2025 4:49 pm

I.o.w., every task in an IDF application can freely access all memory. Tasks can share any memory in any way they like.

In order to avoid issues with multiple tasks reading+writing the same memory concurrently, you should be making use of the FreeRTOS synchronization primitives like mutexes and semaphores, queues, stream/message buffers, or ringbuffers.

The memory allocated by xTaskCreate(...) or provided to xTaskCreateStatic(...) becomes "owned" by FreeRTOS and must not be used by application code as long as the task is not yet deleted.
The read only is an attribute of FreeRtos x taskcreate restricted. In it can be allocated 3 memory regions with
As is shown in FreeRtos IDF

Systems that include MPU support can alternatively create an
MPU constrained task using xTaskCreateRestricted().

static const MemoryRegion_t xAltRegions[ portNUM_CONFIGURABLE_REGIONS ] =
{
// Base address Length Parameters
{ ucOneKByte, 1024, portMPU_REGION_READ_WRITE },
{ 0, 0, 0 },
{ 0, 0, 0 }
};
void vATask( void *pvParameters )
{
// This task was created such that it has access to certain regions of
// memory as defined by the MPU configuration. At some point it is
// desired that these MPU regions are replaced with that defined in the
// xAltRegions const struct above. Use a call to vTaskAllocateMPURegions()
// for this purpose. NULL is used as the task handle to indicate that this
// function should modify the MPU regions of the calling task.
vTaskAllocateMPURegions( NULL, xAltRegions );

The FreeRtos Reference Manual define the Task memory handling as

ulParameters defines how the task is permitted to access the memory region being defined,
and can take the bitwise OR of the following values:
• portMPU_REGION_READ_WRITE
• portMPU_REGION_PRIVILEGED_READ_ONLY
• portMPU_REGION_READ_ONLY
• portMPU_REGION_PRIVILEGED_READ_WRITE
• portMPU_REGION_CACHEABLE_BUFFERABLE
• portMPU_REGION_EXECUTE_NEVER


The question is I will try to do an array with a background of an LCD spi and some other to overlap with user keypad each pixel array is allocated not cero initialized

EXT_RAM_BSS_ATTR static uint16t Arrayscreen[C][R]={,,}
(Can also be uint8t if not possible uint16)

This I will include in the MPU regions in both task as second array.

And another cero initialized as first one.

The same array I will try to use it xStreamBuffer in one task, to receive in other. One task is what handle interrupt to choose which pixel map use. The other receive the constant buffer just to send it to spi. The stream buffer is just to do mutual EXCLUSION and not to save or store.

I seen an answer that tasks in Esp32 IDF don't support MPU, but is in the documentation.

Since I don't have any experience in it I am consulting about it. The question of permissions of memory and usage of cores doing something like this also I what I am trying to ask about because task created restricted is not pinned to core and I suppose that run in core 0.

For the things that continue change like a sensor reading or clock I use a constant black and white array of bits. In this case task is DMA and a function take the needed character (can be only numbers for size. And in the 1 change for a selected color and in the cero for the background of the region where is placed.


Thank for your comments.
Last edited by Dario Lobos on Wed Sep 17, 2025 5:16 pm, edited 1 time in total.

Dario Lobos
Posts: 8
Joined: Wed Sep 10, 2025 6:24 pm

Re: Static and Restricted task creation pinned to core

Postby Dario Lobos » Wed Sep 17, 2025 4:53 pm

The question about pinned to core restricted is because can be defined the array. Two task use same region one read only for example the other read/write

Is still valid in static handle the array with
vTaskAllocateMPURegions( );?
The ESP-IDF FreeRTOS as running on ESP32 devices does not have MPU support, so that call will not work to begin with.
The read only is an attribute of FreeRtos x taskcreate restricted. In it can be allocated 3 memory regions with
As is shown in FreeRtos IDF

Systems that include MPU support can alternatively create an
MPU constrained task using xTaskCreateRestricted().

static const MemoryRegion_t xAltRegions[ portNUM_CONFIGURABLE_REGIONS ] =
{
// Base address Length Parameters
{ ucOneKByte, 1024, portMPU_REGION_READ_WRITE },
{ 0, 0, 0 },
{ 0, 0, 0 }
};
void vATask( void *pvParameters )
{
// This task was created such that it has access to certain regions of
// memory as defined by the MPU configuration. At some point it is
// desired that these MPU regions are replaced with that defined in the
// xAltRegions const struct above. Use a call to vTaskAllocateMPURegions()
// for this purpose. NULL is used as the task handle to indicate that this
// function should modify the MPU regions of the calling task.
vTaskAllocateMPURegions( NULL, xAltRegions );

The FreeRtos Reference Manual define the Task memory handling as

ulParameters defines how the task is permitted to access the memory region being defined,
and can take the bitwise OR of the following values:
• portMPU_REGION_READ_WRITE
• portMPU_REGION_PRIVILEGED_READ_ONLY
• portMPU_REGION_READ_ONLY
• portMPU_REGION_PRIVILEGED_READ_WRITE
• portMPU_REGION_CACHEABLE_BUFFERABLE
• portMPU_REGION_EXECUTE_NEVER


The question is I will try to do an array with a background of an LCD spi and some other to overlap with user keypad each pixel array is allocated not cero initialized

EXT_RAM_BSS_ATTR static uint16t Arrayscreen[C][R]={,,}
(Can also be uint8t if not possible uint16)

This I will include in the MPU regions in both task as second array.

And another cero initialized as first one.

The same array I will try to use it xStreamBuffer in one task, to receive in other. One task is what handle interrupt to choose which pixel map use. The other receive the constant buffer just to send it to spi. The stream buffer is just to do mutual EXCLUSION and not to save or store.

I seen an answer that tasks in Esp32 IDF don't support MPU, but is in the documentation.

Since I don't have any experience in it I am consulting about it. The question of permissions of memory and usage of cores doing something like this also I what I am trying to ask about because task created restricted is not pinned to core and I suppose that run in core 0.

To do the image array I use this

https://sourceforge.net/projects/lcd-image-converter/

This to reduce

http://www.faststone.org/FSResizerDownload.htm

And this to fonts

https://www.ramtex.dk/iconedit/fonts-as ... e-code.htm

For the things that continue change like a sensor reading or clock I use a constant black and white array of bits. In this case task is DMA and a function take the needed character (can be only numbers for size. And in the 1 change for a selected color and in the cero for the background of the region where is placed.

Thank for your comments.

Sprite
Espressif staff
Espressif staff
Posts: 10599
Joined: Thu Nov 26, 2015 4:08 am

Re: Static and Restricted task creation pinned to core

Postby Sprite » Thu Sep 18, 2025 10:01 am


The read only is an attribute of FreeRtos x taskcreate restricted. In it can be allocated 3 memory regions with
As is shown in FreeRtos IDF

Systems that include MPU support can alternatively create an
MPU constrained task using xTaskCreateRestricted().
Not sure how clear I must make this: ESP-IDF DOES NOT INCLUDE MPU SUPPORT AND DOES NOT SUPPORT xTaskCreateRestricted().

In general, assume that 1. all memory in the ESP32 is accessible by any task on any core, and 2. if you have multiple tasks (on the same or different cores) you need to implement thread safety (using muxes, semaphores, queues, stream buffers) yourself.

If you actually post what you want to achieve (rather than how you think you can solve it), we can probably help you find some way to do it in a way that aligns with what ESP-IDF expects.

Who is online

Users browsing this forum: Barkrowler, Google [Bot], PerplexityBot and 2 guests