114 comments

[ 5.2 ms ] story [ 184 ms ] thread
Cool, I really like AVR, but kind of wished there was like a 8-bit RISC-V or something with similar packaging and choices as AVR.
>a 8-bit RISC-V

There's n-bit RISC-V implementations. The registers are still 32 or 64 bit wide, but the ALU is smaller and takes multiple steps.

One such implementation is open source, but I sadly don't remember the name and can't find immediately.

Yeah but the registers do not get smaller in that implementation.
Why is HN obsessed with reinventing the wheel with the new shiny (Rust, Risc-V, etc.) for applications that are perfectly served by mature, battle proven solutions which provide a reliable, cheap and quick time to market.

AVR is today a pretty niche solution, but for it's niche it's better than Risc-V for its mature silicon and tooling, robust analog and digital 5V tolerant I/O, robust CPU and peripheral clocking, cycle accurate simulators, and experienced dev pool.

The over 20 year old gas boiler my grandma has, is "powered" by an DIP packaged AVR chip and does the job just fine for controlling a couple of valves, LEDs, relays, and a PID loop. Same for the old elevator on my university. These kinds of apps is where the simplicity of AVR shines.

Source: former AVR dev

In my opinion, it's because new programmers find C scary due to the prevalence of Python. There's no need to learn anything anymore with all of our RAM and storage. Programming has essentially turned into scripting.

Today you load the boiler library and type start().

>Today you load the boiler library and type start().

Not when you have safety critical real time applications that need to be certified.

Gas boiler control isn't move fast and break things web development. Unless you want to blow yourself up.

That's why old AVR solutions are still used. They've been certified once, they work just fine for this purpose even on newer products. So you go with it. It's a slow moving industry for this reason.

Also, embedded dev is way more than writing C or python code and how many "bits" your CPU core has. You need to take into account clocking sources and stability, analog and digital I/O, on package voltage regulators, tolerance to glitching and brownouts, etc. and for certain applications, AVR chips are way more robust than newer ARM or RISC-V shiny.

I don’t want to go too much into C vs Rust but loads of C code out there, when it comes time to manipulate strings or do something a bit complicated, ends up a hacky mess.

For all the implications you are making about “move fast and break things” in web dev, at least newer tech stacks makes it easier to not completely break your data structures cuz the abstraction ceiling made doing things the right way hard.

Of course experienced C programmers “get it”, design their code in a way to avoid these pitfalls, and can right performant, correct code. I just think that it’s easier with a lot of other tools for stuff that’s just a bit complicated

I feel you're mixing things up. Not every embedded application requires parsing strings or JSONs like you do with web frameworks.

AVRs and 8 bit chips in general are mostly used in various fixed point numerical control applications like CNC, industrial automation, elevator control, and white goods for the home like washing machines, HVAC, and microwave ovens, so for that they're perfect and so is C.

All they do is read some buttons and sensors, crunch some basic math, run a state machine, and turn some motors, LEDs and relays ON and OFF. That's it.

Complex string manipulations is something you'll never see on an AVR chip in such production applications.

Fixed point is a perfect example of an abstraction ceiling that makes it unnecessarily hard to do the right thing.

At first it's fine, but then you'll want to do some filtering, and then some coefficient buckets will start to overflow, and then you'll start tracking exponents, and before you know it you've sunk engineer months or years into an ugly, buggy, underpowered reinvention of floating point numbers.

I've shipped safety critical motor control embedded software that runs flawlessly on thousands of cars using only fixed point math without it being ugly, buggy or underpowered, precisely because everything was computed only in fixed point fractional math.

You're just making up FUD.

"It was good enough for me, so it should be good enough for everybody."

Lol.

Seems like you didn't need fixed point in the first place. It's for when you need guarantees.
I've worked on dozens of embedded projects that don't need string manipulation. Or just outputting some log string through a serial port, which is removed in release.

Why do you think you'll need to process input strings?

> just a bit complicated

Like what? Most embedded projects don't use concurrency, or even dynamic allocations. Not every projects is a hackable bluetooth/wifi stack, that you need Rust otherwise [insert favourite exploit FUD here]. It can be as simple as a toothbrush with two buttons and a motor.

(comment deleted)
I’m just talking about business logic and data structures. It seems fine to want to not have bugs in principle!

