What could FreeRTOS do next? Share your Ideas

Agreed. I use the trick of setting a task to priority 0, then immediately suspending it, then when it is told to run, elevate the priority and then let it go.

Maybe we have a mechanism to create a non-running task?

The other stuff that I do with classes does not have anything to do with creating a task, it’s just graphics tree stuff.

As I once remarked about a graphics program (Carrara), if the people who designed it actually used it, they’d have fixed this problem a long time ago.

You’ve got workarounds, I have workarounds. What can we do to make it work better and not need the workarounds.

I will point out that the priority 0 “trick” doesn’t work with SMP (unless you artificially limit the system to only running tasks of a single priority). What I am doing now, (and hopefully should be updating my published library soon) is begin the stub with a Notification wait, which the constructor (or whatever) needs to give to actually start the task.

I’ve done something like that at times. It was a bit more awkward than the task priority trick. All that would be superfluous if we could create a task in the inactive state, wouldn’t it? Of course, I’m thinking C++ here where I can set a default argument value and tack it onto the end of a function call and only put it in if I need a different value.

I don’t use SMP because I stick to processors that are in the low teens of dollars if I can help it. (ST Micro, that is).

I don’t use SMP much either, because I haven’t had the need, but I want to try to make my library as bulletproof as possible, so I don’t forget about it when I do have a need. Since FreeRTOS has merged the SMP branch into trunk.

Because of the way normal FreeRTOS tasks are created, with everything as parameters, and it using a C API, adding a way to create suspended tasks is likely more costly to add the capability to the kernel, than beginning the C to C++ thunk with a call to wait for a Task Notification before vectoring to the task function. (If task creation started with a configuration structure like the create restricted did, it would be less of an issue)

Maybe this is too simplistic, but how about duplicating the code to create a task exactly, renaming it TASK_SUSPENDED somewhere obvious, change the status of the task by adding code to change the task status before it’s executed?

