Fixing HORRIBLE Embedded Rust So You Don’t Have To

  Рет қаралды 100,010

Low Level Learning

Low Level Learning

Күн бұрын

In my previous Rust video, I did some pretty hacky code to get my Raspberry Pi to Blink an LED. We used the Raspberry Pi Datasheet to come up with some hacky unsafe code that enabled a GPIO pin to be an output, and then blinked it on and off. We did this ALL BAREMETAL with no operating system underneath our code.
The code WORKED. But, it doesn't port well, and it's not very RUSTY. In this video, I'll take my previous embedded Rust code and make it more Rusty by creating parts to a Peripheral Access Crate. A Peripheral Access Crate or PAC is a component to a Hardware Abstraction Layer in Rust. Hardware Abstraction Layers abstract away the memory addresses and pointers to memory mapped IO to make programming embedded systems a little easier.
🏫 COURSES 🏫
C Programming 101 for Aspiring Embedded Developers: www.udemy.com/course/c-progra...
🔥 SOCIALS 🔥
Low Level Merch!: www.linktr.ee/lowlevellearning
Follow me on Twitter: / lowleveltweets
Follow me on Twitch: / lowlevellearning
Join me on Discord!: / discord
0:00 Intro
0:21 Code Review
0:41 Lets Code!
0:59 Making a Clean Interface
1:37 Datasheet 4 Life
2:30 Match Statements
3:46 Unsafe but LESS
4:21 Binary Math
6:35 PUT IT BACK
7:20 One Down Two to Go
7:47 NEXT!
9:29 DOUBLE KILL
10:13 Linker Hack
11:03 Outro

