Tasks outside main file

delphes wrote on Monday, January 22, 2018:


I made an application on cortex M4 (STM32L4), FreeRTOS 9.0 and Keil, it was working like expected until my task, and object create (semaphore, queue etc) was in main.c file, i decided for much clarity to move outside main in another c file and my whole application get hang inside FreeRTOS. I am just wondering if the are any restiction to have task , objects etc outside main file ?


leroy105 wrote on Monday, January 22, 2018:

David, I’m not an expert with FreeRTOS. All embedded C programs execute from main. Literally when you provide power to the MCU, all the startup files are prepping the MCU for the big moment when it goes to main to start executing code.

If you executed the FreeRTOS kernel from a seperate file, so the actual functions are in another C source file, I suppose you could.

If you are just getting started, I would just execute FreeRTOS from main as in the examples and go from there.

The intent of the RTOS is that you call it from main, and that it is always running in the background, such that you never EVER will call another function in main again. (That’s a simplification, but for getting started a good way to think about it).

delphes wrote on Monday, January 22, 2018:

Tim, this does not answer to my question, In some huge program you sometimes need to split into module, to avoid main file with 10000 lines. I am just asking if there are any rules on heap management or whatever to run task outside Main file ?

rtel wrote on Monday, January 22, 2018:

It is not clear to me what you mean by run tasks outside of main file.

Do you mean to implement the tasks in the main.c source file?
Do you mean to create the tasks in the main.c source file?

Or do you mean something else.

A FreeRTOS application is just a C program. Within the scoping rules of
the C language (by which I mean if things are globals), the C compiler
doesn’t care which file contains which function definitions. Likewise
the C compiler doesn’t care what you call the source files, there
doesn’t have to be a main.c. The only thing the compiler cares about,
and even then only by convention as you could change the start up code,
is that there is a function called main() that it will (by convention)
use as the entry point for the application.

Most of the hundreds of examples implement and create tasks both in the
main.c file and outside of the main.c file.

delphes wrote on Monday, January 22, 2018:

Dear Richard,

The task are declared and implemented in separate unit (called doit.c for exemple), the main.c call an init function (located in doit.c) which create task, semaphore, events etc… after call this init function main just start scheduler. So physically the tasks in doit.c are not in main.c.

When the initialisation of task and task itself was in main no problem. Problem arises just after moving to doit.c.

anythings related with M4 main stack/heap or whatever ?

I am curious to see example outside main.c file.


rtel wrote on Monday, January 22, 2018:

…in which case something very odd is happening. Off the top of my
head I would say one of two things could be the culprit:

  1. You are running out of main() stack, but that is VERY unlikely as the
    stack overhead in the fail case is only one additional function call
    depth to the success case.

  2. Your initialisation function (the one in doit.c) is using stack
    variables as parameters to tasks that, once the function returns, no
    longer exist.

I am curious to see example outside main.c file.
Look at any file in the FreeRTOS/demo/common/minimal directory.

delphes wrote on Monday, January 22, 2018:

the declaration of freeRTOS object are here (located in doit.c)

volatile QueueHandle_t xRcv_Queue_xmsg;
volatile QueueHandle_t xTrm_Queue_xmsg;

volatile osThreadId x_stackxProcess;
volatile osThreadId x_ThreadReceiveCar, x_ThreadTransmitFrame;

TaskHandle_t xTask_xReceive = NULL, xTask_xTransmit = NULL, xTask_stackxProcess = NULL;;

my initialization function in doit.c is here :

void _stackInit(void)
osThreadDef(xSProcessThread, gsm_stackxProcess, osPriorityNormal, 0, 256);
gsm_stackxProcess = osThreadCreate(osThread(xProcessThread), &xTask_stackxProcess);

osThreadDef(uartrcvTask, vxReiceiveCar, osPriorityNormal, 0, 512);
x_ThreadReceiveCar = osThreadCreate(osThread(uartrcvTask), &xTask_xReceive);

osThreadDef(xTestThread, vxSendxFrame, osPriorityNormal, 0, 512);

x_ThreadTransmitFrame = osThreadCreate(osThread(xTestThread), &xTask_xTransmit);

xProcess_Queue_x = xQueueCreate(5, sizeof(struct _xFrame_t));
xRcv_Queue_xmsg = xQueueCreate(1024, (unsigned portBASE_TYPE) sizeof(signed portCHAR));
xTrm_Queue_xmsg = xQueueCreate(5, sizeof(struct _x_TX_frame_t));


somethings looks wrong ?

rtel wrote on Monday, January 22, 2018:

Doesn’t look like it is using stack variables, which would discount (2)

delphes wrote on Monday, January 22, 2018:

I was dreaming I was wrong since I already spent couple hours finding. any idea where I can investigate search ?

waveringradiant wrote on Monday, January 22, 2018:

These are tricky things to debug without having all the code. It essentially leads to speculation and prolonged Q&A. So I should just stay out of the discussion… but just take the facts, and ask yourself “what changed as a result”?

So for example, when everything is in main, “everybody sees everything”. But when some of the stuff is moved “over there” but needed “over here”, in theory that’s fine… if you do it right.

(Warning: speculation) For example, typically a header file is used to make something defined “over there” available to the rest of the world. The header file should be #included both where the objects/code are defined, and also in the files where they are used. But what if the definition & the declaration are subtly different? For example, what the if the volatile-defined objects aren’t declared as volatile in the header file. This should give you a compiler warning a) if you have it enabled (not suppressed) and b) if you actually include the header file in the source file where the object (or code) is defined. But sometimes people forget to do this.

My point is this (actually 2 points): (1) without all the code, this is hard to debug, and we can only speculate (which is a fool’s errand with no end); (2) it almost certainly pertains to the mechanics of moving code, and what happens when you do so (could also be that things are arranged differently in memory, etc.)

My suggestion: go back to what works (“all in main”). Change one thing at a time. If / when it breaks, it pertains to that one simple change. Still, the root cause might be tricky, but now the universe is much smaller.

Good luck!!

delphes wrote on Monday, January 22, 2018:

Panapticon thanks for the tips, I will try to do it line by line and open my eyes again…