Author Topic: FreeRTOS - pre-emptive or not?  (Read 5428 times)

0 Members and 1 Guest are viewing this topic.

Offline NorthGuy

  • Super Contributor
  • ***
  • Posts: 2765
  • Country: ca
Re: FreeRTOS - pre-emptive or not?
« Reply #50 on: October 14, 2021, 08:16:14 pm »
That said, even if in the above case, sharing the UART RX wouldn't make much sense.

I think by UART RX you mean pins or registers. The example was about buffering and unbuffering, and I expessedly said:

... your UART buffer has become a shared resource ...

The buffer is shared between the thread that writes the data to the buffer and the thread that retrieves the contents from the buffer.

Aside of that, you certainly can share a single UART peripheral between different tasks. You can even dynamically re-assign pins to use the same UART peripheral module to talk to different devices connected to different pins, although typically UART modules are not in short supply.

 

Offline peter-h

  • Super Contributor
  • ***
  • Posts: 1639
  • Country: gb
  • Doing electronics since the 1960s...
Re: FreeRTOS - pre-emptive or not?
« Reply #51 on: October 15, 2021, 05:25:06 am »
I am doing that but with SPI3, not a UART. That SPI channel is used for multiple devices: ADCs, DACs, special-purpose I/O chips, etc. I've set it up so there is a mutex around the code accessing each device (just one mutex for all of them) and there is a "last device used" value stored so if the new device is not same as last, you re-initialise the SPI and store that device # as "last".

Perhaps surprisingly, it works, but unsurprisingly it took a lot of time to get it to work because the SPI controller needs some undocumented number of APB clocks (and/or the SPI clocks; the frequency is different for each device, from ~500kHz to 21MHz) to settle down. Also some devices need clock parked high, some parked low, some evidently don't care, some clock data on +ve edge, some on -ve edge, some need long timing before/after CS, etc. We had a long thread on this a while ago.

I suspect most people totally avoid doing this sort of thing :) but when it works, it shows the power of an RTOS and mutexes etc. Just don't try it with delta-sigma ADCs which have a 100ms conversion time ;)
Z80 Z180 Z280 Z8 S8 8031 8051 H8/300 H8/500 90S1200 32F417
 

Offline SiliconWizard

  • Super Contributor
  • ***
  • Posts: 9135
  • Country: fr
Re: FreeRTOS - pre-emptive or not?
« Reply #52 on: October 15, 2021, 06:02:08 pm »
I suppose you are reusing a single SPI peripheral by reconfiguring it on the fly if needed and using separate chip select lines?
That would be an example indeed.

But even in such a case, you can still use a single-task approach, which is often less trouble to get right.
Basically, all SPI accesses would be issued in one task dedicated to it. Then you would communicate with other tasks using queues. You can typically set up one "command" queue that each task needing SPI access would fill with SPI access parameters, and then queues for pure data exchange. That may look a bit intimidating at first, but is a lot easier to get right in the end, and scales up better IMO. Hope I was clear enough here with this approach - didn't get into details.
 
The following users thanked this post: harerod

Offline NorthGuy

  • Super Contributor
  • ***
  • Posts: 2765
  • Country: ca
Re: FreeRTOS - pre-emptive or not?
« Reply #53 on: October 16, 2021, 06:04:39 pm »
But even in such a case, you can still use a single-task approach, which is often less trouble to get right.

That is for sure. Abandoning RTOS is even better. With direct access to peripheral, interrupts, and DMA, you can organize everything much better than RTOS ever could, and write much less code too.

But bring in few huge blocking libraries, and you cannot get by without RTOS any more. Hence the popularity.
 
The following users thanked this post: Siwastaja

Offline ogden

  • Super Contributor
  • ***
  • Posts: 3686
  • Country: lv
Re: FreeRTOS - pre-emptive or not?
« Reply #54 on: October 16, 2021, 07:12:42 pm »
I am doing that but with SPI3, not a UART. That SPI channel is used for multiple devices: ADCs, DACs, special-purpose I/O chips, etc. I've set it up so there is a mutex around the code accessing each device
But even in such a case, you can still use a single-task approach, which is often less trouble to get right.
That is for sure. Abandoning RTOS is even better. With direct access to peripheral, interrupts, and DMA, you can organize everything much better than RTOS ever could, and write much less code too.

