100% disagree with your opening statement. The Rasberry pi is now impossible to buy. What should cost $50 is now selling for $190. All of you illegal rom downloading boi's who wanted emulation jacked up the prices. Way to go pirate. Way to ruin it for everyone else.
@@orangehatmusic225 Lockdowns had *nothing* to do with it? Seems a little short-sighted there; chips of all types were affected, including the car my dad wanted to buy. Pirates STEAL ITEMS. Like Assange recently said, he didn't steal anything; he made a copy. Verbs matter. Ever hear "Possession is nine tenths of the law"? When people copy software, the original possessor does not lose their possession. It's more like lighting a candle from another candle. Separately, the esp32 is like $5, a 240x240 color screen is another $5, and PictoBlox is like MIT's Scratch, for the smaller devices. Or the Orange Pi, for $117. So: I 100% disagree with your 100% disagreement. :)
I knew literally nothing about embedded systems and barely anything about Rust 18 minutes ago, and now it feels like it's a very acheivable thing to learn thanks to this demonstration. You're clearly a gifted teacher, fantastic video.
Same here. I have a background in web dev, but allost everything was new to me here. Yet, I‘ve understood pretty much everything and learned a ton. But honestly speaking, I will probably never learn this type of low-level programming. Just seems way too much effort to get something done when there are easier albeit less efficient tools/languages to use. Nice to be able to peek into this world though
@@LowLevelLearning how do I compile for the 64bit version (aarch64) objcopy does not work and i could not find my Problem. (I put AARCH64 in the linker script instead of ARM.eabi)
The great thing about your videos is the pace and "constant" narration. It feels like there isn't a single second in the video where you're not explaining what you're currently doing. That makes it very easy to not lose focus and attention as a viewer
@@LowLevelLearning I agree. You really talk about every detail which is so important. The viewer has no questions, and you make no assumptions about what the viewer knows. I hope to watch more like this in the future :D
It's awesome that he does that, agreed! Just a few videos of this nature and we're downloading helicopter flight manuals between words of dialogue! :) (Matrix reference; as we age, our references get stale, like moldy bread one can use to cure disease or have interesting visions with.)
13:39 I would hope nobody would be mad. Unsafe code is basically the only way this can be done. It's just a fact. There's a reason rust has the unsafe keyword, because it's sometimes needed. :) Also, thanks for the video. It's very enlightening!
Could probably be abstracted into a safe interface (or however it's called). Like a struct (with the PIN number) with methods or even plain functions (one for turning a hard-coded PIN on and the other for turning it off). But in the end the unsafe has be be somewhere.
Safe code is slower code, as there has to be a lot of hash inserts and checks and when you are processing movement, electrical spikes and wave forms, a lot of interrupts that are happening in the higher kilohertz range, such as signal processing, your program isn't gong to be looking at the web directly and should reject anything unexpected.
Thanks for Everything you do LLL, Seriously your videos have invigorated my spirit and inspired me to learn more about computer systems and lower level langs. C and Go are becoming my favorite languages to write my code. I'm gonna try writing some rust today!. Thanks again! Keep up the great work!
@@LowLevelLearning Haha, that's interesting because my takeaway was that low level programming is so different that I know less about it than I thought :). I could probably follow along, but I'm SOL the second something goes wrong.
You can make a `build.rs` file like this ```rust fn main() { println!("cargo:rerun-if-changed=./linker.ld"); } ``` to hint to cargo that a change in that file should also result in a rebuild
The CPU must be running very slow for us to see that LED blink that slowly. 50000 nop operations is nothing for a modern CPU, and we shouldn’t be able to see the LED normally if it ran at the full speed.
@@SqueakyNeb even arduino.. the processor is running at more than 10MHZ ! I guess utilising all the hardware and allocating cores and instructions sets to execute programs must be no easy job ig. Although having even remotely close to raw access to a processor's capabilities and being able to control all the io and all interfaces like a boss.. is fascinating! Might just become true thanks to the people who developed tools to flash sd cards or rpi with such a powerful.. self made os.
I started working on an operating system in rust. I never went that far with it but it works. Can boot both legacy bios mode and modern efi style. Though only in qemu on efi. Don’t have video output properly working on any real efi hardware I have. But with bios boot it works with a text mode console. Boots into long mode and all but no memory protection
Cool, I like it! I don't know any Rust, so this was a good guide on how building Rust for bare metal works. For those who want to go further; If you want to be remotely efficient, you'd use a timer interrupt instead of the nop loops. Then you leave the timer to do it's thing, and whenever the time you've chosen happens, it will call your interrupt routine, which toggles the bit. Then you can do something else in between, instead of wasting cycles in a nop loop. That is, you can do simple round-robin multitasking etc using just interrupt routines and timers. Doesn't matter for just blinking an LED of course, but interrupts are key to do more complex things on bare metal.
I really like how you explain not only how to do things, but how to look for things yourself (e.g. the broadcom datasheet or the rpi firmware). I already have a bit of experience in embedded programming but I'm sure this helps beginners a lot. And more importantly, it makes the whole field feel less magic and scary than just saying "this address controls this LED because I know it".
You should configure the internal timers to trigger an interrupt every millisecond to increment a counter. Then reference that counter to to get more precise timing on when the LEDs turn on and off.
I am absolutely watching your channel from now on.This is the most I have ever learned from a programming video. I've been trying to learn how to be a low level developer for years. Since high school. WOW. It's quick. It's on point. And I can follow it. I love how you just filled in several gaps learning in only a few minutes. I could have stayed in college, and I am not knocking anyone who does, but I have a short attention span. Thanks for this. Don't even remember how I stumbled here.
So glad I found this channel, I have been writing code for a long time and wanted to jump into some low level stuff to improve my wider understanding esp. embedded systems etc. You cover fundamentals so well and easily digestible. Thanks for this!
Hey! Awesome video. As a viewer, I'd like to suggest increasing the font size (zooming the UI) to be clearer to read in small screens. Furthermore, as a concept in video making, it's better to avoid non-flat color elements like your transparent/medium opacity terminal. The video encoder has to sacrifice quality in texts (code) to embrace all details on screen (the diverse details in your wallpaper)
I realized after I rendered and uploaded that the font quality wasn't great :(. I'm transitioning my videos to 4K in the future to avoid this. Thanks for watching!
Actually, if its static then it doesn't detract any quality at all - Tom Scott did a great video about video quality, bit rate, and moving vs stationary details.
@@AbelShields Agreed, translucency is perfectly fine when static, which in this case 99.999% of the time it is; potentially even more 9s when considering the video is 60fps and the proportion of the screen that updates is quite small. The encoder/decoder will *absolutely not choke* on this sort of content. To the video encoder, there is no difference here between a terminal with a translucent background, and a terminal with an opaque, washed out background image. Translucency only matters due to the complexity of attempting to compress something that is changing in extremely unpredictable ways, which translucent objects overlapping and moving on top of a moving background tend to cause. I really like the flair the translucent terminal gives; please don't change it @Low Level Learning ! Though of course, please go to 4K to make the text nice and crisp :)
I just started watching your videos yesterday and in every one you've had full facial hair, the beanie and glasses. Then this one autoplays and I'm like "wait...is this the same guy?" you look so different without all of those "modifiers" haha
This was really interesting. It would be great to see 2 things: 1) A list of references of sources you read to understand each part of this problem including the tools to generate the image that was capable of being loaded into the PI. i.e. a learning path. 2) An approach where you halted the processor putting it into a low power mode until the hardware timer triggered an interrupt allowing you to advance the state of the LED. The spinning for a delay makes this a bad start outside of proving that something could be done.
While not totally unsafe, but definitely more safe, you should wrap only the unsafe parts of the code. Have small subroutines that are entirely unsafe and call them from safe code. Pin-enable, pin-on, and pin-off (maybe the no-op if that requires unsafe as well) should all be their own functions that get called by the main loop which would realistically also be calling some kind of computational code that you definitely want to be checked
I was wondering this myself. There must be a way without using unsafe blocks. I know they’re trying to use rust in the Linux kernel, and kernel device work is almost all about writing bits to raw pointers. Surely rust in the kernel isn’t just all unsafe blocks.
@@Grstearns this is exactly how you're supposed to do unsafe code. Make it as small as possible so that it's easy to read and verify (by humans) that it does only the thing it's supposed to do.
I just found the channel and I loved the video. One thing that it makes me thing was: if is it possible to build a kernel with Rust, then running appa on top of it would be possible too. The possibilities to embed are endless
Me as a web developer trying to learn more low level programming during most of this, "Funny words magic man." But really great video, and has helped me a ton.
Using `global_asm` to change the link section of a function is not supported (since top-level items may be reordered arbitrarily, so it might not apply to what you want it to. The intended way to change the section a function is in is with the link_section attribute, e.g. #[link_section = ".text._start"] pub extern "C" fn _start() { loop {} }
Thanks for such a great introduction! My one question is just about the naming? Is _start convention or arbitrary? Should the entrypoint always be prefixed by an underscore? Is the name main forbidden?
It seems like Rust is really gaining momentum at the moment. I've switched from learning web dev with JavaScript to focusing now solely on Rust, not for any particular field, I just want to really get to grips with Rust. I'm taking a gamble but it feels like a really good investment.
Such high quality content, thank you! Hoping in the future you can find the time to create a whole course on embedded Rust, I'd sign up in a heartbeat.
If you are writing a kernal and it bootstraps in that is the effective OS. You can do that with any compiled language, C,C++ ... How do you think Operating Systems are created? If anyone wants to learn a lot more grab a book called "developing your own 32 bit operating system" You can use the same methods to create a 64 bit system or a lot more.
It's fantastic to have so much knowledge packed into such a short video, BUT this knowledge should not even be necessary! How one even gathers all this info on their own? That would probably take a few more hours to explain :) I think this video clearly demonstrates how abnormal is the current state of software development: * Half the story was about how to *disable* features. * We needed a linker configuration, which was *not* in Rust, but some whatever file format, AND it was just as long as the final program. * It also had to be copy-pasted, because it isn't intuitive enough to remember. * Nothing in the 1st half was related to LED blinking. * At the end of the 2nd half, we had to *download and trust* 3 binary files, ~3 *million* bytes in total, with "magic" file names, to run this ~200 byte (NOT *kilobyte*, just *byte*) example program. * Finally, we had to *disable* a feature, again, because we are not even utilizing the full 64bit capabilities of the hardware.
I'll give it a gold star for devising the most complicated way so far to flash and LED with a microcontroller. One wonders how many lines of code does it take to add two and two. More than the number of electricians to fit a lightbulb I'd say.
1. Very humble request sir, Can you make videos on how to find and learn things, for example how to get the neccessary information required to do xyz task, like the kernel and program you wrote to blink an led using rust, suppose If someone just thought about it and just wants to do a basic thing , how can they achieve it 2. Grapichs and ML/DL processing chip, something like running a stereo vision camera on a edge device which is not a SoC like raspberry pi, performs good, can run basic depth perception, or use an FPGA , a custom ARM chip for product development 🙏🙏🙏🙏🙏🙏 Please
>write a kernel to blink an LED annd there goes all of the respect: either you’re overselling whatever program you’re going to write as a ‘kernel’ or you don’t really know what you’re talking about
Well it is not that bad if the program memory can be loaded from an external SD card. If not then you need some kind of gateway into the built in flash, usually board producer provides these.. custom boards it is on you.
Negative numbers are actually postitive, but with 1. For instance, 8-bit signed integer 2 would be 00000010 in binary, and negative 2 would be bitwise_not(2) + 1 = 11111101 + 1 = 11111110. When they are combined, it is equal to 100000000, and 1 gets truncated because its 8 bit. 2 - 2 = 0.
I don't do rust, but still super useful information. I just got a pico W to do bare metal programming (and learning "properly" ARM assembly at the same time). next step is using a hardware timer instead of a loop?
That's what we did on the university, but I was never good enough to actually get a job in embedded, so I just write Python stuff... Good luck to anyone pursuing this as a career choice. This is however a great hobby and great for home automation, maybe starting your startup...
Or better , can you make a video to use a Raspberry Pi ARM processor as an Arduino board or MCU board, like running small firmware in it, so the sole purpose of that ARM processor becomes to run single / multiple programs in different cores. I know I am asking a little too much 😅
It's an incremental counter, imagine a for loop that does nothing but counts i from 0 to 50000 then exits, basically every timer is built like that, to count time you need a frequency clock to time ratio if you want to count seconds precisely.
Interesting. Not sure about rust though. Might try this first with C/Asm directly. It's interesting, I've been filling out parts of the "stack" from bare metal in bits. I'm a professional software engineer Java+Python+whatever. But for hobby I have done quite a bit on Arduino and other MCUs which have no OS, up to the ESP8266/ESP32 which have a minimal RTOS. To be honest the PI has lost more uses to me than anything else. The MCUs can do all the simple things the PI can in a much simplier and more reliable ways. No OS and readonly ROM code is so robust. At the other end of the spectrum the PI has horrible through bandwidth (not tried the PI4 yet). If you try and run, say, an NFS/Samba/DLNA server on it, it launchs 20 threads, bottlenecks the bus and if the client does anything nasty like skip back and forward in some MP3s, hit Next, Next, Next on a video folder OR the smart TV tried to fetch 100 thumbnails for a folder of movies. Night night Raspberry PI. So for that I use an old Dell desktop as a mini server (70W). The only thing remaining, where the MCUs are just not powerful enough, but don't need a full PC, are security and timelapse cameras using webcams. This is handy as it avoids the need for invasive and insecure "cloud based" security systems.
The lowest I have gone was making a custom PCB with an Arduino Atmel chip, bare, no bootloader and associated passives. Then I programmed it with a BIN file produced with the ARM cross compile stack on my linux machine, using assembler. I was happy this was "Arduino free Atmel MCU" programming. No trace of the Arduino eco system. Other low level activities I found fun, was fixing a bug in a C library for I2C communications with a hardware ADC, which was following a quirk in the protocol that the lib was not prepared for and crashing. That involved raw binary manipulation and literally "bit banging" the I2C protocol manually.
It's just an arbitrary amount. NOP = no operation, which is used to make the program sleep. If it's blinking too fast, make it more. If it's too slow, reduce the number.
I have grasped many info from explanation. Some of them were completely new to me. I'll appreciate if you were able to zoom just to the area where lines of code are written, specially the IDE. Thanks,,
Please add a filter for low freq audio on your videos in the future. Your microphone is able to pick up vibrations on your desk when you hit it or kick it too hard, the bass from that seems boosted. so every time you moderately hit your desk, the bass speakers on my headset shake. You should be able to cut everything below 60HZ without affecting your voice.
really good video thank you! Im really confused, how can a file start at position 0x000..8000? what does that mean? Isnt each position incremented for each byte of data we have, and files start at position 0x0?
The file gets loaded at that address by the RP bootloader. We need to make sure the code we write is aware of that, otherwise offsets may be wrong in the code. Theoretically we could compile the code "position-independent" to get around this, but that's not always easy.
@@LowLevelLearning ahhh its like an offset? so we have other data before that position (0x0 ..0x008000) and that file is loaded after all that content exactly at position 0x00..800
@@jordixboy at address 0x00000000 is the start of the bootloader (it's own vector table). and the 0x8000 offset is to be future proof (so the bootloader can grow/be replaced by another one without exceeding the reserved max size)
I would love to see you setup and use Rust within an STMCube or MPLABX IDE development environment. Also curious if those IDE's could support ICD with Rust. I could use Rust professionally if I knew how to do that.
Great video! I have a suggestion: could you remove the transparency effect on the terminal/IDE because it's a little annoying and sometimes even challenging to read? Other than that, your whole content is excellent containing valuable information!
Don't forget it's not just running 50k NOPs. It's running one NOP, decrementing a counter, doing a compare, and then a branch instruction. It's likely around 10 instructions PER NOP, which adds a ton of time. Good catch though!
I was thinking the same! I guess it's easier that way. Does rust have loop unfolding ? Since this program is so small, having 50k * 2 instructions would fit no problem. But then the delay would be too short. Oh well... Having literally only nop would give the same exact run time, right ? The current nop+for overhead, does that give also a completely fixed amount of time to run ? I guess since it doesn't have to access RAM, it should, right ?
Very interesting, thanks! The Pi is already very beefy to learn embedded programming, at least it makes it very comfortable. Anyway, I'm wondering if they'll even be able to produce the 3 model again, I'm not optimistic. It would be a shame, so much fun things to do with it.