Electronics > Microcontrollers

FreeRTOS - pre-emptive or not?

<< < (12/13) > >>

mikerj:

--- Quote from: NorthGuy on October 16, 2021, 06:04:39 pm ---
--- Quote from: SiliconWizard on October 15, 2021, 06:02:08 pm ---But even in such a case, you can still use a single-task approach, which is often less trouble to get right.

--- End quote ---

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.

--- End quote ---

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.

Siwastaja:
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.

NorthGuy:

--- Quote from: mikerj on October 17, 2021, 01:16:20 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.

--- End quote ---

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.

Siwastaja:
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.

peter-h:
"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.

Navigation

[0] Message Index

[#] Next page

[*] Previous page

There was an error while thanking
Thanking...
Go to full version