SiliconWizard suggested dedicated task with queues for handling I/O of common peripheral - to avoid blocking of consumer tasks. If you think that better solution is to abandon RTOS - then think/learn again :)
 

Offline mikerj

  • Super Contributor
  • ***
  • Posts: 2888
  • Country: gb
Re: FreeRTOS - pre-emptive or not?
« Reply #55 on: October 17, 2021, 01:16:20 pm »
But even in such a case, you can still use a single-task approach, which is often less trouble to get right.

That is for sure. Abandoning RTOS is even better. With direct access to peripheral, interrupts, and DMA, you can organize everything much better than RTOS ever could, and write much less code too.

An RTOS does not prevent direct access to peripherals, interrupts or DMA.  Even if you are using a simple scheduler or a conventional superloop with state machine you would still need to provided protection to  shared resources like DMA that run outside of a tasks execution.
 

Online Siwastaja

  • Super Contributor
  • ***
  • Posts: 5364
  • Country: fi
Re: FreeRTOS - pre-emptive or not?
« Reply #56 on: October 17, 2021, 03:45:46 pm »
You are looking NorthGuy's comment in the wrong way. If you have already defined everything using computer science operating system terminology and mindset, and you have a problem you need to solve defined in this context, "abandon RTOS" obviously is no solution to that problem. But isn't it an X-Y problem to begin with?

But NorthGuy's suggestion is a viable choice in the bigger picture. Well, not always, obviously, sometimes some specific RTOS happens to be just the right tool for the job. And then it matters which RTOS it is.

But many if not most projects that are written on top of RTOS don't need or benefit from said RTOS if looked at on clean sheet specification level, but because they are written for RTOS, you can't get rid of it without rethinking the whole project. And that would likely be a stupid move to rewrite a project "just" to get rid of RTOS if the project works well.

This is like building a brick house vs. wood frame house. Both work and result in a decent house, but in completely different ways. But a very skilled mason may not understand how to build a decent wood frame house, and a carpenter would suck at building the brick wall.

I only dislike the elitism that comes with RTOS mindset, namely while people like I accept RTOS might be an acceptable idea, use it if it works, many RTOS believers force the projects into this mindset bringing all the made-up abstractions that made parallel programming on general purpose computing difficult, to relatively simple embedded projects where all these complications could be completely avoided in the first place. Their claim is there are some very difficult and complex problems regarding to parallel computing which are nicely "abstracted" by the OS, but this is mostly BS, in reality these complex problems are made up at the same time they are solved.

A classic interrupt priority driver state machine is extremely simple to analyze and I have had to think about some "equivalent of mutex" exactly... zero times.

But you can keep claiming I need to somehow manually and tediously implement all those mutex-equivalents and semaphore-equivalents and spinlock-equivalents and threads and complex schedulers and whatnot, but in reality, I don't have to.

And I don't need to think about what scheduling delay is or what time slicing value I need to use. My interrupt priorities are configured according to the urgency of the interrupt source and the ISR starts in 12 clock cycles.

Quite frankly, I believe NorthGuy hit the nail; RTOS is a very useful tool for people who learned general purpose computing, writing blocking code. There is nothing wrong with that. If that's what you do and you are old enough not to learn new skills, then RTOS is likely the right choice to work with on microcontrollers. But I for example started learning microcontrollers at 14 years old, on brand new Atmel AVR series, similar to PIC. This gives you a different mindset, and yes, it's completely extendable to largest ARM microcontrollers on the market because they fundamentally work the same.

What I do not like is that many really experienced PIC-style developers who could develop nearly bug-free, simple, understandable and high performance code on any modern microcontroller, have been forced to change their thinking by RTOS and library elitism and misinformation.