Though to your point when we’re talking about 8-bit microprocessors the amount of complications that could even be placed. I just feel like it’s totally normal to feel lacking when writing/reading certain kinds of code in C.

> business logic and data structures. It seems fine to want to not have bugs in principle!

I think there is no (embedded) language so far which prevents you from having bugs in business logic.

Agreed, I was illustrating what Python programming looks like to me. Having experience in embedded C, I see Python as a templating language at best, and it's obviously not something you'd use for critical systems. Every time I use Python I end up rewriting libraries in C.
I much prefer simplicity in the runtimes of things that have the potential to affect lives in a catastrophic way. With the summit being 'no runtime', which makes validating a design that much easier.
I program C, Python, Rust and Javascript, Java, C#, C++, ... And I can assure you the reason I started using Rust is not that I find C too scary. It is an interesting language that has some seriously interesting concepts in it.

To rule out certain (very security relevant) classes of mistakes entirely is good as well.

That being said, learning Rust also made me a much better C programmer, because it forced me to deal with many problems and concepts that might bite even experienced C programmers once in a while all while using a language that just won't let you do the stupid stuff.

Of course that makes you angry and you curse at the compiler. And then you think about why this doesn't work and this is the moment where you pause and go: "Oh.."

For me the enlightenment came when a tech blogger asked for the fastest string tokenization program in any language and I sent him my 10 minute naive Rust thing and it won second place. The first place was hand crafted assembler. My thing could handle UTF-8, the other could not.

This is a real and tangible thing, not just some "shiny" thing.

> it won second place

Out of how many?

While I'm pretty sure you're a very competent programmer, there's a possibility others used non-optimal algorithms.

A good algorithm in a slow language can, on the limit, be faster than a bad algorithm in a faster language.

Case in point: Norvig's sudoku solver in Python blows everything else away in performance because he put a lot of thought into the algorithm [1]. I wrote a C program to solve sudoku (using a backtracking approach), and it was nowhere as fast as Norvig's python program. Can anybody conclude python is therefore faster than C? No! The only thing you can conclude from that is that I'm a lousy programmer :)

Sure you can reimplement Norvig's program in Rust or C or assembly or Brainfuck or whatever, but that's besides the point.

[1] https://norvig.com/sudoku.html

> Out of how many?

20 or so.

It has been a while ago so I cannot recall the exact way I did it, but I certainly didn't implement any specific algorithm, I just did the straightforward thing using Rusts builtin functions as a realistic emulation of a lazy programmer.

The point of my comment was not to claim that Rust is the faster language. The point was that you can write mediocre Rust and still end up with extremely performant code that covers a lot of ground.

My experience exactly. I wrote an emulator in Rust for a thing implemented on an FPGA that generates a video signal. For the first pass, I just ported the Verilog code to Rust, essentially: big loop over all the pixels every frame, figure out which color it should be, return that. There are a ton of ways to factor things out of that so you're not doing repeated reads of stuff, and I was going to gradually put them in until it was fast enough...

And then the naive solution ran at 100 fps.

So uh. Okay then. I see the value in Rust now.

> all of our RAM and storage

This has a cost. Even saving a marginal 10 cents can make a difference.

Even if we live long enough to see a 10 cents microcontroller with 1GB of RAM/FLASH, there will be a $0.000001 part using the same technology but with 2K RAM and 16K storage.

If I'll be making millions of boilers, guess which one I will use.

> Programming has essentially turned into scripting.

Hard real time applications disagree with this. And remember that someone still has to lay the foundations to run scripts in an MCU.

> There's no need to learn anything anymore

I heard the same thing and several variants, 20 years ago when .NET came out.

10 cents for 1 million boilers is only 100k. That's about the price of an additional engineer, so it may very well be worth it to move up in abstraction instead.
What should I do with an extra engineer? Should I hire one just for the sake of moving up in abstraction?

100k saved is 100k earned. Half a Ferrari.

It's exactly the reverse. You need fewer engineers because it's going to be much easier to write the same code at a higher level of abstraction. So you can have that engineer work on something that's going to make you revenue, or hire one less dev.
More about C just being really outdated. There has been some innovation in programming language design since the 1970s. Python is not exactly cutting edge and is an entirely different language.

But Rust, Go, Swift, Zig, D, Terra, Nim and many others can potentially fill much of the same niche as is occupied by C today.

