Don't Worry, C and Rust Can FINALLY Coexist (Here's How) | Embedded Rust and C on the RP2040 Pi Pico

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
finally c and rust can peacefully co-exist if you don't believe me stick around to the end of this video to find out in this video we take a raspberry pi pico and write code in both c and rust that compile down and run on the embedded arm cortex m0 processor okay so to make this project that runs both c and rust on a raspberry pi pico we'll have to do a few things first like in any other video i've done where we use raspberry pi pico we have to get clone the raspberry pi pico sdk i'll show you here where that comes from it's just a set of libraries and code that raspberry pi wrote that allows you to interface with the raspberry pi pico using kind of a hardware abstraction layer so go ahead and clone that i've already got it so i'm not going to do that right in front of you guys um next you're going to clone this project here it's actually the code that i've written to prepare for this video you can download this and follow along with me if you're interested in doing so that code if you open it looks like this here on the right it uses the raspberry pi pico api to essentially turn on the default pin and doing it all in c right so if we do cmake dot and we do make it'll build the binary into the uf2 file that we can put onto the raspberry pi pico and i'll show you here that mine currently is blinking as this code intends it to so this isn't important right this isn't cool we don't care about this we want to we want to write rust and make them work together the c and the rust so step one to do that will be we'll make a new cargo file or a new crate and we'll call it rusty so rusty is going to be the location where we compile our rust library that we then incorporate into our c program and then use that library to do things in rust and jump between rust and sea so to do this properly we need to edit this cargo file right so this cargo file gets generated like this by default nothing really important here basically say the package name is rusty we have our initial version and that we made it in 2021 it's actually wrong but you know not a big deal um we need to do a few things to enable this cargo package to be compiled as a static library a static library in a dynamic library are different and we have to do static for an important reason that i'll tell you later in the video to make it a library we'll do this lib mark here this tells the package hey this package produces a library uh the library name for us will just be the same it'll be rusty and it's going to be the crate type of a static library a static lib the static lib here tells the compiler and the linker to produce a dot a file an archive file as opposed to a so file so once we have that now we got to actually write the code that we want to happen in rust so by default rust will create this source folder for you here we're going to actually remove the main.rs because this will get compiled into a full rust executable and instead we're going to write a lib.rs because we are a library the entry point for this library will start at lib.rs to begin we are going to write an embedded program so we're going to type no standard to make sure that rust does not try to compile in the rust standard library into our library and make it this huge you know blob of code that we don't really need right next because we are going to end up decoding in a embedded environment we need to incorporate a panic handler so we need to use the panic info type and declare our custom panic handler when we're embedded we need to tell the compiler hey if something goes wrong what do i do and we do that with this notation here panic handler and we'll make a function called panic with a k for the lulls that takes a panic info as input and it's of type panic info reference and it returns nothing and actually doesn't return at all and then what it will do is it'll just loop infinitely we will really not handle the panic if the board panics we're just gonna have to kind of deal with it and figure it out ourselves don't worry about this too much the important code here is where the code for you know that we write in rust actually begins we need to be able to export this code to the c interface and allow c to link with it the way we do that is we say first pound no mangle this basically guarantees that the function declaration that we come up with is exposed to c in a way that it can understand right and we're going to say there is a public external c type function we're going to call it set and sleep and we'll talk about that why in a minute it takes a pin which is an i32 and an on off value which is a bool and it yields an i32 let's zoom out a little bit i 32 and for right now it's just gonna return one that's all so basically this is a function that c can link with and it will return one here no no really craziness going on there so now that we have this code written that exposes a set and sleep function that c can link with we need to build this library to actually try to link it into our project right to do this we do cargo builds that builds a project we want to set it to release mode to strip out all the unnecessary bloat code and debug code that comes by default with the rust crate and then also we want to set the target to be this here it's the thumb architecture for arm arm v6 no underlying os abi and the extended abi for the arm cortex m0 so we'll do this there are some uh you know things that the compiler is concerned about one of them being that we don't use any of the function parameters that we set but that's not a big deal if we go into the target thumbnail abi folder and then into release you'll see we've created this lib rusty here so we're going to do is we're actually going to copy this path and use that to eventually link up the rest of our project with this library here so we'll go into our cmix file and there's a bunch of code here that tells cmake essentially how to build our makefile to build our project we want to add lib rusty.a into this target link library so it tells the compiler hey when you're looking for code also look at this additional archive library we need to do is add the cmake source path here so we make source der and then add the path to our our library here so it's cmakesorster which is the current directory here rb 2040 blank and then we will do slash rusty target thumb mode blah blah blah all the way to incorporate our library so we'll finish up and include that with cmake dot and run make to confirm that it actually makes it okay so we haven't actually incorporated any code here what we're able to do now though is go into our blink.c and actually use this function that we've created in rust so we'll go ahead and copy that out and we're going to create a prototype in our c file to know where to link against we're going to do uh it actually returns an in so int set in sleep takes into x and into y we don't really care about the parameters right now and we could say that intex equals set set and sleep one two right this doesn't actually do anything we're just proving a point that we can copy or that we can write this code in rust expose it externally to c return a value and then call that function in a c file that runs embedded right so we'll see make dot again to confirm that our whole building gets recreated and we'll type make cool so we can actually see that our program got built here this uh blink dot elf and we can actually go in with object dump and look at the file and then we're gonna search with slash for set and sleep just to confirm that in the main function set and sleep does get called so this is pretty cool right our main function written in c links up against a rust function and then uses that rust function to do something in rust whatever we wanted to do right now it just returns one and then eventually goes back and continues the rest of the execution so you may be thinking this code is pretty dumb it just returns the number one from rust who cares and you're actually right this code to be important needs to make use of the raspberry pi pico stks exposed c apis there is one problem with raspberry pi pico's sdk in that the api calls are actually inline so they are included at the source level and because of that we can't use them as an externally linked function in rust so what we need to do is actually create a jumper function a function that allows us to jump into these inline functions here in our c program so that rust can access them we're going to call it a void function it's going to be called the gpio put explicit it'll do is it'll take an int pin number and a bool on or off and it's going to call gpio put on pin and on off and then return the reason we're doing this is we need to create a symbol that is not inline that rust can actually access to make use of the c code without this here it actually has no idea where gpio put lives so now that we have gpio put exposed through our explicit function declaration and sleep ms already exposed publicly because it's a real function and not an inline what we can do is we can edit our rust to expose these functions in rust using the extern calls so extern here basically tells linker hey i'm about to say some function names that we're not going to write ourselves they're going to come from what's called a foreign function interface the foreign function interface here for these will be first the function gpio put explicit which will take a pin value of i32 and an on off of bool and it will return again it's actually a void but for now we're just going to lie and say it takes an i-32 and then also we'll expose a function of sleep ms which takes a time as an i-32 and again null but returns i-32 we're gonna lie to the compiler and then we're going to edit our set and sleep prototype here to also take a time as an i32 as well we're going to write set and sleep to do what it says we're going to call our gpio put explicit and again this is an unsafe call because it's a c function we're going to call our gpi output explicit which lives over here in c land with the parameters pin and on off and then we're going to call sleep ms with the provided time and then at the end here we'll return one the idea here is we're just proving the point that we can use an exposed c api inside of rust do some rust logic and then return back to a c function here and what we'll do is we'll actually use this to completely replace the logic of our program so instead of gpio put led pin one and sleep we can just do set and sleep led pin one and it will sleep for a thousand milliseconds and then we'll set and sleep led pin zero 1000 milliseconds we need to edit our prototype here and we'll make it actually correct we'll say int pin in or bool on off and then into time and then there we go so what will actually happen here is we will run c we will go through this loop we will do set and sleep which will actually be a far jump into our rust library the rust library will use the exposed gpio put explicit which lives over here in c and then call sleep and then return one so what we have to do to get this to work is first go into our rusty library and cargo build should be no issues there awesome we'll go back and we'll type make well full build no dependency issues nice and and clean and then finally we need to actually copy the library onto our raspberry pi pico so do that real quick and we'll copy it right here okay and as you can see we now have our raspberry pi pico sitting there and blinking at the interval that we specified in our c file but making use of that in a rust file guys i hope you learned something i hope you learned that you know c and russ actually do play together pretty well you got to kind of trick the tool chains to work together but once you figure that out it's actually not that much work to make a c function called rust or a rust function called c or vice versa um if you enjoyed this video you learned something or you dislike me do me a favor hit like hit subscribe check out my merch store link in the description below and i'll see you guys next week take care [Music] you
Info
Channel: Low Level Learning
Views: 48,061
Rating: undefined out of 5
Keywords: rust programming, embedded rust, rust and c embedded, rust memory safety, rust hello world, arduino, maker, craft, hobby, electronics, wires, temperature, safety, project, board, electric, leds, led, thonny, python, micropython, os, ide, onewire, ds18b20, circuitpython, review, launch, measure, probe, rp2040, specs, specifications, how to, guide, programming, Pico emulation, retro games raspberry pi pico, etaprime, eta prime, raspberry pi pico, arm cortex m0+, low cost
Id: zSWkrpu8KBA
Channel Id: undefined
Length: 12min 26sec (746 seconds)
Published: Sat Mar 26 2022
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.