Пікірлер: 268
@LowLevelLearning
@LowLevelLearning Жыл бұрын
COME HANG OUT ON TWITCH KEKW www.twitch.tv/lowlevellearning
@FoxDr
@FoxDr Жыл бұрын
This is now much more explicit, but not quite Rust-y yet. One of Rust's great things is that it helps prevent logic bugs (such as writing to a non-output pin) using the typesystem (technically you can do some of that in C, but in Rust it's the idiomatic way). The GPIO could return an OutPin for example, and that OutPin would have the set method instead, guaranteeing that you never write to a non-output and letting you not have to use the pin number again. The GPIO could even return an Option, which would be None if it's already used, by you or an other program (since it's DMA, other programs that use the GPIO would also need to set the same registers)
@edgeeffect
@edgeeffect Жыл бұрын
Make invalid states unrepresentable.
@DanForbesAgain
@DanForbesAgain Жыл бұрын
Love your videos, but an error message of "Something has gone terribly wrong" is questionable at best when it comes to advice aimed at improving code 😅
@LowLevelLearning
@LowLevelLearning Жыл бұрын
Lol... concur. You should never get to that part of the code, but agree that maybe the error message isn't great XD
@DanForbesAgain
@DanForbesAgain Жыл бұрын
It would totally be possible to enter that code path since the function accepts a u32 and not like an enum or something, but yeah I totally hear what you're saying. But you know what they say...one good error message is worth 1000 GitHub Issues 😅
@emilien.breton
@emilien.breton Жыл бұрын
In my opinion this error shouldn't even exist. The function type signature indicates it takes in a `u32`, but it really doesn't. It takes in a `Pin`. In most languages you'd blindly take in a u32 and throw an exception when it's out of range (which is conceptually what we have with that `panic!`). That's terrible practice. In any language that has a decent type system, there is no reason not to use total functions everywhere. It was incredibly frustrating to watch this video because the code that was written isn't Rust; at its core, it's a C program with Rust syntax slapped on.
@altairbueno5637
@altairbueno5637 Жыл бұрын
@@emilien.breton all these languages but you choose to speak with the truth lmaoo
@tagged5life
@tagged5life Жыл бұрын
@@emilien.breton I agree, I’d probably pass in a enum variant of Pin.
@paulsimon1494
@paulsimon1494 Жыл бұрын
Read-modify-write operations for set/clear registers are useless. The whole purpose of set/clear registers is to avoid RMW, even datasheet states this: > Separating the set and clear functions removes the need for read-modify-write operations. Also there are 6 GPIO Function Select registers, not just 3. If you really want a proper way of implementing a PAC, see svd2rust, it generates code which is much closer to idiomatic Rust.
@jan.tichavsky
@jan.tichavsky Жыл бұрын
Agree, embedded processors have dedicated instructions and registers so you can toggle or set specific bits in one go, using read modify write slows it down significantly.
@RayBellis
@RayBellis Жыл бұрын
I came here to say this - as you say it's right there in the data sheet shown in the video - you don't need to mask the bits that you're _not_ setting, specifically to avoid a RMW operation.
@newlinjohn
@newlinjohn Ай бұрын
I also came here to say this, I see I’m a year too late though 😂
@carljacobs1287
@carljacobs1287 Жыл бұрын
I've not used this chip, but don't think you need to read-modify-write GPIO_SET0 and GPIO_CLR0. Just set-and-forget - it allows for very fast pin toggling and is inherently thread safe in multi-threaded environments.
@KitsuneAlex
@KitsuneAlex Жыл бұрын
Unsafe blocks are also expressions, you can do let value = unsafe { ... }. Any expression inside of the unsafe block will be hoisted out by the compiler, as in, the type of the expression inside the unsafe block == the expression type of the unsafe block itself. Nice video :)
@zactron1997
@zactron1997 Жыл бұрын
Obviously all personal preference, but I would not use a u32 as the input type for a pin number, and instead use an enum of all the possible valid pins. It's pedantry, but an obvious bug in your current code is I could call set(1000000) to access a completely non-existent pin. You could use an if/match statement to ensure only valid u32's are passed in, but then you're potentially sacrificing performance at runtime which could instead be done at compile time. Otherwise, love the video, this is exactly how I imagine the unsafe block should be used in Rust; creating islands of danger that can be thoroughly scrutinized.
@darkceptor44
@darkceptor44 5 ай бұрын
"bug" this is so funny, i dont use rust but it looks like you're creating problems that don't exist, it falls onto the developer to put a existent pin number and the way i see it would be a constant anyway that can then be used in some kind of assertion test, its not like it will use pin numbers given by the end-user or something.
@OnlyHerculean
@OnlyHerculean Жыл бұрын
These two videos on the Raspberry Pi cleared up so many things for me it's insane, thank you very much and keep on with this high quality content.
@chair547
@chair547 Жыл бұрын
I would go a step further and have pins themselves be raii objects so you can only write to a pin if it's already been set to an output
@edgeeffect
@edgeeffect Жыл бұрын
In the STM32 crates I've seen, they do exactly that one type for an uninitialized pin, one for an input pin, one for each kind of output pin..... "make invalid states unrepresentable".
@raffimolero64
@raffimolero64 Жыл бұрын
I would suggest creating a gpio *module* rather than an empty struct to hold all of your functions and constants if you're not going to store any state in the GPIO struct itself. That way, users may simply `use gpio::set_output;` and do `set_output(21);` directly in their code. You could then also remove the prefixes from all of your consts. you'd just have this: mod gpio { /// function select zero const FSEL0: u32 = // value; // more private constants... pub fn set_output(pin: u32) { // code } // more public functions... } // example thing you can now do use gpio::set_output;
@peternrdstrm
@peternrdstrm Жыл бұрын
I REALLY love Rust content. You inspired me to start low level development myself, and I only use Rust. Rust gang for the win!!
@wChris_
@wChris_ Жыл бұрын
At 6:08 the '~' is the right operation since we want a bitwise not while the '!' is a logical not and since mask is a shifted 3 which is a truthy value it will be turned into a 0 clearing the entire register!
@LowLevelLearning
@LowLevelLearning Жыл бұрын
Crap I totally missed that. Thank you!
@ericedin8362
@ericedin8362 Жыл бұрын
Thanks, I was thinking "Why did Rust make that change from C?"
@JeffHanke
@JeffHanke Жыл бұрын
In rust '!' *is* the bitwise not when used with integers. It's only logical not when used with booleans.
@xphreakyphilx
@xphreakyphilx Жыл бұрын
I do wonder if Rust will ever use ~ as bitwise not as I believe the original reason it wasn't is that in the early days of rust ~ was to box objects.
@wChris_
@wChris_ Жыл бұрын
@@JeffHanke what?? why would rust do this? i guess it isnt C but still..
@amiwatchesyt
@amiwatchesyt Жыл бұрын
Hi, I'm quite new to electronics and I have a doubt. If you are setting how to interpret a pin could you use that function to return a pin struct that holds all the relevant information to put it on and off? That way you can't possibly act on a pin you haven't set previously
@thatluminary
@thatluminary Жыл бұрын
I am fairly new at programming, I understand nothing at your videos (except the beginner tutorial ones about C) but I still enjoy watching all of them. The smallest amount of knowledge I might get is precious to me. Thank you for the great videos and keep them coming :))
@LowLevelLearning
@LowLevelLearning Жыл бұрын
It takes time! You'll get there.
@thatluminary
@thatluminary Жыл бұрын
@@LowLevelLearning Thanks for the encouragement :))
@Maykeye
@Maykeye Жыл бұрын
Some general thoguhts: * If you are going for read-modify(reading comments, it might be not the best approach, don't know), it'd be cleaner to make something like `unsafe fn read_write_volatile(address: *mut u32, f:F) where F:FnOnce(u32)->u32` So for example `set` would become `unsafe {read_write_volatile(GPIO_SET0, |x| {x | (1
@herbertwestiron
@herbertwestiron Жыл бұрын
Thanks for using large font in this video. Really appreciate it.
@LowLevelLearning
@LowLevelLearning Жыл бұрын
No problem!
@sohn7767
@sohn7767 Жыл бұрын
What’s the advantage of using a zero sized type over a module in this case?
@peter9477
@peter9477 Жыл бұрын
In the current case probably none, but note that some chips have multiple GPIO peripherals at different addresses and you'll probably want something like the struct to help model that.
@BambeH
@BambeH Жыл бұрын
Later on, the functions shown in the video could be moved to a trait, which the zero sized struct could implement.
@sohn7767
@sohn7767 Жыл бұрын
@@BambeH this makes sense with what @Peter Hansen said
@saeidakbari6303
@saeidakbari6303 Жыл бұрын
Again, watching a perfect example of quality stuff How about creating some longer and structured courses for rust on embedded?
@LowLevelLearning
@LowLevelLearning Жыл бұрын
In the works!
@Ma1ne2
@Ma1ne2 Жыл бұрын
@@LowLevelLearning I'd love that! Great follow up video, but I am also very happy you made these "mistakes" in the first one! Great way to build up and show what is the idea behind Rust, to abstract these unsafe interactions into a safe(r) interface. Can't wait to grab my little RaspberryPi once I finished moving and follow these videos again hands on :)
@himbary
@himbary Жыл бұрын
@@LowLevelLearning ETA? I am a rust beginner and I want to get into embedded. This would be awesome.
@MrMooin
@MrMooin Жыл бұрын
This is Awesome! Is there a IDE like Eclipse where you can debug the Code and see the Content of Valuables by stepping slowly through the Code? I'm happy that i found your Channel!
@OnlyHerculean
@OnlyHerculean Жыл бұрын
I think implementing the Drop trait for the GPIO struct might make the code even better.
@OnlyHerculean
@OnlyHerculean Жыл бұрын
Haha shit fixing my typo removed the heart from the comment 😂 But whatever now it says correctly struct instead of strict
@markdlp
@markdlp Жыл бұрын
Is it possible to replace the delay with a mills function? just to not stuff the memory with nops.
@alexloktionoff6833
@alexloktionoff6833 Жыл бұрын
Can you make more videos about RPiPico programing in rust? Especially about proper flexible inline assembler with input, output and clobber registers.
@williamdrum9899
@williamdrum9899 Жыл бұрын
Does the compiler inline functions if it can or is every function you write going to require a CALL and RET (I guess this is ARM so really it would be BL and BX LR?)
@begga9682
@begga9682 Жыл бұрын
It's optimized by LLVM which probably has inlining conditions documented somewhere
@d3line
@d3line Жыл бұрын
In my experience rust almost always inlines small functions, especially if they are used only once. This would be controlled generally by the optimization level (O3 for fastest code, more inlines, Oz for smallest code, less inlines) and by #inline[always/never] attribute on a per-function basis.
@IvesvanderFlaas
@IvesvanderFlaas Жыл бұрын
How about concurrency? Should you have lock/mutex/disable interrupt around the read, change, write operations to avoid skipping a bit clear/set? Or will the above layer always run from the same thread?
@chair547
@chair547 Жыл бұрын
So you would have to worry about concurrency if there was any actual multithreading code in this. There is not
@d3line
@d3line Жыл бұрын
This is kernel code, so it is in full control of what runs when. Threads are not a concern until you write the threads into existence!)
@redcrafterlppa303
@redcrafterlppa303 Жыл бұрын
You should replace the two "set" and "clear" functions with one with an additional parameter taking an enum with variants "clear" and "set" instead of copying the code twice.
@tagged5life
@tagged5life Жыл бұрын
You could have two wrapper functions and then call a private function with your enum variant passed in.
@redcrafterlppa303
@redcrafterlppa303 Жыл бұрын
@@tagged5life yes thats possible but I don't really see the point. It's basically like a setter method for an enum field. Why would you make an extra function for each variant? You could also use a bool.
@DegradationDomain_stuff
@DegradationDomain_stuff Ай бұрын
What is the point if you wrapped both read and write into an unsafe block? Will it really become safe if you make operations on it in rust?
@jamespeterson7979
@jamespeterson7979 Жыл бұрын
you could add debug attributes to remove the "not-used" warnings :)
@nicolaslopeza2251
@nicolaslopeza2251 Жыл бұрын
Why not using a HAL crate to use the GPIO enums, etc defined for that specific board (quite new to rust, and to embedded programming in it, it might be a silly question)
@Knirin
@Knirin Жыл бұрын
That is the idiomatic way to do it.
@redumptious2544
@redumptious2544 4 ай бұрын
I'm not him but I feel like those videos are specifically to do stuff "from scratch". He even says at the beginning that he's going to build a PAC in the video which would be the basis for a HAL.
@linkernick5379
@linkernick5379 Жыл бұрын
Any working code is infinitely better than the crashing one 🙄
@paulwratt
@paulwratt Жыл бұрын
nice - cheers for showing _both_ ways
@LowLevelLearning
@LowLevelLearning Жыл бұрын
You bet
@datawolk
@datawolk Жыл бұрын
Good tutorial, next a proper sleep/delay function?
@LowLevelLearning
@LowLevelLearning Жыл бұрын
Good idea!
@kayakMike1000
@kayakMike1000 Жыл бұрын
How dare you make this so much simpler! You must maintain the dark arts of firmware!!!
@jacksonbourne
@jacksonbourne Жыл бұрын
since all blocks return a value, you can just use: let mut val = unsafe { core::ptr::read_volatile(...) }
@QckSGaming
@QckSGaming Жыл бұрын
I'm at a bit of a loss here. What did this refactoring achieve apart from giving the pin addresses a name? It seems like the same unsafe code as it was, with some syntactic sugar, in the end being much more complicated than it has to be. Is it some Rust thing? Does it do magic in the background?
@boggarak-roblox
@boggarak-roblox Жыл бұрын
Based on how I understand it, the refactoring *Low Level Learning* has done here is meant to the reduce the amount of code inside of an unsafe block, because, when you put code in the unsafe block, you are telling the Rust compiler that you know what you are doing and thus it *doesn't need to check for violations of the **_memory management rules_* typically imposed on Rust code. Because Rust's memory management rules that the compiler forces you to follow are there for a reason (and is a selling point for Rust in comparison to other Low-Level programming languages like C or C++), you typically don't want to use unsafe blocks unless if you _really_ have to (like reading or writing volatile data, which is typically a memory violation under the memory management rules but is crucial in Embedded Systems Programming). If there is too much code inside the unsafe block, especially if it is doing more than just simply reading or writing data to a volatile memory location, then there is a chance that there might be problems regarding memory that Rust will simply ignore - *defeating the entire purpose of using Rust of all languages.* Thus, it is important to only use unsafe blocks _just_ for reading or writing volatile data and nothing else. Otherwise, you are creating problems you could easily have avoided. (Not to say that the refactoring could've been improved to make the code more readable or easier to debug). (If I am wrong (_and I might be, since I am new to Rust_) about something I said, let me know so I can correct it.)
@glennmiller394
@glennmiller394 Жыл бұрын
Good stuff. Thanks,
@Little-bird-told-me
@Little-bird-told-me Жыл бұрын
someone who is starting out now and wants to learn a low level language, which one would you recommend _C_ or _Rust_ ?
@LowLevelLearning
@LowLevelLearning Жыл бұрын
Start with C in my opinion. Rust is awesome but you need to know a decent amount about programming for it to make sense. C has far less abstractions
@Little-bird-told-me
@Little-bird-told-me Жыл бұрын
@@LowLevelLearning Cool, thanks mate.
@sledgex9
@sledgex9 Жыл бұрын
Does rust have the equivalent of C++'s "enum class"? I would make enum classes for the pin/register values so that I would enforce type safety in the public API (or, in this case, the GPIO struct's functions)
@finnmonstar
@finnmonstar Жыл бұрын
uhhhh maybe look into rust enums??
@sledgex9
@sledgex9 Жыл бұрын
@@finnmonstar Sure. If I wanted to learn about Rust. However, I only wanted to point out a possible direction based on the language I know, in case there is something equivalent in Rust.
@finnmonstar
@finnmonstar Жыл бұрын
@@sledgex9 I do not know that much C++. Maybe I can help you with C features, but I know nothing about the former. The language is too bloated and complicated for my taste. Anyway, tell me the features "enum classes" have in C++. Maybe I can help you with feature parity across Rust and that language you mentioned.
@sledgex9
@sledgex9 Жыл бұрын
@@finnmonstar In C++ "enum" doesn't create a strong type (for a lack of a better word). Enum values are implicitly converted to/from ints when passed around. You can even accidentally pass the value of the wrong enum type into a function that expects another enum type and the compiler will happily accept it. However "enum class" (or strongly typed enums) don't allow for implicit int conversion nor do they allow you to pass the wrong enum type to the function. The compiler catches those errors. Since Rust is more new I assume that its "enum" will behave more like "enum class". It wouldn't make sense for Rust to adopt the old C/C++ style of enums.
@finnmonstar
@finnmonstar Жыл бұрын
@@sledgex9 You are right about that. In Rust you need to convert everything to the right type, even 32-bit integers to 64-bit ones.
@xZise
@xZise Жыл бұрын
Hi is it even necessary to read the set register, setting the bit and then setting the register? Shouldn't also work if you remove line 68 and only set one bit and write it to the register so that the register "or"-s it itself?
@adrianbool4568
@adrianbool4568 Жыл бұрын
Processors don't allow you to write just one bit. If want to ensure that you're only changing the one but you care about then you need to read in the whole word; make just the specific change you want to that value and then write that "surgically" modified word back.
@animowany111
@animowany111 Жыл бұрын
@@adrianbool4568 The GPIO_SET and GPIO_CLEAR registers are special write-only hardware registers, this is not actually a memory address that would persist. By writing a full u32 value with just one bit set, you are effectively just setting or clearing that one pin without interfering with other pins.
@adrianbool4568
@adrianbool4568 Жыл бұрын
@@animowany111 Oh, OK, thanks for letting me know! Sure makes the code easier & safer like that!
@RayanMADAO
@RayanMADAO 3 ай бұрын
I dont understand why we need to do the bit manipulations instead of directly setting the value
@code-dredd
@code-dredd Жыл бұрын
_Leaves no spaces between math operators_ Me: The code is terrible. It must be rewritten.
@davidjohnston4240
@davidjohnston4240 Жыл бұрын
It magically became less readable as it became more rusty.
@adrianbool4568
@adrianbool4568 Жыл бұрын
I think that's mainly down to the added support for any pin number rather than original's operation only on PIN 21. The arithmetic does get a little messy. I guess that is what encapsulation is for.. :-/
@Rodrigo-lv8if
@Rodrigo-lv8if Жыл бұрын
Could someone tell me if this tutorial works on Windows. If so, could you reply to this comment with a link to your project on github, because I tried the tutorial and it doesn't work for me on Windows?
@user-vy1kz1co9p
@user-vy1kz1co9p Жыл бұрын
the 50000 "nop" s cause me mental pain
@Turalcar
@Turalcar 3 ай бұрын
49999, because 1..50000 it includes neither 0, nor 50000
@Little-bird-told-me
@Little-bird-told-me Жыл бұрын
which window manager are you using. I3 ?
@LowLevelLearning
@LowLevelLearning Жыл бұрын
Yea
@Little-bird-told-me
@Little-bird-told-me Жыл бұрын
@@LowLevelLearning Noice
@abdulrahman1s
@abdulrahman1s Жыл бұрын
This code is unsafe, let's fix it with more unsafe blocks 😁
@LC-hd5dc
@LC-hd5dc Жыл бұрын
more smaller blocks with limited scope > one big one that could be doing anything also after the cleanup it's clearer what the code is doing
@devdev3052
@devdev3052 Жыл бұрын
Was anyone able to compile for rp4 64 bit? I think the target triplet should look like this armv8-none-eabihf However rust says it cannot add a target of armv8-none
@paulsimon1494
@paulsimon1494 Жыл бұрын
Correct target name is aarch64-unknown-none
@devdev3052
@devdev3052 Жыл бұрын
@@paulsimon1494 yup. thanks
@OlivierEble
@OlivierEble 5 күн бұрын
I don't know what is good "very low-level" rust. But Having a "safe" function that is not thread-safe doesn't feel right. (concurrent calls to set or clear are potential race conditions)
@clubby7893
@clubby7893 Жыл бұрын
Might std::hint::spin_loop be a better alternative than a tight loop of nops?
@LowLevelLearning
@LowLevelLearning Жыл бұрын
no_std :(
@clubby7893
@clubby7893 Жыл бұрын
​@@LowLevelLearning Ah of course 😄Maybe the core::arch intrinsics used to implement it for your specific platform? I'm not familiar enough with Arm to tell if it's supported though
@animowany111
@animowany111 Жыл бұрын
@@LowLevelLearning core::hint::spin_loop exists
@oxey_
@oxey_ Жыл бұрын
oh, you're overestimating me by a lot. I will definitely have to
@thirtysixnanoseconds1086
@thirtysixnanoseconds1086 6 ай бұрын
the unsafe is merely refactored out. i really dont get why you wouldnt stick with the tried and tested c
@HIRVIism
@HIRVIism 2 ай бұрын
You concentrate the unsafe code in a few, marked locations. The rest of the program can then enjoy the benefits of rust, and you know where to look if you encounter weird behavior.
@richardorourke4501
@richardorourke4501 Жыл бұрын
Just re-write it in Ada, do it right the from the start.
@edgeeffect
@edgeeffect Жыл бұрын
Rust is Ada for the 21st century. ;)
@guillermomoreira5601
@guillermomoreira5601 Жыл бұрын
Have you tried zig?
@rallokkcaz
@rallokkcaz Жыл бұрын
I have, and I helped write the code from the stream where we work shopped the example code. Zig is fine, but the DX is trash and the documentation is balls. Rust wins over zig for me but I'll still give it a chance in the near future as an exercise in futility hahahah.
@bartpelle3460
@bartpelle3460 Жыл бұрын
zigma balls lmaoo
@davidgomez79
@davidgomez79 Жыл бұрын
Rust is like putting training wheels on a ninja bike. C being the ninja bike. (bait)
@absalomdraconis
@absalomdraconis Жыл бұрын
No, but it is like putting a roll cage on one. Useful, but only an incremental change.
@kayakMike1000
@kayakMike1000 Жыл бұрын
Magic numbers kinda suck too, but that's a mistake in all languages. Also... What's up with that noop? Are there not proper timers? Also ... Screw make. Get Meson and Ninja. Much much better
@indefinitingdefinition
@indefinitingdefinition Жыл бұрын
Very nice explanations about low level rust! What is this desktop environment? I heard a windows sound in one of your videos, is that a WSL? What is this windows manager? Do you have a video explaining your desktop setup? Looks really curious.
@unknownlordd
@unknownlordd Жыл бұрын
now do this to all the other videos my child
@LowLevelLearning
@LowLevelLearning Жыл бұрын
Yes Jesus 🙏
@dries1454
@dries1454 Жыл бұрын
Ironically, you ended up with the same unsafe code you had in the beginning. The only difference is that they are wrapped in small functions so you don't see a big unsafe block in the main function.
@raffimolero64
@raffimolero64 Жыл бұрын
which then makes it easier to debug individually rather than as one whole swathe of danger
@ChungusTheLarge
@ChungusTheLarge Жыл бұрын
Isn't that the definition of abstraction?
@DanielRodriguez-ff5cs
@DanielRodriguez-ff5cs Жыл бұрын
so in rust you must replace an unsafe code with another unsafe code, it's like the language was not meant for embedded systems
@LowLevelLearning
@LowLevelLearning Жыл бұрын
🤔
@finnmonstar
@finnmonstar Жыл бұрын
well atleast the whole logic is not unsafe, and you can find memory bugs easier i think
@DanielRodriguez-ff5cs
@DanielRodriguez-ff5cs Жыл бұрын
@@finnmonstar that's fair enough!
@HansBezemer
@HansBezemer Жыл бұрын
Gee, no bitfields in Rust?
@vladlu6362
@vladlu6362 Жыл бұрын
Couldn't you just have XOR'd the Val with itself to make sure it is 0?
@LowLevelLearning
@LowLevelLearning Жыл бұрын
Sure but then you’re destroying any state that was already there, which would suck if you want to use multiple pins on the same port
@DegradationDomain_stuff
@DegradationDomain_stuff Ай бұрын
RustberryPi when?
@minneelyyyy8923
@minneelyyyy8923 Жыл бұрын
... by rewriting it in C!
@rallokkcaz
@rallokkcaz Жыл бұрын
LLG.
@LowLevelLearning
@LowLevelLearning Жыл бұрын
LLG 5Life
@nevokrien95
@nevokrien95 10 ай бұрын
U wrote this code lol😂
@Dygear
@Dygear Жыл бұрын
Thanks!
@Dygear
@Dygear Жыл бұрын
*Chefs kiss*
@LowLevelLearning
@LowLevelLearning Жыл бұрын
:O Mark THANK YOU AGAIN my guy holy crap. Seriously this is so generous
@Dygear
@Dygear Жыл бұрын
@@LowLevelLearning This directly helps me. I'm working on a Time Clock for one of my customers. I've done it with a Raspberry Pi (In C) with Raspberry Pi OS and an RFID reader. Having to buy RFID keys has been come a pain so I'm going to do it with a PICO and a finger print reader next. At this point I might as well write it in Rust and I'd love to write it from the ground up. Plan is to have the code MIT licensed once I'm done with it as it's not a competitive advantage for me to keep the code a secret.
@Ma_X64
@Ma_X64 Жыл бұрын
Oh! You just need a new language! More sAfE! 🤣
@mychromebook9935
@mychromebook9935 Жыл бұрын
the forth programming language is way easier than Rust for embedded stuff. Rust just seems overly complicated for simple stuff.
@memcpy
@memcpy Жыл бұрын
Amen, have you tried flashforth for embedded ?
@LowLevelLearning
@LowLevelLearning Жыл бұрын
I'll have to give it a try!
@liam.3d265
@liam.3d265 Жыл бұрын
C will live forever
@mychromebook9935
@mychromebook9935 Жыл бұрын
@@memcpy yeah, and mecrisp forth for ARM make it easy to turn off and on gpio pins
@CallousCoder
@CallousCoder Жыл бұрын
It’s been ages that I’ve used it. And it was quite hard to learn for a C/assembly programmer. But when you grasp the concept of “everything goes over the stack” it clicks.
@edgeeffect
@edgeeffect Жыл бұрын
That's wonderful... it takes a "real programmer" to point at their own code and say "this stinks".
@sonuaryan5287
@sonuaryan5287 3 ай бұрын
Syntax of rust is horrible. Why not they just take c grammar and added safety 😂
@cozyGalvinism
@cozyGalvinism Жыл бұрын
You may be able to move the linker stuff into a build.rs so it gets built automatically
@akaikangaroo
@akaikangaroo Жыл бұрын
Watching all these videos I understand that I could never be a good programmer for at least two reasons: 1) I still can't type on my keyboard while watching to the screen; 2) I am absolutely unfamiliar with Linux and never even tried to learn it😑
@der.Schtefan
@der.Schtefan Жыл бұрын
Rust: when you like C, but thought it is too readable.
@LordHog
@LordHog Жыл бұрын
To make this Rust program perfect would be re-writing it in C!
@carljacobs1287
@carljacobs1287 Жыл бұрын
C++. The simple stuff compiles just as small, but then it gets cool!
@piotrek3282
@piotrek3282 Жыл бұрын
still bad tho
@LowLevelLearning
@LowLevelLearning Жыл бұрын
no u ha gottem
@BetaTester704
@BetaTester704 Жыл бұрын
Yeah rust is a no-go for me. Rather not melt my brain
@iyamroshan
@iyamroshan Жыл бұрын
You are so handsome 😘
@metamud8686
@metamud8686 Жыл бұрын
The audio is horribly out of sync with your video / mouth movement.
@virdvird
@virdvird Жыл бұрын
And you just made code with worse performance for embedded. Same as arduino library do UPD. My statement is wrong see godbolt link below
@rallokkcaz
@rallokkcaz Жыл бұрын
Rust's zero size struct semantics are not the same as an abstraction like C/C++ with AVR dude.
@softwarelivre2389
@softwarelivre2389 Жыл бұрын
@@rallokkcaz but now he has to calculate a bunch of masks instead of pasting at the memory location directly. As this code seems to only target the 21 pin, it ends up wasting more CPU cycles (unless the compiler already precalculates those values before the function call, which I doubt it does).
@saadisave
@saadisave Жыл бұрын
@@softwarelivre2389 LLVM can easily inline simple calculations when all inputs are literals. It can even compute the result of a function at compile time and inline the result.
@softwarelivre2389
@softwarelivre2389 Жыл бұрын
@@saadisave yeah, that I know, but as this is not a pure function, and it does memory allocations in its body, I don't know if that will be optimized beforehand or not in this context. If it is, then disregard my comment.
@virdvird
@virdvird Жыл бұрын
@@rallokkcaz It's not about struct. Is `register = match reg ` zero cost abstraction?
@lilhaxxor
@lilhaxxor 6 ай бұрын
This is misleading. You just moved the unsafe code around, but it's still present. "No unsafe code" when you still have unsafe blocks. Call it an interface or encapsulation. What a joke. 😂
@AlFredo-sx2yy
@AlFredo-sx2yy Жыл бұрын
ooooor use C and stop wasting your time!
@anon_y_mousse
@anon_y_mousse Жыл бұрын
Since hundreds of libraries exist already for C it would've been even easier. Instead he's writing it from scratch in a language which treats him like a baby and loses most of its proclaimed advantages at that level.
@AlFredo-sx2yy
@AlFredo-sx2yy Жыл бұрын
@@anon_y_mousse not only that, even if you're in a system where no libraries exist or you cant use any libraries for whatever reason, C gives you no limitations and does not treat you like a baby, so as you said, all advantages that rustaceans claim are lost at that level.
@d3line
@d3line Жыл бұрын
@@AlFredo-sx2yy i'll bite. What advantages are lost at this level? The only difference from C that I can see is needing to actually say "unsafe" when the thing that you're doing is unsafe. Also he doesn't actually use the rust features that would be used by a library author writing a hardware abstraction layer in rust. For example rust can prevent using nonexistent pin numbers or reading output pins/writing input pins at compile time with 0 runtime checks, haven't seen that in C. He also gets a big chunk of libraries if he needs them, and all others if he writes a heap allocator.
@AlFredo-sx2yy
@AlFredo-sx2yy Жыл бұрын
@@d3line the "advantages" provided by rust are lost when you try to go this low level lmao..... i thought you had watched the video? You havent seen C detect nonexistent pin numbers because you havent seen proper C code then. That's something that YOU have to program, the fact that Rust provides this out of the box for certain architectures doesnt mean shit, because good luck finding a build target for all of the architectures you can find lol.... Christ the shit i have to read i swear.
@d3line
@d3line Жыл бұрын
@@AlFredo-sx2yy 1) *which* advantages are lost? You keep exasperatedly saying that some nebulous advantages are lost without defining what, in fact, is lost. 2) I haven't seen stuff like compile time const functions in C because they don't exist in C, yes. C has no way to prevent you just using pin number 12345 except runtime "if" check. Rust can do this at compile time (not shown in video). 3) I'm not talking about using some magic from rust's platform support, you can code it yourself by using rust's type system, and provide your users with un-misuse-able API at no runtime cost. That's a rust advantage, and I don't see how it is in any way lost when programming for embedded devices. Also please chill...
@necauqua
@necauqua Жыл бұрын
Nothing prevents you from doing GPIO::set_output(any random u32), this is not that Rusty still. Make. Invalid. State. Unrepresentable!!! (that is, something wrong _logically_ should not even compile! Or be hard to make it compile such that you'd have to deliberately try to) This was (with exclamation points hah) the greatest statement that Rust introduced me to and I replicate it in everything I write ever since. So your 'safe interface' is actually not very safe What you can do instead is this (or there are a few ways to do that, simplest that came to mind is a enum) #[repr(u32)] // you can do enum_value as u32 where you need it now, totally safe pub enum Pin { PIN21 = 0x1234 // whatever it is //.. and so on from the datasheet } impl Pin { pub fn from_raw(raw: u32) -> Option {..} pub unsafe fn from_raw_unchecked(raw: u32) -> Pin {..} } also unsafe can be an expression so you do `let mut val = unsafe { read_volatile }` - a bit shorter :) also², please install rust-analyzer lsp extension in vscode please, watching you do cargo build in the terminal every time is painful :)
@bartpelle3460
@bartpelle3460 Жыл бұрын
you make yourself sound so incredibly uneducated with the last paragraph that your (entirely valid) former paragraphs are out of the window.
@minimalhostage
@minimalhostage Жыл бұрын
@necauqua You posted some really helpful information. I have a lot of experience in Rust and C, have been lucky enough to work on very difficult problems throughout my career and have led a lot of engineering teams. I say this mainly because its given me exposure to engineers with all types of communication styles. Its obvious to me that you were trying to be helpful by posting a rusty approach and a clean interface that takes the reader into account as much as the runtime. Your approach was solid and I think you wrote it in good faith. Because of that I want to post some constructive criticism for you, also in good faith. 1. It appears you don't know how to use "lol". As it stands, your comments come off as extremely self-important and patronizing. If you remove the "lol", then your statements are just blunt but not necessarily malicious. You seemed to use "lol" to punctuate important points but, unless you're trying to alienate your reader, I recommend you abandon "lol" entirely. You can also try replacing them with exclamation points or clarifying questions. 2. Your classification of embedded is limiting and elitist. Also, you're categorically wrong about "proper embedded". Embedded systems are simply units, within larger electrical systems, that have a processor, memory, and Input/Output capabilities for peripheral devices/components. In this video and the last, he replaced the OS with some kernel code and fed it to a bootloader. All he used on the physical board was... the processor, memory, and I/O pins. Maybe you'd rather he use an STM32 or some other MMU-less MCUs and spend half the video walking us through a circuit diagram. But there are already thousands of videos covering that for people who know where to look and what to look for. Maybe a big reason this video focuses on raspberry pi's is because the boards are versatile and ubiquitous. You can have a desktop machine or just a processor, memory, and I/O. An embedded approach to raspberry pi is much more inviting than the same video with an STM32 or something. Engineering, as a practice and discipline, is about trying to accomplish what you want with what you have. That's it. Everything about "proper" and "the right way" is just pedantic and frankly signals that the person has spent a lot of time in a narrow field, academia, or has little experience outside of their chosen discipline. If an engineer insists on a solution without bringing up trade-offs, alternatives, and cost benefit analysis, then 99% of the time they're just reciting dogma they read/heard or used to solve a problem in the past. Like I said, it is obvious to me that you were trying to be helpful. I don't mean to be rude, only clear. You mentioning "Make. Invalid. State. Unrepresentable!!!!" up front made it obvious to me that you have experience in this field; that you care about attention to detail, correctness, and stability. All of these are great qualities that are really hard to find. If I were hiring an engineer, you'd be a desirable candidate. If I were looking to assign a mentor, you'd be on my list. But your tone is very condescending and abrasive. You know so much that you assume the way you know how to do something is THE way to do it; You forget that much of what you've learned is just another engineer's opinion or ideology. An opinion that another engineer taught THEM and is either outdated or will likely become outdated. I could be wrong, but you sound like a student or a junior engineer that's very passionate about the subject but hasn't really been exposed to a variety of systems and problems. Regardless, here's my parting advice: The way you communicate just negates the value of the information you try to communicate. And people will opt for getting that information elsewhere. The hardest thing about engineering is having to collaborate with other humans and navigating the social nuance that emerges when solving difficult problems. Every tool you've mastered, or want to master, was built by a group of people that worked well together. I believe you have a lot to offer as a teacher or collaborator. It seems like you want to help and share or at the very least contribute. If that matters to you at all, consider asking people more questions and making less assumptions before proposing a solution. Technological systems are built in the context of social systems. Communication skills will serve you well in social systems. I think practicing them will go a long way and you'll even enjoy it as you get better. BUT If you're just a troll and like to feel superior to others or self-important then... carry on and ignore my comment; it was meant for somebody else haha
@bartpelle3460
@bartpelle3460 Жыл бұрын
@@minimalhostage Nothing but respect for the respectful way you phrased that; I don't have that in me but I commend it nonetheless Charles💯
@necauqua
@necauqua Жыл бұрын
@@minimalhostage wow this was very detailed, thanks I mean I'm just used to be kind of rude/patronizing as you've said - because this is the internet and way more commonly you encounter obtuse people than good helpful people like you - and your approach also sounds kind of more 'formal' than I would've liked it to be - this was meant to be kind of a rant and I was annoyed (why? idk really actually, maybe it was elitism indeed, 'oh they learned some rust and sharing their incomplete knowledge') by some things in the video. Also non-native english I will edit some of my comment, everything you said is absolutely valid It is funny how one can hate something in others yet express it themselves to such an extent, thanks for opening my eyes - I really don't like elitism and static unchanging ideologies and when someone thinks some one thing is 'proper', yet I said exactly that huh Still hate that something that runs an OS is called embedded, but looks like my notion of 'embedded' was just invalid :)
@necauqua
@necauqua Жыл бұрын
@@bartpelle3460 while I removed the paragraph as it was really poorly worded anyway indeed - I did think (oh well maybe this was wrong the entire time) that embedded is when you run something on a 'bare metal', w/o an OS - and raspberry pi's being a full-blown arm computers with linux installed were out of this definition - yet every youtuber seems to do 'embedded' with raspis. Although after the explanation from Charles it seems that if you run some code _in place_ of the OS, as it's done in this video - it is indeed embedded - I was under impression of some other youtubers doing like a blinking gpio led with like a python script running on that arm linux on raspi.
zig is the future of programming. here's why.
9:34
Low Level Learning
Рет қаралды 193 М.
rust runs on EVERYTHING (no operating system, just Rust)
18:10
Low Level Learning
Рет қаралды 344 М.
СҰЛТАН СҮЛЕЙМАНДАР | bayGUYS
24:46
bayGUYS
Рет қаралды 809 М.
Заметили?
00:11
Double Bubble
Рет қаралды 3,1 МЛН
rust runs on EVERYTHING (no operating system, just Rust)
14:29
Low Level Learning
Рет қаралды 206 М.
Why i think C++ is better than rust
32:48
ThePrimeTime
Рет қаралды 268 М.
reverse engineering makes you a better programmer (let’s try it out)
13:12
Rust on ESP32 - Getting started
14:09
Floodplain: Streaming, Rust and Embedded
Рет қаралды 18 М.
Harder Drive: Hard drives we didn't want or need
36:47
suckerpinch
Рет қаралды 1,6 МЛН
everything is open source if you can reverse engineer (try it RIGHT NOW!)
13:56
Low Level Learning
Рет қаралды 1,2 МЛН
Rust is not a faster horse
11:37
No Boilerplate
Рет қаралды 317 М.
Blinking an LED: Embedded Rust ecosystem explored
17:14
The Rusty Bits
Рет қаралды 14 М.
The ultimate Rust IDE is here
6:53
Let's Get Rusty
Рет қаралды 125 М.
😱НОУТБУК СОСЕДКИ😱
0:30
OMG DEN
Рет қаралды 3,1 МЛН
Iphone or nokia
0:15
rishton vines😇
Рет қаралды 573 М.
Теперь это его телефон
0:21
Хорошие Новости
Рет қаралды 2 МЛН
Mi primera placa con dios
0:12
Eyal mewing
Рет қаралды 525 М.