> In my opinion, it's because new programmers find C scary due to the prevalence of Python.

A professional programmer who does not find C scary is about as confidence inspiring as a nuclear engineer who does not find plutonium scary.

There are Padauks, Holteks, Sonixes and others most EEs in the West never hear about
Why is HN obsessed with reinventing the wheel with the new shiny (Rust, Risc-V, etc.)

What else does this "etc" include?

(comment deleted)
Probably eink, is slate not good enough for you?
I'm amateur. I decided to go with RP2040 because I have a limited time and I want to understand underlying architecture. ARM is more useful than AVR, because ARM knowledge (even Cortex-M0) is more transferrable to other fields, like my Macbook.

Same could be said about RISC-V. It's going to be big. So it's very tempting to learn it once for many different areas.

Again same could be said about Rust. I can (theoretically) write microcontroller firmware with Rust, I can write OS with rust, I can write linux app with rust, I can write website with rust. That's very appealing in terms of knowledge transfer.

There're so much things which reinvent the wheel. I think that people want to choose one good enough wheel and keep using it. C and C++ are not good enough. Rust might be good enough. ARM is proprietary and not good enough. RISC-V from outside perspective seems to be good enough. Progress has to stop somewhere.

>I'm amateur.

My point exactly, and that's fine to choose whatever you're more comfortable with for your hobby projects, but when we're talking about actually developing products and shipping millions of units on tight budgets with high constraints, that need to operate flawlessly for decades in harsh environments, you'll realize why using "ye olde faithful" 30 year old AVR core, could make a lot more technical, business and financial sense than the newest shiny ARM based chips that just came out in <current_year>.

So, no offense, but amateur hobby work and shipping millions of products that need to be bullet proof, are worlds apart.

I've summarized your stance as "real men use C on AVR".

Newer technologies such as Rust fundamentally do not solve a technical problem, but a social one. As you say, anything can already be done reliably and cheaply using existing tools and chips _provided you already know the field_. What the new tech brings in is "knowledge scalability" - one can reuse much more of their experience from non-embedded platform and focus on learning the challenges specific to the MCU environment without having to deal with the incidental complexity of low-level programming.

Rust is transferable, but it's the RISC-V what-ifs that don't necessarily follow. You can run Rust or Zig on AVR.
> but when we're talking about actually developing products and shipping millions of units on tight budgets with high constraints, that need to operate flawlessly for decades in harsh environments, you'll realize why using "ye olde faithful" 30 year old AVR core, could make a lot more technical, business and financial sense than the newest shiny ARM based chips that just came out in <current_year>.

I've found the opposite to be true being a embedded engineer. AVRs in products typically smack of the Arduino->product pipeline and don't otherwise make much sense these days in professional circles. Their BoM cost is absurd versus the other options. That's why digikey still has thousands of avrs available, but stm32fs are still in the months of lead time or qty 25 from some sketchy resellers.

It's pretty hard to justify an AVR is a design review either at the ~$3 qty 1 space where you can instead have a 100mhz arm with more peripherals that might allow more consolidation of your design, or in the lower ends where there are cheaper micros when you're just babysitting one or two slow peripherals.

I don't think anyone would seriously claim that the existing 8-bit architectures represent any optimal design point (AVR definitely does not). A constant cycle of innovation is what characterize all technology progress.
Let's not let perfect be the enemy of good.

A lot of embedded devices and white goods are profitable to build and sell in the economies of scale, because they can reuse an old microcontroller design like the AVR, which is not the pinnacle anymore, but that's been proven over decades to be robust and reliable for specific use cases.

Technology progress is happening regardless, but not all products benefit from switching to the new shiny. Especially legacy boring products.

Some AVR perks like 5V tolerant I/O, and pins able to sink high currents, is something rarely found on newer more modern ARM or RISC-V chips which tend to be more "fragile" in some regards. So this is why sich older chips could still be advantageous.

> So this is why sich older chips could still be advantageous

Yup. I just found myself having to buffer an ESP32's output with an LS245!! because the old-school LED display I needed to drive required more current on its logic inputs than the ESP could source. An AVR would have driven it just fine.

And before anyone asked why I used a 74LS245 instead of a more appropriate level converter, I had to go with what's in stock these days and this design will have at most 3 units built.