I'm not looking for popularity or "thank you" presses with this comment, and I understand this is only one side to the complex story.
« Last Edit: October 17, 2021, 03:57:14 pm by Siwastaja »
 

Offline NorthGuy

  • Super Contributor
  • ***
  • Posts: 2765
  • Country: ca
Re: FreeRTOS - pre-emptive or not?
« Reply #57 on: October 17, 2021, 03:56:39 pm »
An RTOS does not prevent direct access to peripherals, interrupts or DMA.  Even if you are using a simple scheduler or a conventional superloop with state machine you would still need to provided protection to  shared resources like DMA that run outside of a tasks execution.

While DMA transfer is in progress, you will have a flag which tells you that. You can poll the flag if you wish, or, if you want to react sooner, you can create an interrupt which fires immediately as the DMA transfer is finished. Moreover, you can assign priorities to interrupts. Say you can configure priorities in such a way that the DMA interrupt does happen, but not if fast ADC interrupt is in progress. Or perhaps your DMA controller may be clever enough to trigger a different DMA transfer once the first one is done. All these mechanisms are already there, and there's absolutely no need to use RTOS to duplicate them.

The new thing that RTOS add, which wasn't already there, is multi-threading. It lets you run multiple threads (tasks if you wish) which can preemt each other and thereby share the CPU creating an illusion that each task runs on its own CPU. This lets you write your code in  linear fashion - if you need to wait for something, you just block the thread and then, when the condition is satisfied, the thread continues automatically. Without RTOS, you would have to write non-blocking code - if you want to wait for something, you would have to find a way to continue other tasks and poll periodically for the condition.

The decision between using RTOS or not should be based on whether you want to write blocking or non-blocking code. Blocking code is arguably easier to write, certainly much easier to find on the Internet. But to use it, you would have to bring in the RTOS.
 

Online Siwastaja

  • Super Contributor
  • ***
  • Posts: 5364
  • Country: fi
Re: FreeRTOS - pre-emptive or not?
« Reply #58 on: October 17, 2021, 04:05:14 pm »
Again hit the nail, that's exactly the difference, and also the real reason why to use RTOS. All the BS about mutexes being needed to use peripherals and DMA and whatnot is only a smoke screen (or more likely, lack of thinking without bad intent, but I wanted to sound dramatic, sorry 'bout that).

RTOS is a real simplification in code writability and readability if there are complex, long control code paths that need to run in parallel to each other. ESPECIALLY when there are NO dependencies so that no mutexes are needed. This is in contradiction to the typical claim that RTOS shines in mutexes. No, mutexes are needed when the nice "run blocking linear code in parallel" paradigm falls apart, and then it gets into all the problems with multithreaded code.

For example, when I write without RTOS, my FSMs may be built with 20 functions each of which represent the code to run one state, then set the interrupt vector to the next state. On RTOS, this can be written in one loooong function with wait-for-something loops, or OS yield function calls in between, to let the scheduler to do its magic. Sometimes that's easier to read, and a few lines shorter per state. So instead of 20 functions 10 lines each so 200 LoC total, now you have one function of 150 lines.

Quite hilariously though, the typical style guidance is to split such long blocking code into state machine containing of small functions such as one per state. If you do that, you have already got rid of the RTOS mindset, even if you run RTOS.
 

Offline peter-h

  • Super Contributor
  • ***
  • Posts: 1639
  • Country: gb
  • Doing electronics since the 1960s...
Re: FreeRTOS - pre-emptive or not?
« Reply #59 on: October 17, 2021, 05:50:48 pm »
"I suppose you are reusing a single SPI peripheral by reconfiguring it on the fly if needed and using separate chip select lines?"

Yes exactly.

"Basically, all SPI accesses would be issued in one task dedicated to it. Then you would communicate with other tasks using queues."

I didn't do that. I just have different tasks using different SPI3 peripherals, and the SPI3 is mutex protected. The SPI3 controller is re-initialised if needed. The time consuming bit was that this is undocumented - nowhere does it tell you how many clocks (and which clocks) are needed before/after SPI init, before you can send out data, etc.

" Blocking code is arguably easier to write"

