What could FreeRTOS do next? Share your Ideas

Well, as I understand it, there’s gotta be a task somewhere.
if the IDE sets up a task, and a lot of people do use the configuration part of the APP (pin assignments, subsystems, etc) as a convenience.

It’s simply how I make use of something they provide me.

I’m not sure I use the (badly) designed parts of their libraries, although I’d rather not use much of all, hence the wrappers I use to make their low level hal routines better behaved at the system level.

Since every program makes assumptions on how it is to be used, why, and what the “proper” way is… I’ve just fit within an easy scheme to do.

What would you rather they do (since I haven’t looked a their ISR programming much)? With no good documentation on why they did what they did, you tend to roll your own.

Any pointers to egregious waits?

No. I have seen systems that are completly driven off ISRs. No task but the idle task (which is always generated by FreeRTOS) needed.

Also, as I pointed out earlier, even if there IS a task (typically more than one), FreeRTOS does not place any restrictions on how and where module initalization is distributed over the code (before or if after in which tasks after the scheduler is started). There are use cases for all kinds of setup.

I do not know about “a lot of people.” I myself have participated in about a dozen FreeRTOS related projects over the years. Only one of them involved using an IDE (not from ST), and it was used only to build, load and debug. No system construction module I have ever seen in an IDE was any useful (see below).

Please remember, again, that “they” are a 3rd party completly independent of FreeRTOS. “They” offer their IDE exclusively as a marketing instrument in the hope that it helps with their hardware sales. There are also other IDE manufacturers with different business models.

In any case, ST does NOT have an interest in unleashing the power and flexibility of any of the middleware packages they support. On the contrary, they are looking for the smallest common denominator in all RTOSs they let you click in, sacrificing a good deal of the features that distinguish middleware packages from each other for the sake of unification.

There is nothing wrong with that by itself, but this is a FreeRTOS forum. From FreeRTOSs point of view, the ST IDE is nothing but a 3rd party provided package that in some installations uses (and provides some degree of support for) FreeRTOS. I personally do not see any incentive to look at system construction (which is also part of system architecture) of a given project from the point of view of such an external package.

the IDE is used for configuration, loading, and debugging. There is no part of the IDE that sets up tasks except for a default task.

The “task” set up as a convenience is a simple while (1) loop with a vTaskDelay(1) in the loop. That’s all it is.

I’m making use of what I’m provided, following a scheme that works for this project. None of this is about specific ST decisions, but I did try to explain, within the context of their framework, what I am doing.

If You get C++ running, there is no need for Rust at all.

Happy Easter!

1 Like

At least one reason the task entry point (“task function”) needs to have C language linkage, not C++ linkage. It’s the same problem with callbacks that expect C; by default, C++ class member functions don’t have the right linkage.

I do not recall if you can simply define a member of the class with “extern "C"” or if you have to have to have a non-member function declared “extern "C"” and have the task parameter be a pointer to the instance of the class, and then have that function call the task function of the object (after the parameter was cast to the correct pointer type). I have done the latter, I don’t recall if I’ve done the former.

What could FreeRTOS do next?

Ada bindings and the ability to use Ada procedure as task entry-points/functions.

For a mysterious (well, not to me, but I’m not permitted to say why) reason, a project I’m working on needs this, and though someone on my team (not me, I don’t know Ada well enough) can put something together, we can’t share it and it won’t be anything like portable.

A set of Ada bindings for things like FreeRTOS tasks, semaphores, mutexes, timers, events, etc., would make it easier for projects like mine to justify using FreeRTOS to our program managers.

As it stands, only the GCC Ada compiler (“Gnat”) is needed, but if there are other Ada compilers out there, it would be good if the bindings can work for them as well.

1 Like

Quick sketch:

  1. the main task is a call to a setup routine. That’s a C++ routine that creates tasks.
  2. while C++ classes own the task variables, the task itself is a C structure declared outside the class. It is not a part the class.
  3. A pointer to the class owning the task is passed as the argument to the task (this)
  4. to access the class variables, a copy of the task object is created in the task

I have added detail to my response. The problem is that the scheduler has to be the one to call the task entry, and the scheduler always uses a C linkage, so this will not be set, and the function will not be able to access the instance member variables.

What I have done in other instances is to create a function in the class implementation file, but not a member function of the class, with C language linkage. The function return type is void and it takes a single void* parameter. Assuming a C++ class named “FooClass” with the task main method “main”, the task wrapper function would be:

extern "C" void FooClassTaskEntry(void* param)
{
    FooClass* instance = (FooClass*)param;
    instance->main();
}

In the class’s “setup” method, you create the FreeRTOS Task instance providing the this pointer as the task parameter and the wrapper function “FooClassTaskEntry” as the entry point. It uses one extra stack frame, but otherwise it works pretty well.