You COULD do that, but that adds more code than adding the Wait for Notifications in the thunk. Also, that change would need to be edited into tasks.c each time to add it ourselves. (An official version likely makes a macro wrapper for the existing one that just sets a parameter to make it start Ready vs Suspended.

Let’s hear it for the official version, then.

Apologies, but I do not see the problem here, let alone a reason to abandon C++.

Nothing in C++ requires a constructor to be used. From what I can tell, it is - like many other language elements - an offer, nothing more. There is nothing wrong or immoral in ignoring constructors and delegating “real” initialization into an architecture enforced mandatory class member function that must be implemented. Yet that does not have anything to do with C++ itself, just the framework used around it.

The framework I am currently using requires that each task encapsulation implements a Create() and a Run() member that must be explicitly called to start the task member function. Each task member function in turn is required to call a virtual WaitToExecute() member before entering its infinite loop. The WaitToExecute() member can be used to synchronize the task function start with its prerequired other threads of execution. There is no need whatsoever to fiddle with priorities or worry about code that needs to work for both statically and dynamically created task objects (which does make a big difference in embedded applications). Of course, this is only one possibility to establish a framework; there are many other, as have been sketched out here.

I do not see what FreeRTOS could do here but (arbitrarily) define some “preferred” control framework.

Or am I missing something?

1 Like

Ah, yes, I see the problem.
There is no way that I will abandon C++, have too much code written in it, and for a graphics system, well, inheritance of objects makes too much sense.

The C++ wrappers around FreeRTOS functions that I used made use of the constructors to establish parameters, and indeed, called parts of the class to make things work.

While FreeRTOS (in ST micro land) has the ability in their IDE to set up tasks, I don’t do that. There is only one task at the very beginning, and that’s the default FreeRTOS task as implemented by the IDE. From that task, I call a bridge setup task which is designed to be called from C. That task then initializes the I2C, SPI, and Serial drivers as well as installs a display. The initializations are solely controlled by #define and #ifdef in a configuration file. So far, that configuration file (with suitable adjustments) is used for all projects.

So everything is installed programatically. Since there are no default C++ tasks, the approach using the constructors to initialize and set up a FreeRTOS task under C++, while very nice, simply didn’t meet the programming model I use.

Since the constructors assume an existing task before they’re called, as I program the project, the code is not real, pointers to it are null.

And given this model, constructors can’t be used. I do use a “new” to reserve space for the class, then there’s a create (which sets up structures), and an init (which sets up parameters and is often parametrically driven). So this is close to what you do.

At this point, statically and dynamically created objects do not seem to be important.

What the problem is, and you’ve solved it in your code, is that tasks run immediately upon creation. Some tasks are interdependent, they require facilities that may not yet exist. My request would be to be able to create a non-running task, and simply start it up when needed. My current solution is to create a task with priority 0, then immediately suspend it (creation tasks and most others are at about 3). This works for me, since I don’t use SMP, nor the processors that use it. Love to, but either cost or package limitations seem to get in the way.

What I wanted was a method to simplify the problem, which would simply be to create a non-running task. An operating system I wrote for the Xmega allowed just that.

And what I wanted FreeRTOS to do was to define an arbitrary modification to the creation method to create a non-running task.

You’re not missing much except the context in which this happens. A number of projects pulling from a common group of programs, which are configured by a single configuration file per program.

I might consider a slightly different mechanism.

  1. each task knows what it is dependent on.
  2. if the task does not exist, then the dependent task is in a wait loop.
  3. if it does exist, then check a “running” variable in the task, which if set, allows the dependent task to run.
  4. e.g. NRF mesh networking needs the packet system running, so there’s a check.
  5. remote registry and device finding (such as remote displays) needs both the NRF mesh network running and valid entries in the DHCP table.
  6. so dependencies…

I like the idea of automating things.

Thanks

Ah, I see, thanks for the explanation.

To me it seems as if your reasoning is centered around a 3rd party IDEs way of encapsulation, in this case STs. If that is correct, I would argue against it; FreeRTOS can and should not make up for shortcomings stemming from 3 rd party software.

Yet I would agree that there can not be a lot of harm in adding a way to create a task suspended, requiring it to be explicitly triggered off. A fair number of RTOS’s provide that feature right out of the box. I believe that a good number of use cases can be covered by that feature.

1 Like

I’m not quite sure where the encapsulation comes from. In the IDE you have the choice of declaring tasks to start with, or ignoring that and rolling your own structure. You are not forced to pre-declare tasks, queues, semaphores, etc. Indeed, the only thing you are “forced” to do is to set up parameters for the default task.
Some OS do expect you to set up tasks beforehand, emDOS, for instance. Azure does not. Not familiar with any others.

Once you start messing with C++, the program structure becomes something that FreeRTOS was not explicitly designed to cooperate with.

We have support for ethernet, and so on. Could we have support for serialization as an add-on module? Many peripherals are byte oriented, and with some processors, the structures are word aligned. Is it reasonable to include this? I’m not talking chip/hardware support, but a reasonable way of packing variables other than #pragma (which may be processor specific). Queues could do it (a byte oriented queue), but you’re possibly looking at a queue which can be written as bytes, but read as packets. (fixed length packets).

In FreeRTOS, there isn’t such a thing as a “default task.”

In KADAKs AMX (defunct long time, but a pioneer in RTOS in its time), there was the concept of a “launch task” that was required and had a few privileges over other tasks. That task would basically set up the rest of the application level system. Nothing like that in FreeRTOS.

CubeMXIDE assumes there is one and sets up the structures in main.c as a convenience. You could always remove the code, but to what end? Main.c initializes (low level) all of the drivers, clocks, etc and tests them (some). It then calls the FreeRTOS scheduler with the pre-defined (you set parameters and can include code) task. It also has places for tick handling, error handling from FreeRTOS and the like.

Sure, no problem, any IDE has its own idiosyncracies, and since there is an open market for IDEs, everyone developing for FreeRTOS is free to use any IDE (or none) of their choice to build their firmware with.

There are a number of scenarios where developers/system designers need to abandon this prefabbed init sequence, for example if the code needs to be copied to SRAM before starting (in which case the SRAM init and copy sequences must come before anything else) or where peripherals are served by a 3rd party pre defined task which does the initialization standalone within the task before entering its infinite loop, or others. As it is perfectly valid to do so, ST is well advised to leave the option to bypass their control flow model in favor of a custom setup.

My point is simply that because of this independence, FreeRTOS itself should not contain any code that is tailored around a specific IDEs view of things (which I believe is something you originally requested; please correct me if I am wrong).

My point is simply that because of this independence, FreeRTOS itself should not contain any code that is tailored around a specific IDEs view of things (which I believe is something you originally requested; please correct me if I am wrong).

Could you point out the specifics of that, please? What I have asked for are specifics that make FreeRTOS easier to use, IMHO. There are a number of things I’d like improved about the way that FreeRTOS is presented in the IDE, but I haven’t mentioned them at all (I’d think).

These ought to be useful for everybody, depending on program organization.

In my opinion, that is not a very strong suggestion that this is the way it should be done. After all, parts of their library assume it is ok to do busy waits with long timeouts inside ISRs, which is why the HAL tick needs to be a high-priority interrupt.

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.