
FLOSS Weekly
Episode 878 transcript
FLOSS-878 Jonathan Bennett: This week I'm talking with Jonathan Pallant about Rust and primarily in the embedded world, the Raspberry Pi Pico, the Nordic, Espressif, all of your favorite little MCUs. You can run Rust there and partially due to efforts by people like Jonathan. This is Floss Weekly, episode 878, recorded Tuesday, August the 4th. A tool with opinions Hey, folks. It's time for FOSS Weekly. That's the show about free, libre, and open source software. I am your host, Jonathan Bennett, and today, once again, we're gonna get rusty. Whereas last time though, when we talked to someone with Ferrous Systems, we were talking about Rust on the Linux desktop, in user space, Rust on general purpose computers, and today we're talking about Rust somewhere a little different. I've got Jonathan Palant with us today. He is also from Ferrous Systems. In fact, I think his day job is teaching Rust there, and I think also doing some programming work. But let's get him on and ask about all of the places where Rust runs that you may not have thought about. Hey, Jonathan. Welcome to the show. Jonathan Pallant: Great to be here. Thanks for having me. Jonathan Bennett: Yeah, it's good to have you back. Or no, you for the first time. Good to have Ferrous Systems back. The second interview with one of you guys in a couple of months now. All right, so this, this magical thing called Rust it runs on the desktop, it runs on the server, it also runs on the Raspberry Pi Pico? Jonathan Pallant: Yeah. It- So joys of having a systems programming language, right? You get a compiler, source code goes in, machine code comes out, right? So anything that runs the machine code should be able to run it. So yeah, Rust is really interesting in being able to scale from the very, very large. It is the language that powers Amazon Web Services, and Cloudflare, and Google, and a whole bunch of other stuff. But it scales down to, as you talked last time, desktop applications- ... things like Sudo written in Rust. But also scales down to the small, very small. How small is always an interesting question, but- Jonathan Bennett: Yes, it is. Jonathan Pallant: I have run Rust on ST Micro, Microcontroller, Arm Cortex-M4 32K flash, 4K RAM. As modern things go, that's pretty small. I'm not sure I'd be happy squeezing Rust-generated code onto like a Z80 or a 6502. That may be a bit too small, but certainly tens of K of flash, a few K of RAM, I think- ... is quite workable. Jonathan Bennett: I happen to have here the Seeed Studio Xiao board actually their next generation Xiao board. It is a Nordic nRF54. The word Xiao in Chinese means tiny, and it is an appropriate name, as you can see. T- Can we do Rust on a nRF as well, on, on Nordic? Jonathan Pallant: Yeah. So Nordic semi generally use Cortex-M4 M0 in the nRF51, M4 in the nRF52. I did a lot of work with their cellular modules. Don't know if you've ever used a 9160? Jonathan Bennett: I've not, Jonathan Pallant: but- the very small device that does LTE Cat M- ... so the, the IoT version of 4G, and that comes with a Cortex M33 that you get to play with, and then a secret second processor that runs the modem firmware- ... that you are absolutely not allowed to play with because cellular. Jonathan Bennett: Yeah. Okay. So the ... Boy, the, the embedded world is an interesting world. There's a large there's quite the gamut of different things that count as embedded, and sometimes the lines get a little blurred, right? Because you can take the Linux kernel and run it on an ESP32-S3. Now, it's not a fun experience, but you can do it. It'll boot. It can be made to, it can be made to happen. And so i- it's interesting to me that Rust goes all the way down to some of those very, very small targets. How does that work? Is there an operating system that a, a Rust binary is then running on top of? Is there some kind of real time operate OS? Do you guys run on Zephyr, or is, are you literally just writing Rust that runs on the bare metal? Jonathan Pallant: Yeah the output of the, the Rust compiler, it works like a C compiler. Source code goes in, machine code comes out. So the compiler doesn't really care whether- ... you have an operating system or not. You could absolutely be the first code that boots when the system comes out of reset. Jonathan Bennett: But I mean- Where- ... there's like the question of am I making system calls to a kernel? Am I telling the kernel to do, the, the multitasking stuff, or am I just always, is the binary always running on the Jonathan Pallant: CPU? And where that comes in is less in the, the language, but more in Rust's choice of standard library. People say, "Ah, the standard library," as if it's one thing. But as with all good things, it's actually three things in a trench coat. The, the top part of the standard library in Rust is the thing that knows about files and threads and networking, and that's the thing that's gonna be operating system specific. And it's basically the Rust equivalent of hash defines that say, "Hey, if you're on Windows, we're gonna call this Windows function, but if you're on POSIX, we're gonna call, open read and write." Sure. And that's what lib std is doing. It's this operating system abstraction layer. As I said, file system, networking, threading. Below that you've got the heap allocator and all of the heap allocated collections. They actually live in their own separate library. If you're a Windows, Mac, or Linux user, you may not be aware of that because it's hidden, and everything heap-related is all exposed at the top level anyway. But there is this lib alloc, so if you want a heap allocator, it lives there. And then you've got these fundamental Rust types, these things that no Rust program can live without, and that don't actually care about what operating system. If you've used Rust, you'll be familiar with the result and the option types. They're enums, they are generic, they need to be defined in a library somewhere. And things like that go into a library called lib core. So when people write bare metal Rust, so Rust running on a Cortex-M4 or a RISC-V processor with no operating system these people say, "Oh, I'm using Rust as no std." And what they mean is I'm using the Rust standard library, but I've basically switched off the top half and I'm only using lib core. So I'm only using the parts that are operating system agnostic. No file system, no threading, no networking, but you do get Unicode string handling, as I say, result and option types, sort of fundamental properties of integers and floats and things like that. Jonathan Bennett: It, does this work hand-in-hand with a like an SDK the published stuff that the vendor puts out? So like we, we mentioned the Nordic. Obviously Nordic writes... I mean they, they've written Zephyr support. They've also got their oh, I forget what they call it, their little shim libraries, almost like an OS. SoftDevice I think they call it. And so when we're in Arduino land with C and C++, we do a lot with SoftDevice on the Nordic devices. Do, do... When you write Rust, do you use that stuff on this, this sort of a device, or are you f- blaze your own path? Jonathan Pallant: People come at this from different places. I went to a trade show in London recently, and I went round and surveyed all the people there who had the booths down at the show in London, said how do you write embedded firmware?" And honestly, I was surprised at how often Zephyr comes up. A lot of people seem to be really into Zephyr. And if you wanna use Zephyr, absolutely, you can put Rust on top, build your little Rust applications, link them into the Zephyr kernel, and that's all gonna work great. I wouldn't describe myself as a purist- but I'm in this to push what Rust can do. A great analogy came up the other day about about, about AI usage, and it was like sometimes there are heavy things that need to be lifted, and sometimes this is your job, and you should use whatever machine you've got to lift the heavy things. And sometimes it's 'cause you're at the gym- ... and if you bring a forklift truck to the gym, you are defeating the point. You're cheating. When I write Rust, I'm at the gym, and I wanna do it the hard way because I wanna practice my Rust, but also I wanna show what Rust can do- ... and find if there are any corners where Rust doesn't work. 'Cause I wanna know about those- ... and maybe I can go to the Rust project and get them fixed, or, I can educate my customers about areas where Rust doesn't work. So- Yeah ... for me, going bare metal is always more interesting. Jamming random integers into random memory addresses, that's where I'm most comfortable. But if people wanna use like a FreeRTOS or a ThreadX or any number of real-time operating systems that are written in Rust- If that gets the job done, that's great. Jonathan Bennett: Yeah. I think that's actually a really good segue to ask the question of what do- what is your day job? You're not... Are you writing production code, or are you doing the the education thing there at Ferrous? Jonathan Pallant: So my I asked for the words senior embeddage engineer to be written on my business card- Okay ... because it covers a multitude of sins. Technically what I'm doing mostly is teaching. So I teach Rust. I am the lead trainer. I'm responsible for all of our training materials, which are all open source. Anyone listening can just go and find Ferrous Systems Rust training, read all my slides, do all my exercises. It's all creative commons. You can help yourself. But I can't only teach, one, because my head would melt. I did a day of teaching today. I've been teaching eight hours already, so I may- ... yeah, just dribble a little bit. But also, yeah, you need breaks. But also, if I only taught Rust I don't think I would get better at Rust. There is an a need to sharpen the knives and practice the tools. So in between trainings, I'm, like, picking random dev kits and going, "Great, let's do some Rust on this. Let's write some training material about it. Let's pick an entirely new platform nobody's ever written Rust before." I have in my hands a lovely NXP developer kit. S32Z2 for the people who don't have video. This is get this right, eight Cortex-R52 with 20 megs of RAM. Jonathan Bennett: Oh, wow. Jonathan Pallant: As microcontrollers go- It's huge ... this thing is cooking. But it can't run Linux because none of these processors have an MMU. These are all- ... Arm's real-time platform. So a couple years ago I was like, "Can you even do this in Rust?" Probably, but I don't find anyone online who's done it in Rust. So we called in a favor from NXP. We got the board. I would not personally wanna buy one of these out of my own pocket money. It's a little out of my fun budget. Yeah, and we got Rust running on it bare metal, dual-core lop step. We can run asynchronous Rust. We got the interrupt controller going. But I do that because it's interesting and because it ends up useful for customers and useful as training material, yeah, embedded systems engineer, as I said, covers a multitude of sins. Jonathan Bennett: Rust and embed- the embedded world as a whole is really a moving target as places like NXP and STMicro and Microchip, Nordic, and all the rest of Espressif, everybody, they're constantly pushing the envelope, releasing new things, g- gluing new weird chips together that we didn't think we would ever see, and then suddenly- you see it at a trade show or a talk. But it's a moving target, and if all you're doing was education, then, you're, you would get stale, right? So I think it's incredibly useful to stay hands-on with the technology. Jonathan Pallant: No, absolutely, and I try to make it out to Embedded World every year to run the booth, but also just to walk the floor and- go and see what's new and get a sense of how things are training changing. You go to Embedded World three or four years ago- most of the floor didn't know what Rust was. "Do you do Rust?" "No." "What's Rust? Tell me about Rust." And this, they'd never heard of it. And now they're like, "Yeah, no, we've heard of it. It feels like a thing we should be doing." But certainly I think these big silicon vendors are thinking about, "What is my next step? How would I introduce this without alienating all of my existing customers who like the CSDK? Is there a migration path? How... do these things feel the same or do they feel different?" Espressif, I gotta give shout-out to them for being far ahead here. They basically hired all the open source hobbyists who were doing Rust on their chips. Gave them a job and they have their own Rust team. We've seen Rust news out of Infineon as well. Yeah, and I hope we see more out of the other silicon vendors as well because if they don't do it, who will? I mean me, but my time is somewhat limited and there's only so many dev kits I can buy. And it's the open source community. It's random hobbyists who go, "Oh, I've got a random dev kit I got off Adafruit or whatever. Got a chip. Does this have Rust support? I don't know, let's write something. Let's put something together." And we have all this sort of flourishing ecosystem around STMicro, around Nordic, around Raspberry Pi. I personally did the Rust support for the 2350. That was fun 'cause they gave me pre-production chips, so we had Rust support ready to go on launch day. But these are all independent ecosystems with their own thing going on. Which is great if you just wanna get into Rust and have some fun. But if you are- on the hook to design the firmware for a product where you wanna make a million a month, I can see why you may not just want to pick up random packages online, and you may wanna talk to the silicon vendor or someone else- and get a bit more professional support. Jonathan Bennett: Because the way where madness lies, and I know because we've done this ourselves, is you end up coming along and forking about 100 different packages, that you've got your own version of the library because you have some fix, and the upstream library is dead, or you can't get ahold of the maintainer, or this or that. Yeah. Been there, done that. That's my life these days. How similar is it? We've thrown out a lot of different embedded architectures. So again, compare, like, Nordic to the Raspberry Pi Pico. Can you write one Rust program and get it to run on both places? Is there cross-platform driver support? So say I've got a an I2C-connected temperature probe. Can I write one Rust driver for that and run the same code on the Pico and the the, the Nordic? Jonathan Pallant: You can, and this is thanks to the work of a great bunch of people called the Rust Embedded Devices Working Group. So take you back to 2017. I'm just starting to get into Rust. I'm using a random TI Stellaris dev kit that I happened to have lying around, and I'm doing my own thing, and some other people are doing their own thing, and we find each other. And we're like, "We're C developers. We've written a lot of C code." "Rust looks fun, but we're very aware of how-" I describe the C embedded ecosystem as like islands. And these islands are all really quite far apart. Yeah. And if you live in Nordic island, and I don't know, you happen to run out of chips 'cause there's a chip shortage, and you wanna get over to- Jonathan Bennett: That would Jonathan Pallant: never happen ... ST Island, to get over to ST Island, those islands are quite far apart, and it's pretty difficult to write, say, a cross-platform driver that, that works across that. And we looked at that and we said, "What could we do in this fledging fledgling Rust embedded ecosystem to try to, for that not to happen?" And the Rust language mechanism that it offers for that is a thing called a trait. And if you're a C programmer, you can think of it like struct full of function pointers. That's how the Linux kernel does it. That's how the Linux kernel thinks one disk controller looks like another. They both, drivers, provide a struct with a function point of open and a function point of a close, and read block and write block. In Rust we call that a trait. So the Rust embedded working group published some traits, and there's a trait for I2C, and there's a trait for SPI, and a couple of other sort of common peripherals, GPIO- razor pin high or low. And then what someone needs to do is come along and say, "Oh, I would like Rust to be usable on i- my particular chip." NRF 52 for example. So you would write some Rust code, and you would implement the trait. So here's my I2C driver- Yep ... represents this peripheral, and it implements the trait. When I flip to the other side, someone's got- a CO2 sensor. Little I2C device, measure the air quality. I've got- And they just need an Jonathan Bennett: I squared- I've got one of those on the desk behind me waiting for me to either find or write a driver for it. Jonathan Pallant: Fantastic. And you just need an I2C bus to put it on. And what do I2C devices need to do? The driver needs to do a read maybe do a, a write and then a read. There's a couple of fairly basic operations. 7-bit addresses, 10-bit addresses, and that's all encoded in the trait. So if I wanna write a Rust driver for my little CO2 sensor, I am generic over some type T, where I don't care what type T is as long as it implements embedded hal colon I2C- some trait. And then a third person comes along, and they're like, "I may be the first person in the universe to use that CO2 sensor with that microcontroller." And they can compose it together. Yep. And in general, it should just work. You will... There's ef- efficiencies that you will lose because it's a g- sort of a very generic API- that's not very- ... chip specific. But the trade-off is, yeah, here's my random Adafruit LCD screen, here's my CO2 sensor. Plop them all on a board. Here's a, a, what we call a, a HAL implementation someone's written for this chip, and it should all just work together, and generally it does. Jonathan Bennett: Yeah, that's very cool. It's actually similar to the way the the Adafruit excuse me, the Arduino ecosystem has evolved. You've got kind of that, that same idea in mostly C code, some C++, but it's that same idea. We've got an abstraction of here's what a wire bus is going to look like. It's usually what you see it called. And then somebody else can come along and write a driver for it. Was that part of the inspiration? Jonathan Pallant: Yeah, I think we'd the people who formed the Embedded Work Group, we'd obviously used Arduino before, but we'd also used these kind of very vendor-specific SDKs. But you also get the, the classic embedded commercial vendors. They all have their own stacks and their, probably their own in-house operating system. It seems every embedded company's got their own operating system they've had since the '90s- Of course ... and that kind of stuff. So we've seen all of that. And what would a, like a utopian future look like? I'd love anybody to be able to pick up any MCU- and any device and just plug them together. Jonathan Bennett: Do you see vendors actually starting to write the the, that bottom half, that support layer for you guys? Jonathan Pallant: So we have seen Espressif do that. So they publish all of the, the, the drivers you need for their chips. For most of the other vendors, I think we've seen something from Infineon. But for most of the other vendors it's wait and see. Maybe throw the hobbyists a bone, some free hardware occasionally. But that's all mainly hobbyist-driven. I will shout out STMicro, who have done the other side. Surprised me. But if you've got your little STMicro sensors, 'cause obviously they don't just make MCUs- I believe they have all these sensing modules as well. They will give you Rust drivers for the sensors. Jonathan Bennett: Cool. Jonathan Pallant: Which you can just get from STMicro's GitHub and use, and then use those drivers with your other Rust co