AVR might be not optimal in mathematical sense, but it feels so nice:

- Tons of registers, up to a point where there are attiny parts with no RAM, and they are fairly usable;

- Great code density for embedded - single-instruction atomic GPIO bit sets/bit resets, branch-if-bit-set/reset, etc;

- In general, pretty approachable instruction set, if one fancies writing some assembly/machine code directly, while GCC also targets this ISA without issues;

- Brilliant JTAG-like hardware debugging interface that uses zero extra pins (reset pin is reused), and hardware-wise, interfacing requires serial port + one diode, that's it [0]

[0] https://github.com/dcwbrown/dwire-debug

What innovation is needed for 8 bit controllers? If you need something more powerful, get another controller: there are plenty. Are they less hardened, too expensive, or voltage-sensitive? Then that's where to look for innovation.
If we're talking about Rust and Risc-V specifically, there are pretty straightforward reasons for why people like them so much.

Rust: native code with very strong safety guarantees and no garbage collection. I have yet to see another language fit that niche.

Risc-V: fully open source processor design, along with a reference implementation and tooling. As far as I know, hardware does not have a history of being free and open.

HN is hacker news after all. People like to tinker. Just because something is tried-and-true doesn't mean it can't be improved on or be re-built for practice.

>Just because something is tried-and-true doesn't mean it can't be improved on or be re-built for practice.

And that's why HN should also consider to look outside of the fast moving tinkerer bubble and realize that if you're trying to sell some white goods profitably there's a reason why the old and tested is used and not the latest shiny.

Hardware development is completely different than web development.

You made me imagine an npm-like world for FPGA development of custom CPU from thousands of amateur packages. It was both funny anf horrible. Thanks?
Ada comes to mind, doing it since 1983.
Good reply! Why are we on hacker news if not because we are interested in new stuff?
We are into new stuff for sure!!

However, "hack" has a broader scope. Old stuff holds way more potential than one might think at first glance.

That "hacker", who digs in to the history will end up doing new stuff on that old stuff, often a "hack" and that can make "news."

:D

Cheers! 8 bits is enough, says my tagline. TGIF!

While I am excited about RISC-V, let makes sure we don't get carried away.

> Risc-V: fully open source processor design, along with a reference implementation and tooling. As far as I know, hardware does not have a history of being free and open.

Yes, it is possible to have more FOSS hardware, but this is not a guarantee. Companies can choose to keep their implementations closed and modify the implementations. RISC-V is permissively licensed afterall.

I really hope companies who implement RISC-V in the future keep open about their implementations, but it isn't a hard requirement.

People seem to confuse RISC-V as open source when really its an open standard ISA.
> Rust: native code with very strong safety guarantees and no garbage collection. I have yet to see another language fit that niche.

Ada?

As I understand it, RV32E is small enough to compete with existing 8 bit designs, and RISC-V architecture designers have settled on that as the smallest reasonable design point. There's been many proposals for a 16-bit adaptation of RISC-V (compared to the existing RV32 and RV64, and the proposed RV128) but the interest just isn't there.
There's a LOT more to this discussion.

SiFive claims they can fit a RV32E core into 13.5k gates, but to my knowledge, that's just the core itself without any of the IO, memory, etc.

A small 8051 implementation can be made in 2.7k gates with a lot of typical implementations using between 8 and 14k gates (but with a lot of proprietary features not actually in the spec).

Setting aside the question of power efficiency of 8-bit cores, the real question becomes one of instruction density as that determines the size of the storage and RAM (increasing these can have dramatic cost differences). To my knowledge, RV32E doesn't have a compressed instruction variant meaning every instruction is 32 bits long. 8051 instructions are between 8 and 24-bits long (generally, 8-bit for math, 16-bit for MOV, and 24-bit for immediates).

If you're working mostly on 8 or 16-bit data like a TON of MC work is, then I don't see how RV32E could have any advantage. If you're working with a lot of 32 or 64-bit data, then I can easily see a RV32E chip requiring less space for the same results.

A 16-bit only variant of RISC-V that repurposes the remaining 50% of the instruction space (used for marking 32 and 48-bit instructions) would be a much more interesting option here IMO.

> To my knowledge, RV32E doesn't have a compressed instruction variant meaning every instruction is 32 bits long.