It certainly is, even if you yield to RTOS whenever waiting for something. I think that's the real advantage of an RTOS. It simplifies writing code where different bits do different things.

If one goes back to the earliest days of microprocessors, one didn't have an RTOS (unless one wrote one, and then it was probably very basic). One did all time critical things in an ISR, and this is still the right way to do time critical (response time critical) things today. The latency can be just a few instructions. Background stuff was done in a timer ISR - 100Hz, 1kHz, etc. The main foreground loop was probably fairly simple. But software was simple back then :) Today's software is vastly more complex, especially when using libs which nobody understands and which are buggy (seems to be the case for SSL/TLS stuff) and which were written to be blocking.
Z80 Z180 Z280 Z8 S8 8031 8051 H8/300 H8/500 90S1200 32F417
 

Online Siwastaja

  • Super Contributor
  • ***
  • Posts: 5364
  • Country: fi
Re: FreeRTOS - pre-emptive or not?
« Reply #60 on: October 17, 2021, 06:11:23 pm »
Yes, when having to deal with complex, broken and buggy libraries to implement simple things which take 5 nonblocking LoC without the library, life gets very difficult very quickly. The answer is obvious, adding more complexity until it somehow kinda magically works out. During this process, it's very typical that most fancy pre-requirements (nanoseconds! 10000 years MTBF!) are relieved to be able to deliver at all. For example, "robust" means it works on lab table during demonstration. "Real time" means something happens within the human timeframe of not noticing the delay (i.e., < 10ms).

It doesn't have to be that way.

Unless the project really is complex. I mean like autonomous space shuttle that lands on the Moon while doing moonwalk better than Michael Jackson ever did level complex. In such case, you may want to leverage existing machine vision algorithms, for example, meaning actually complex libraries instead of 5-LoC ad-hoc solution. And you may want something fancier than a 1kHz tick interrupt.

But FreeRTOS likely isn't the solution for that use case, either.
 

Offline mikerj

  • Super Contributor
  • ***
  • Posts: 2888
  • Country: gb
Re: FreeRTOS - pre-emptive or not?
« Reply #61 on: October 18, 2021, 10:47:50 am »
An RTOS does not prevent direct access to peripherals, interrupts or DMA.  Even if you are using a simple scheduler or a conventional superloop with state machine you would still need to provided protection to  shared resources like DMA that run outside of a tasks execution.

While DMA transfer is in progress, you will have a flag which tells you that. You can poll the flag if you wish, or, if you want to react sooner, you can create an interrupt which fires immediately as the DMA transfer is finished. Moreover, you can assign priorities to interrupts. Say you can configure priorities in such a way that the DMA interrupt does happen, but not if fast ADC interrupt is in progress. Or perhaps your DMA controller may be clever enough to trigger a different DMA transfer once the first one is done. All these mechanisms are already there, and there's absolutely no need to use RTOS to duplicate them.

And I haven't suggested there is.  I saying that shared resources who use does not start and end within a "tasks" allocated time need some form of mutual exclusion to prevent collisions and race conditions.  Polling the DMA flag might be good enough, but equally it might not be, this is exactly the kind of thing that can cause race conditions.

The new thing that RTOS add, which wasn't already there, is multi-threading. It lets you run multiple threads (tasks if you wish) which can preemt each other and thereby share the CPU creating an illusion that each task runs on its own CPU. This lets you write your code in  linear fashion - if you need to wait for something, you just block the thread and then, when the condition is satisfied, the thread continues automatically. Without RTOS, you would have to write non-blocking code - if you want to wait for something, you would have to find a way to continue other tasks and poll periodically for the condition.

This isn't even true, there are cooperative only RTOSs and RTOSs that can be configured to only work cooperatively.  A good RTOS brings far more to the game than you seem to think they do.

The decision between using RTOS or not should be based on whether you want to write blocking or non-blocking code. Blocking code is arguably easier to write, certainly much easier to find on the Internet. But to use it, you would have to bring in the RTOS.

