Kamil
Kamil

Reputation: 13941

Using local variables with functions that take pointers in FreeRTOS

I need some explanation/clarification about using local variables in FreeRTOS when I need to pass them to another functions as pointers.

For example I have some function that modifies data under pointer 'data'.

void modify_data(int * data){
    *data = 10; 
}

Can I use it like this?

void some_function(void){
    int d;  // local variable
    modify_data(&d);
}

Or maybe I should make global variable?

int d;
void some_function(void){
    modify_data(&d);
}

Or static variable?

void some_function(void){
    static int d;
    modify_data(&d);
}

My question in general is:

How to use (or replace) local variables with functions that take pointers in FreeRTOS?

Edit:

At this moment my understanding of this is:

I'm using FreeRTOS 10.2.1, CMSIS 1.02 and code runs on STM32 microcontroller.

Upvotes: 0

Views: 776

Answers (3)

Kamil
Kamil

Reputation: 13941

So after some discussion in comments and some research I found the answer for my concerns.

Local variables can be used in any way, JUST EXCEPT local variables declared in main function (and in functions called by main) (before FreeRTOS scheduler is started).

Source of my concerns was that I have read in some tutorial, that local functions created in "main context" may be messed up or not exist. It was not explained clearly that it applies to "main c function" and I missunderstood everything thinking that "main context" is context related with Main Stack Pointer, not just "main function".

FAQ on FreeRTOS website says:

The context of main() does not exist after the FreeRTOS scheduler has started as, from that point, only RTOS tasks and interrupts have a context. To maximise the amount of RAM available to the FreeRTOS application, and as allowed by the C standard as the context of main() no longer exists, some FreeRTOS ports re-use the stack allocated to main as the system or interrupt stack. Therefore never allocate variables or buffers that are needed or in any way accessed by the FreeRTOS application on the stack used by main() because they are likely to get overwritten.

So this simplified example would be OK:

int x;

int main(void)
{
    x = 10;
    createTasks();
    vTaskStartScheduler();
}

But something like this will not work in FreeRTOS:

int * px; // this pointer will be not valid after vTaskStartScheduler()

int main(void)
{
    int x = 10;
    px = &x;
    createTasks();
    vTaskStartScheduler();
}

Someone might ask why I used a local variable in main and want to access it in the rest of the application without declaring it as a global variable. I was doing this because I have developed specyfic/weird way of attaching my code to CMSIS/STM32Cube generated code (which forces the programmer to write in "user code regions") that was working until I started using FreeRTOS.

Upvotes: 0

Depends on what you want to do. If you want to use d outside of that function you need to define it as a global, if you are only gonna use it inside the function declare it as local.

Upvotes: 1

Vlad from Moscow
Vlad from Moscow

Reputation: 311068

For starters this statement

*data = (*data)++; 

invokes undefined behavior.

As for your question then to change a variable within a function you need to pass it to the function by reference that is indirectly through a pointer to it. For example

void f( int *px )
{
    *px = 10;
}

void g( void )
{
    static int x;
    f( &x );
}

Upvotes: 1

Related Questions