AIUI, the E variant is designed to work quite well with the standard compressed encoding. Of course implementing compressed instruction decode takes some area, too; there will be some crossover point at which the density benefits of compressed instructions will more than pay for the higher complexity of decode.

Yeah, I've heard from someone implementing it that on an RV32I core (so not quite a RV32E, but pretty close), the area difference between implementing the compressed instructions and not was about the same as 64 bytes of SRAM. There is a cross over point, but it's pretty damn low. Particularly when you weigh the reduced size of the code memory needed, it's almost always a no brainer.
I am not speaking as someone working in industry but somebody with a hobby interest and as a writer. I have been looking at solutions to reach assembly to beginners. I think Things like Arduino and AVR has been great for beginners in terms of getting solutions up and running. Wiring works fine.

My issues is that I have realized that as a platform for teaching assembly it isn’t ideal. RISC-V gives a much friendlier ISA while also offering something which is realistic for modern hardware.

But wouldn't it be preferable to use a 32bit RISC-V uController or a dirt-cheap ARM core like the RP2040 for teaching? Any 8 bit platform would be specialized either towards legacy support or extreme cost optimization, but not towards beginner ease of use ...
As someone working in industry, I really have to wonder at the reason for teaching assembly to beginners while the rest of us are trying to move up the abstraction ladder. Care to expound on why you're doing this?
Debugging embedded software or even low level software or examining malware is much better at assembly level.
I see. I don't know much about malware, but I do know a bit about embedded programming and it's been a solid 20 years since assembly has helped me to debug something.
That is initially what RISC-V was for - it was born out of a teaching ISA that was easy to program and easy to implement in hardware.
HN is a news site, mature, battle proven solutions are not things people are hyped about.
RISC is a 32 or 64 bit arch. There was some discussion of a 16 bit version but it didn't get traction. 8 bits wouldn't really work: who wants an 8 bit cpu with 32 bit wide instructions? From a software perspective I could see some attraction to new 8-bit architectures, but in market terms it is legacy space by now, it seems to me.
That AVR has 8-bit registers isn't much of a benefit today. While it might make the AVR's core small, it requires more instructions to operate on 16-bit or 32-bit values — which a lot of code has to. For instance, an "int" in AVR C is 16 bits and because C does "integer promotion", it requires 16-bit semantics even when both operands are char. Despite having wider registers, I believe RISC-V cores could be made quite small too because of how lean its ISA is.

As a hobbyist, I use AVR mostly because it is 5V-capable and electrically robust, so it can interface with vintage peripherals without requiring signal-level converters or additional ESD protection. It would be nice to see more competition in this space, for sure.

While the C standard does say that integer promotion happens, if the result is being cast back to char again, a C compiler will see that it doesn't need to operate on 16 bits and is allowed to optimize the result back to 8 bit operations. See for example: https://godbolt.org/z/zM8reeqrc
I feel like 16-bit MCs aren't popular because they aren't popular.

They offer a straight-up 2x performance increase in most applications and something like a 4-10x performance increase with 32-bit numbers (not to mention the space savings from fewer instructions).

Despite this, the 16-bit MCs all seem to be rather niche. I'd love for an open RISC-V variant that could fill this gap and allow sourcing of the same ISA from multiple companies.

I dunno. AVR-8 is basically the last 8 bit CPU so it is much better than the CPUs we remember from the 1980s like the Z80, 6502, 6809, in most respects except RAM size. 32 registers is a lot! It also takes advantage of the Harvard architecture and has none of this pipelining and cache BS, most instructions take a cycle so if it runs at 20MHz it is basically running at 20 MIPS. Assembly language is beautiful and thinking about writing C for it makes me want to cry.

The one issue is that it has no upgrade path to anything more powerful so if you want something better it is going to be ARM or ESP32 so you might just keep writing portable C.

(comment deleted)
Why do you want that? What do you think that would look like? What about it appeals to you? Specifically?
As a side note, I am trying zig for embedded on tiny MCU and it is a better fit than rust. Not having to "move the borrow" for register around makes the code simpler to reason about and also is important when flash is only a few kb.

I think both languages have their applications and I am really happy with both.

I hope both languages (and others!) will help us make quality and robust softwares in the long run.

