What? More 8-Bit Microcontrollers?
eejournal.com
eejournal.com
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.
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.
I don't know anything about Zig and should probably look into it, but I think Ada is underrated for MCU's.
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.)
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.
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+.
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.
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.
If you have serious hard real time requirements, you will be using a very simple 8bit mcu.
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.
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
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.
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.
> 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.
Ada?
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!
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.
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.
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.
- 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]
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.
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.
What else does this "etc" include?
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.
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
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.
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.
You're just making up FUD.
Lol.
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.
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.
I think there is no (embedded) language so far which prevents you from having bugs in business logic.
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.
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.
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.
And then the naive solution ran at 100 fps.
So uh. Okay then. I see the value in Rust now.
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.
100k saved is 100k earned. Half a Ferrari.
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.
A professional programmer who does not find C scary is about as confidence inspiring as a nuclear engineer who does not find plutonium scary.
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.
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 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.
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.
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.
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.
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.
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.