Again no. Even if you write non-blocking code (e.g. state machines) then you are very likely to want some kind of priority scheme, and some way of passing data between your "tasks" or synchronising them.  All the stuff that's built into an RTOS, but reinventing the wheel can be fun too.
 

Online Siwastaja

  • Super Contributor
  • ***
  • Posts: 5364
  • Country: fi
Re: FreeRTOS - pre-emptive or not?
« Reply #62 on: October 18, 2021, 11:04:26 am »
The fact is that available CPU and MCU architectures are designed to run without RTOS. That is why problems you think appear when working without, in reality mostly do not exist. You would see that immediately if you actually did this work. I have never ever had to even remotely think about a race condition accessing DMA. This hasn't even crossed my mind. DMA peripherals are designed to work fine from bare metal code. Interrupt priorities exist for a reason, too.

But I don't need my code to be in "linear" fashion with wait-for-something-else inbetween. I'm fine writing nonblocking or "callback-like" code.


The RTOS scheme is all backwards; instead of RTOS solving a problem, RTOS invents problems then solves them. If you work logically backwards thinking that "oh, RTOS solves this problem -> removing RTOS removes the solution -> problem remains", you get the logically wrong result.

This is not saying RTOS does not have possible strengths, not at all. But the argument that life without is difficult because of shared resources like peripherals is just complete and utter.... I don't even need to say it out loud. This is a FUD argument. Instead, why wouldn't you concentrate on telling us what are the strengths and benefits of RTOS? Without coming up with made-up problems that supposedly happen without, because there are experienced developers who immediately see these are made-up problems.
« Last Edit: October 18, 2021, 11:07:23 am by Siwastaja »
 

Offline NorthGuy

  • Super Contributor
  • ***
  • Posts: 2765
  • Country: ca
Re: FreeRTOS - pre-emptive or not?
« Reply #63 on: October 18, 2021, 02:03:47 pm »
All the stuff that's built into an RTOS, but reinventing the wheel can be fun too.

Oh, "reinventing the wheel" again. Look at it this way. Many, if not all of these things, existed before RTOSes. So, following your logic, RTOSes are nothing more than reinvented wheels :)
 

Online Siwastaja

  • Super Contributor
  • ***
  • Posts: 5364
  • Country: fi
Re: FreeRTOS - pre-emptive or not?
« Reply #64 on: October 18, 2021, 03:28:49 pm »
"Reinventing the wheel" is one of the most misused metaphors.

Really it means taking something old, that works really well and can't be improved by making large changes, yet change it fundamentally to turn it into something new that performs worse, for example make it square. This happens all the time, but "not using RTOS" is not such case. Opposite could be said arguably, though.

But it follows the logic of these RTOS people. In their world view, the RTOS is the only way to do anything more complex than a LED blinker, and if you don't use it, then it logically follows that you are writing your own "RTOS equivalent" each and every time from scratch, and doing it in inferior way, hence "reinventing the wheel". If a scheduler in RTOS is 1000 LoC, the logical conclusion is, if you don't use it, you have to write your own scheduler which is also at least 1000 LoC and likely worse because it sees less testing and is done in hurry compared to a well-designed RTOS. But this is complete fallacy if and when you don't need an OS scheduler at all.

We are not alone with this view. Not using RTOS can be a marketing argument showing how widely people are sick about "having to use" RTOS. For example, Fanstel markets their BC833M product family (well, basically Nordic Semiconductor microcontrollers) with this statement:

"The embedded stack interface uses an asynchronous and event driven model removing the need for RTOS frameworks."

source: https://static1.squarespace.com/static/561459a2e4b0b39f5cefa12e/t/60270895e454bd0fb5d24793/1613170839894/BC833M_Product_Specifications.pdf

This is actually a pretty good one sentence description how embedded MCU development is normally done. It's good they tell this because with such clear information, the actual implementation team can convince their boss that no, RTOS is not desirable in the project.
« Last Edit: October 18, 2021, 03:30:26 pm by Siwastaja »
 


Share me

Digg  Facebook  SlashDot  Delicious  Technorati  Twitter  Google  Yahoo
Smf