When you are coding in Rust for tiny MCU sooner or later you would code some functions in assembler or in unsafe Rust. At this point Rust does not provide much of the advantages over Zig as far as safety guarantees are concerned. Lightweight Zig seems to fit this space better that heavy Rust.
Besides the CTE and Cross compiling, what is objectively better in Zig then in Rust? Just the Rust ecosystem would sway me towards it honestly instead of something esotoric like Zig. Writing unsafe Rust is not really a problem I have.
Well, I am not saying it is better objectively, but for my uses it was easier.

I wrote a firmware in rust and I rewrote it in zig as my first real world exercice, I ended up with 90% less code. Rust has really great abstraction and I like it, but for some things it is overkill. In zig I didn't need much of the abstraction because I did not have to make the borrow checker happy. In rust you have to structure your code in a way each part of it will have access to what it needs. In zig you just access it, as a global if needed. And sometimes the ability that zig code have to fit in memory (mine) is a real productivity boost.

Small MCU programming usually doesn't use dynamic memory allocation at all. Does Rust bring borrowing into play in any other situations?

I don't know anything about Zig and should probably look into it, but I think Ada is underrated for MCU's.

Yes. Borrow checking is unrelated to dynamic memory allocation. The borrow checker checks that references point to valid memory. The location of that memory is not relevant.

Also, Rust is more than a borrow checker. My day job is working on an embedded system that has zero dynamic allocation, and Rust’s other features are still very valuable to us, independent of the borrow checker (which also does bring value, to be clear.)

Out of curiosity, what Zig features do you find useful when it comes to programming for those 8-bit MCUs with tiny flash?
Native support for static allocators like arena. Ability to compile C and call it with 0 efforts.
Could you give an example of `move the borrow`? I've noticed a lot of cumbersome APIs on Rust embedded, usually with the intent of building out an ecosystem vice writing firmware.
I wasn't very clear, I clarified below.
can you elaborate on what you mean by "move the borrow around registers", an example maybe? what other things are you experienced that are struggling doing in rust?
I meant move the ownership.

For one firmware, I have some code that keep the MCU sleeping and it wakes with I2C address match. When the I2C code handles the match, it must change the configuration of the system registers related to sleep to stay awake when waiting for interrupt, this means my I2C controller must be the owner of that register so it can change it. But after I2C handled the request the I2C controller must pass the register to the other controller that will go back to sleep when done. In rust I do that by having an Option<TheRegister> in both controller, and when I2C is done, main controller do the_option.take() to grab the register, do its job, then put it back. The usual way to do that in rust is to use Arc<Mutex<T>> but that doesn't work in my MCU, so I use the Option trick.

The other hard thing is DMA, it requires a lot of fidling, while in zig it jus works.

I'd argue these are related to current rust libraries rather than with Rust itself. For practical purposes this might not matter. I've been making an effort to clarify this, as I'm worried these early APIs will scare people away from Rust on embedded. I had to write my own HAL (with ergonomics and DMA-based APIs as priorities) since I ran into the same problems you describe.
“Also, that the 8-bit machines are seeing increasing use as co-processors, performing tasks like taking sensor readings and pre-processing this sensor data before passing it on to the higher-level processor.”
I just came out of a embedded Linux training, and the guy basically told us that if we want to have hard real time constraints, it is easier to execute real time stuff on a dedicated microcontroller on the side. I find it crazy that we need such a powerful MCU to run Linux, but still it is not fit for real time.
When I worked at Qualcomm this is exactly what we used to do, if I rememeber correctly even parts of the USB driver used to run on one.
It really depends on what you're doing, but there are certainly versions of Linux that are capable of hard real-time performance. But it shouldn't be too surprising that the goals of an operating system designed for multiuser, multiprocess context is not well aligned with the needs of real-time machine control applications. The trainer is correct, often times it really is appropriate to just delegate those requirements to a dedicated controller whose job is to do nothing else than keep performing the same DSP loop over and over in a well-timed manner. However, there are certainly cases where you might want to interact smoothly between real-time and non-real-time components of a system and use things like shared memory, and in those cases, there definitely are Linux-based solutions available. Like most things in engineering, there are trade-offs along this continuum, so knowing the options and the pros and cons so that you can make a good design decision is just part of the job.
Hard real time, yes. But with very high tolerances compared to what a MHz processor can accomplish just running the application.
The only version of linux I know of that's capable of hard real time performance isn't really linux anymore but instead just runs an rtos microkernel underneath linux to make real time guarantess and simply runs linux as the lowest priority task on that kernel.