It should not be necessary to copy the FreeRTOS task object; I simply have a pointer to the FreeRTOS task object as a member variable of my class. (Actually, I have a FreeRTOS task object as a member variable and use the static initialization API instead of the dynamic creation API; FreeRTOS doesn’t know if it’s static allocation or in some C++ class, it just knows the address you passed to it.)

I’ve been doing this across many projects over the past 10 years and it’s never been a problem, and it’s a technique I have been using since I first started with C++ in the 1990s, since pretty much all of the callbacks for interfaces I was using at the time were expecting C linkage, though that wasn’t on FreeRTOS.

1 Like

This works, too.


				xTaskCreate(
						(TaskFunction_t) &LED_TASK,
						name,
						LED_STACK_SIZE,
						(void*) this,
						2,
						&task_handle);

void LED_TASK(void const * argument)
{
	uint32_t				mask;
	LED*					me;


	me = (LED*)argument;


	// ************************ initialization **********************************************************************
	mask = 0x80000000;
	while (1)
	{

		if (me->blink_mask & mask)
		{

			me->SET(LED_ON, 100);

I’m using a static C++ entry point (the same one) for all tasks derived from my base task class. This calls a method on the task object, which is the main loop of the task. Task objects need to be explicitly started (a method called) to get them going, this method creates the task using FreeRTOS xTaskCreate and using the common entry point mentioned above with the object as the task parameter. So basically I create the task objects using constructors to pass parameters, and call start() on them. This seems to be working well.

I’m kind of perplexed by the difficulties everyone is describing, and wondering if I have some hidden issue because of lack of understanding. I don’t have any extern “C” linkage issues or declarations. My tasks can be created after the scheduler and can even be short lived and exit, although I don’t use that functionality much at all.

2 Likes

I’m using a very similar method since a long time and don’t have any problems with it.
There are more ways of suitable, pretty straight forward C++ bindings/wrappers.
Although I could imagine that a task create suspended could be useful in some use cases. Just my 2ct.

1 Like

The problem comes when the “Task” wrapper is a base class of the class the represents this specific task and creates the task as part of the constructor, then the FreeRTOS task comes into existence before the full class is constructed, and if the stub tries to use a virtual member function to access the task functionality.

Using a separate “start” or “run” member function in the task wrapper class gets around the problem, but means that until you do that the wrapper doesn’t have a task that it is wrapping.

If you use tasks that are created and destroyed a lot during the running, the start method can make sense, but if tasks will generally run “forever” the constructor method makes more sense, but leads to the issue for the unusual task created after the scheduler has started.

Better newlib support. Lots and lots and lots of users continue to be burned by MCU vendors providing improper integration - then they get memory corruption. Details https://nadler.com/embedded/newlibAndFreeRTOS.html
Thanks!

1 Like

Although it has been stated before, let me toss in another vote for an official set of modern (C++20 and beyond) C++ wrappers.

I’d also like to see a tickless mode to improve performance, not necessarily timer granularity, since this is easily made using a bit of architecture-specific code.

In general I’d like to see the diff of vendor-specifics fork against upstream vanish, but I realize that this is hardly your call.

What I do understand is that those ports reset the system stack after starting the OS so that they can use the full stack’s lenght for the ISRs chores, is my understanding correct? Isn’t that a flaw?

As @madyn pointed out: Is that behavior documented?

No :grin:

C++ bindings are a better option.

Not a flaw, just an engineering design decision weighing off contradicting requirements (in this case memory usage vs. serving fringe use cases). IMHO, the decision in those ports is perfectly ok as there is a straightforward and easy workaround (do not use local variables on the main stack for use after the OS has started, use globals instead).

As this is port specific behavior, there is no place in the “general documentation” for it. There probably should be a note in the porting guide if it isn’t yet. As for this forum, this behavior is pointed out in a perceived 1 out of 3 threads in the kernel section.

I don’t like the CubeIDE RTOS model. You might want to add FreeRTOS as independent module in your IDE project and just connect the timer that will drive the system tick. This is the way NXP used to include FreeRTOS in its also Eclipse-based IDE called MCUXpresso. Nowadays this IDE offers seamless integration with FreeRTOS and other OS, but including it under your control is sometimes the best option.

Just to update everybody, I have been talking with Sven regarding his heap library on the github page for the library. I have tried to communicate what the 5 heap_x.c is used for and why each has advantages and disavantages. I then downloaded Sven’s heap library and made an example (no example code is included atm) to evaluate the advantages and disavantages of this library as well: The problem with Sven’s heap is excessive memory usage - an overhead of 20 bytes per allocation is not ideal for embedded usage. For this reason alone, a general replacement of the 5 FreeRTOS heaps with this heap is out of the question and even as an additional option (like heap_6.c) it would most likely see limited use due to the memory usage.

3 Likes

Thanks for doing the tests, I considered that myself! Your results once more prove the engineer’s fact of life that very rarely there is a single best solution to any given problem - finding “the” best one is almost always a trade off between different, at times contradicting, pros and cons of each solution.

1 Like