Queue tactics for large memory objects

Since the definition of “Real-Time” is based on getting answers in the needed time, the primary reason to actually be USING an RTOS is that your tasks have deadlines.

Task A may need to do 5 ms of processing with a deadline of 25 ms after request.
Task B may need to do 2 ms of processing with a deadline of 5 ms after request.

WIth these requirements Task B needs to be higher priority than Task A. You also need to know that no more than 10 requests for task B can occur in the 25 ms you have to do Task A, or you have run out of processing bandwidth, but likely you know Task B won’t be requested that often.

If your idle task always has plenty of time to run, even at the peak of demand, you put in too much processor (or you have a very large reserve for the future).

Looking at the definition, I presume the logging task is going to be I/O bound, and using a very small percentage of CPU utilization, even when running flat out. This says that for total system throughput, it is important to give it a moderate priority so that the logging peripheral’s output buffers are kept filled when we start to develop a logging back-log, so I would give the logging output task a moderately to high priority, primarily below tasks with harder Real-Time constraints, but above tasks that might be more compute-bound.

In my experience the logging task always had the lowest priority and was used only if no other work had to be done. I dont think I had it starved ever.

That is a common concept, but not always right. If you do never starve it, then it may be ok.

The key things to consider:

  • What are the consequences of the Logging Queue filling up? (Is the data loss acceptable, or the delay of the other tasks)

  • Are there periods when the logging output is the limiting factor for the system?

  • Are there (or could there be) periods when CPU utilization gets high enough that priorities actually matter.

As I mentioned before, if you always have plenty of CPU bandwidth, you have a faster CPU than you need, or you don’t really need an RTOS.

As I mentioned before, if you always have plenty of CPU bandwidth, you have a faster CPU than you need, or you don’t really need an RTOS.

I think I speak not only for myself (maybe this is far fetched), but i am not always using RTOS because it is mandatory, but because it gives the overall API that allows to deliver the functionality faster.

As for you points I also agree.

Side questions regarding the double queue approach: It is needed in it to initialize the free indexes queue with all available indexes at init time. It seems that one cannot do that in the main, before the scheduler is called (neither with xQueueSendToBackFromISR or xQueueSendToBack). Is the only option here to add a second level init function that will be called in a task, once the scheduler is started?

Yes, sometimes you use the more powerful tool than needed because it is handy. The key point is that it is best not to imply such usages are “Normal”.

For the double queue, yes, you need to initialize the free queue with the pointers, and that is normally best done pre-scheduler (I don’t like saying “in main”, as most of the time my main has almost no code, and everything is done in setup functions, not main itself.

There is NO problem in calling xQueueSetToBack from main, the requirement is the delay term must be set to 0 when called when blocking is not possible. The documentation talks about not being able to use functions that can block, but that means with the parameters as given at that call, so with a block time of zero, they are usable.

I guess you are right.

For the double queue, yes, you need to initialize the free queue with the pointers, and that is normally best done pre-scheduler (I don’t like saying “in main”, as most of the time my main has almost no code, and everything is done in setup functions, not main itself.

It was a very short train of thought indeed.

There is NO problem in calling xQueueSetToBack from main, the requirement is the delay term must be set to 0 when called when blocking is not possible. The documentation talks about not being able to use functions that can block, but that means with the parameters as given at that call, so with a block time of zero, they are usable.

Ok, thanks!