https://en.wikipedia.org/wiki/RTLinux

RTLinux is quite old. There's an official patchset for real-time preemption in Linux that's making its way to the mainline kernel.
If you're talking about the preempt-rt patches being merged, those are very soft real time.
(comment deleted)
Can I ask, which training was that?
A week long course with a Linux greybeard in my country. It focused on how to make our own Linux distribution (using yocto) for our future embedded platform.
If you are hard real time, then the ability to country hose many cycles each assember instruction will take makes it easy to prove your code is correct. Run on a much faster modern 64 bit CPU with branch prediction, caches, and other tricks and there is no way to know how long any instruction will take. Getting non-real time things done is faster on the 64bit CPU, but the 8 bit is going to get the things it does done one time every time.
Each job requires a tool that does it best, within some limits.

To set a bit in GPIO:

- on AVR, one assembly instruction, 2 bytes machine code, 1 CPU cycle (unless interrupts are enabled);

- on microcontroller-style ARM (Pi-pico), 2-4 assembly instructions, 8-20 bytes machine code (depending on compiler options), 4-12 CPU cycles. All numbers deterministic within the same build (unless code cache is cold, then 50+ cycles, and don't forget interrupts);

- on ARM+linux, hardcore mode: same as above + small, deterministic number of extra cycles since GPIO runs at slower clock than CPU. That assumes you go out of your way to reserve CPU core, set rt_prio for your task, etc...;

- on linux, via sysfs: who knows. 1000 CPU cycles is probably the lower bound, but each run is going to take different amount of time. On a busy system, some - as long as a few seconds.

The pi-pico does have that cute PIO state machine though to baby sit GPIO and get single cycle granularity out of it.
Yep, I suspect that will be the path forward. Same high level strategy, but integrated into a single package. It will be interesting to see if the babysitters remain state machines or if they grow into tiny little microcontrollers.
Or tiny little FPGAs connected to the GPIO lines would be neat too.
Many automotive MCUs have complexe timer coprocessors integrated for hard real time I/O purpose. Examples are GTM, eTPU and N2HET that I know about. Does the PIO work in the same way?
This is exactly the division of labor my current project has. The UI and data storage run on a Linux System On Module and the real time control is on an STM32 processor running an RTOS. Pretty standard these days.

I've been on projects where the Linux part would have been offloaded to a tablet or an Android SBC running an app and communicating to the real time processor via BLE.

Perhaps counter-intuitively, big complex CPUs are incredibly bad at real time control. Instruction latency and jitter can be huge when dealing with complex caching systems, deep instruction pipelines, etc.

If you have serious hard real time requirements, you will be using a very simple 8bit mcu.

Both processor hardware and the Linux operating system are powerful in large part because they're opportunistic. But that's the opposite of predictable, which is what defines hard real-time.
About a decade ago I was designing a controller for an RS485 sensor net. It was a mass of UARTS (for each 485 bus) and an AVR manage communication between the busses and the host. I was quite surprised that it was cheaper to buy AVRs just for their onboard UARTs than to simply buy UART chips. Such is the power of volume.
I'm at a point with a design where I cannot find any SPI, I2C, or indeed any other serial Programmable Interval Timers and I can't even get my hands on SMD 8253s, so I'm considering just using some sort of microcontroller instead.
It is also very nice for safety related tasks because it makes a code audit much simpler.
(comment deleted)
Do these have cost savings over a budget-series 32-bit MCU, eg using Cortex-M0? For example, STM32G0 is very cheap (~$1-4 USD depending on variant and quantity), and has a number of peripherals.

My guess: 8-bit MCUs are used for high-production run, minimal cost uses where the MCU does one specific task, probably in a network with other MCUs. In these cases, they could offer cost savings, even over an M0/M0+.

Yes. You can get an 8-bit for $0.15 in quantity and they go down to 6-pin SOT-23 or even smaller parts.

The PIC10F320 is an interesting one as it can replace a fairly large amount of discrete logic very easily. I think I paid $0.47 in one off quantity for those! It was used to entirely replace a couple of timers and a state machine.

(comment deleted)