Fixing HORRIBLE Embedded Rust So You Don’t Have To

  Переглядів 98,199

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

КОМЕНТАРІ: 267
@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 27 днів тому
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.
@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!!
@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".
@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 :))
@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.
@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
@markdlp
@markdlp Рік тому
Is it possible to replace the delay with a mills function? just to not stuff the memory with nops.
@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
@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!
@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..
@herbertwestiron
@herbertwestiron Рік тому
Thanks for using large font in this video. Really appreciate it.
@LowLevelLearning
@LowLevelLearning Рік тому
No problem!
@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.
@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?
@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 3 місяці тому
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.
@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!)
@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.)
@paulwratt
@paulwratt Рік тому
nice - cheers for showing _both_ ways
@LowLevelLearning
@LowLevelLearning Рік тому
You bet
@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
@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.
@linkernick5379
@linkernick5379 Рік тому
Any working code is infinitely better than the crashing one 🙄
@glennmiller394
@glennmiller394 Рік тому
Good stuff. Thanks,
@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?
@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!
@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.
@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.
@datawolk
@datawolk Рік тому
Good tutorial, next a proper sleep/delay function?
@LowLevelLearning
@LowLevelLearning Рік тому
Good idea!
@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
@jamespeterson7979
@jamespeterson7979 Рік тому
you could add debug attributes to remove the "not-used" warnings :)
@jacksonbourne
@jacksonbourne Рік тому
since all blocks return a value, you can just use: let mut val = unsafe { core::ptr::read_volatile(...) }
@kayakMike1000
@kayakMike1000 Рік тому
How dare you make this so much simpler! You must maintain the dark arts of firmware!!!
@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
@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
@RayanMADAO
@RayanMADAO 2 місяці тому
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.
@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
@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
@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 Місяць тому
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. ;)
@oxey_
@oxey_ Рік тому
oh, you're overestimating me by a lot. I will definitely have to
@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.. :-/
@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
@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.
@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.
@unknownlordd
@unknownlordd Рік тому
now do this to all the other videos my child
@LowLevelLearning
@LowLevelLearning Рік тому
Yes Jesus 🙏
@nevokrien95
@nevokrien95 9 місяців тому
U wrote this code lol😂
@DegradationDomain_stuff
@DegradationDomain_stuff Місяць тому
RustberryPi when?
@HansBezemer
@HansBezemer Рік тому
Gee, no bitfields in Rust?
@minneelyyyy8923
@minneelyyyy8923 Рік тому
... by rewriting it in C!
@rallokkcaz
@rallokkcaz Рік тому
LLG.
@LowLevelLearning
@LowLevelLearning Рік тому
LLG 5Life
@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 11 місяців тому
Isn't that the definition of abstraction?
@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! 🤣
@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
@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!
@sonuaryan5287
@sonuaryan5287 2 місяці тому
Syntax of rust is horrible. Why not they just take c grammar and added safety 😂
@edgeeffect
@edgeeffect Рік тому
That's wonderful... it takes a "real programmer" to point at their own code and say "this stinks".
@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.
@iyamroshan
@iyamroshan Рік тому
You are so handsome 😘
@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
@der.Schtefan
@der.Schtefan Рік тому
Rust: when you like C, but thought it is too readable.
@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😑
@metamud8686
@metamud8686 Рік тому
The audio is horribly out of sync with your video / mouth movement.
@BetaTester704
@BetaTester704 Рік тому
Yeah rust is a no-go for me. Rather not melt my brain
@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 5 місяців тому
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...
@cozyGalvinism
@cozyGalvinism Рік тому
You may be able to move the linker stuff into a build.rs so it gets built automatically
@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.
i changed my mind about zig
9:34
Low Level Learning
Переглядів 139 тис.
rust runs on EVERYTHING (no operating system, just Rust)
18:10
Low Level Learning
Переглядів 334 тис.
Новая технология! РАССЫПНОЙ ПОДШИПНИК
00:35
Voloshyn - ЗУСИЛЛЯ (прем'єра треку 2024)
06:17
VOLOSHYN
Переглядів 916 тис.
Protect The Yacht, Keep It!
15:08
MrBeast
Переглядів 56 млн
VOID Linux: a GEM in wide distro world...
16:06
A1RM4X
Переглядів 70
i cant stop thinking about this exploit
8:40
Low Level Learning
Переглядів 218 тис.
Rust Data Modelling Without Classes
11:25
No Boilerplate
Переглядів 156 тис.
zero-day vulnerability in Palo Alto firewalls exploited in the wild
5:24
Low Level Learning
Переглядів 112 тис.
why do header files even exist?
10:53
Low Level Learning
Переглядів 336 тис.
researchers find unfixable bug in apple computers
8:32
Low Level Learning
Переглядів 677 тис.
Rust is not a faster horse
11:37
No Boilerplate
Переглядів 314 тис.
Abstraction Can Make Your Code Worse
5:13
CodeAesthetic
Переглядів 595 тис.
new linux exploit is absolutely insane
8:29
Low Level Learning
Переглядів 407 тис.
Вы поможете украсть ваш iPhone
0:56
Romancev768
Переглядів 405 тис.
📱 SAMSUNG, ЧТО С ЛИЦОМ? 🤡
0:46
Яблочный Маньяк
Переглядів 640 тис.
APPLE УБИЛА ЕГО - iMac 27 5K
19:34
ЗЕ МАККЕРС
Переглядів 84 тис.
Рекламная уловка Apple 😏
0:59
Яблык
Переглядів 799 тис.
How about that uh?😎 #sneakers #airpods
0:13
Side Sphere
Переглядів 8 млн