Raspberry Pi C/C++ Baremetal Programming | Using C to Direct-Register Control Your Raspberry Pi

แชร์
ฝัง
  • เผยแพร่เมื่อ 19 ส.ค. 2021
  • The Raspberry Pi is a fan favorite of makers and embedded developers. In my previous tutorial on Raspberry Pi Baremetal programming, I demonstrated how to use ARM Assembly to perform direct-to-register programming on the RPI 3B+. In this video, I'll show you how to do direct to register programming, but instead of using assembly, well use C to turn an LED on and off via the Raspberry Pi's GPIO Interface.
    Subscribe for more videos like this on the Raspberry Pi!
    🏫 COURSES 🏫
    www.lowlevel.academy/courses/
    Check out my new merch store!: lowlevellearning.myspreadshop...
    Find the code here: github.com/lowlevellearning/r...
    SOCIALS:
    Follow me on Twitter: / lowlevellearni1
    Follow me on Twitch: / lowlevellearning
    Join me on Discord!: / discord

ความคิดเห็น • 75

  • @DavesGarage
    @DavesGarage ปีที่แล้ว +37

    Really appreciate the starting point! You might want to mention how to get the SDK or whatever assembler and linker you're using. I'm about to search for it, but a link would have made it easier!

    • @alexandrohdez3982
      @alexandrohdez3982 ปีที่แล้ว +2

      Hi Dave great to see you here 👏👏👏

  • @ChandlerKluser
    @ChandlerKluser 2 ปีที่แล้ว +36

    Dude that's great!! Could you please tell us more about how these linker files are and how these C compilers work? thanks in advance!

  • @meoDomicio
    @meoDomicio 7 หลายเดือนก่อน

    I love low-level programming, thanks for your videos.

  • @neelabhpaul3024
    @neelabhpaul3024 2 ปีที่แล้ว +2

    great informative video!!

  • @ORIofficialchannel
    @ORIofficialchannel 2 ปีที่แล้ว

    that's something new, thank you!

  • @maksimmuruev423
    @maksimmuruev423 2 ปีที่แล้ว +4

    Is it any timer usage possible instead of empty while loops? Will be also interesting to see. should be more energy efficient.. I suppose

  • @alexroman6246
    @alexroman6246 2 ปีที่แล้ว +9

    the most difficult for me was linker script and assembly regions explanation.
    could u tell me where to find good help to understand how linker scripts work and how arm cpu reads data from linked and compiled file. (assembly start file+C files that contains below in file)

  • @CallousCoder
    @CallousCoder 2 ปีที่แล้ว +32

    It’s much easier on ARM to run bare metal is easier than on Intel. I was about to start a series of making a cooperative multitasking OS. But I got a new project, so no time for now.
    I wasn’t aware about this header file, when I did my GPIO video I had to deep dive into the documentation.

    • @LowLevelLearning
      @LowLevelLearning  2 ปีที่แล้ว +12

      Yeah x86 baremetal programming is much more difficult, and there isn't a ton of learning value there. It's just annoying.
      The header files are nice. Digging through documentation is something you should know HOW to do, but shouldn't have to do often.
      Thanks for watching!

  • @jugnu361
    @jugnu361 2 ปีที่แล้ว +1

    Very Skillful

  • @packa5676
    @packa5676 2 ปีที่แล้ว +13

    Any plans to work in graphics later on in the series? Btw great series!

  • @zapiton
    @zapiton 2 ปีที่แล้ว +1

    I was searching for gold, but found platinum.
    until the end of the video I thought, that u coding for rasbian os😅😅
    this is cool staff

  • @robotboy3525
    @robotboy3525 ปีที่แล้ว

    Hi ,
    I'm assuming this uses the same C/C++ SDK as the RPi Pico right ??

  • @namesurname6583
    @namesurname6583 2 หลายเดือนก่อน

    how did you put the assembled program on the SDcard? have you used the standard image recording utility? You didn't show anything. from which address will the loader need to be read? if you record using the dd utility, how would it be?

  • @TooSlowTube
    @TooSlowTube 2 หลายเดือนก่อน

    Is there a video explaining the process of compiling it all (after installing a tool chain, maybe?) and loading it onto a microSD card? I don't get how to actually make use of this information and get the code running on a Pi.

  • @edgeeffect
    @edgeeffect 2 ปีที่แล้ว

    I'm trying to write assembly in a modular (hopefully) scalable way.... I'd love to see if other people could maintain it. ????????

  • @namesurname6583
    @namesurname6583 2 หลายเดือนก่อน

    how did you put the assembled program on a USB stick? a standard utility for recording an image? You didn't show anything. from which address will the loader need to be read? if you record using the dd utility, how would it be?

  • @jeffcauhape6880
    @jeffcauhape6880 ปีที่แล้ว +1

    Where can we go to learn more about linker files?

  • @isaiahkroeker7062
    @isaiahkroeker7062 ปีที่แล้ว

    Very helpful. Though I was running into an issue. I think I had the code the same as yours, but for some reason the raspberry pi stalls whenever a c function returns (it just no longer does anything). But if I start the start.s file with a line that sets the frame pointer and stack pointer to a spot of memory I set, it works perfect.
    Any clue why this would be?

    • @LowLevelLearning
      @LowLevelLearning  ปีที่แล้ว +1

      Yup! When you call a function in C, the return address is put onto the stack. If you don’t initialize SP, the return address gets lost and you crash the device. Setting SP fixes this.

    • @isaiahkroeker7062
      @isaiahkroeker7062 ปีที่แล้ว

      @@LowLevelLearning Did you do this in your code? That made sense to me but I thought I didn't find a place where you set SP so I assumed there was an initial stack already setup for the pi.

  • @jonasfelipe777
    @jonasfelipe777 ปีที่แล้ว

    Can I apply it to Raspberry Pi Pico with the RP2040 microcontroller?

  • @bryanhutson6741
    @bryanhutson6741 19 วันที่ผ่านมา

    would really love to see this done on a more modern intel/amd x86 cpu.

  • @Gyannea
    @Gyannea 2 ปีที่แล้ว +2

    I am still trying to understand how you can write directly to memory or a hardware register from user space without the OS preventing that. Is it because the program only runs when booted? I asked a similar question in your assembly example. I take it that it is not possible to create a normal executable that can be started by the user.

    • @benjamindreyer9884
      @benjamindreyer9884 ปีที่แล้ว +3

      i think its because there are no OS, its baremetal so there are no kernel i think

  • @benlee6140
    @benlee6140 2 ปีที่แล้ว +3

    Can I write the write() & read() function in Pi OS?
    By that I mean can I access the register using the address mentioned in the datasheet (just like what you do)?
    ex. If I want to change the value of BCM2837_GPFSEL2 by point to the address "0x3F200008

    • @Henry-sv3wv
      @Henry-sv3wv 2 ปีที่แล้ว +4

      no, Linux doesn't want you to have direct access
      Edit: found out you can map physical addresses into your virtual adress space of linux process if it runs as root.
      google: mmap gpio raspberry pi
      you need to translate the bus address into the physical one. if there is no mapping into a physical one then you cant mmap it...

  • @butterfinger4393
    @butterfinger4393 2 ปีที่แล้ว +3

    This is awesome!! Can you make a hello world on hdmi example. Is it even possible using c++?

    • @LowLevelLearning
      @LowLevelLearning  2 ปีที่แล้ว +4

      It's definitely possible to interface with the HDMI controller in baremetal. It's probably a fair amount of code but you can do it.

    • @maxhouseman3129
      @maxhouseman3129 2 ปีที่แล้ว

      The kernel does nothing else. So HDMI output is for sure possible.

    • @petermuller608
      @petermuller608 2 ปีที่แล้ว

      @@maxhouseman3129 are you sure? To my knowledge, the ARM core isn't even connected to the HDMI port on the raspberry pi. It uses a dedicated video chip

    • @maxhouseman3129
      @maxhouseman3129 2 ปีที่แล้ว +2

      @@petermuller608 Yes. I know. Because the ARM processor has not the power to drive a hdmi device.
      But the kernel sends the commands to this chip anyway.

  • @hallkbrdz
    @hallkbrdz 2 ปีที่แล้ว +3

    Q: Instead of a loop for delay, is there a high-resolution counter I can use to turn on a GPIO pin, wait, and then turn it off again after 5µS?

    • @petermuller608
      @petermuller608 2 ปีที่แล้ว

      Your CPU clock is the high resolution counter ;)

    • @Henry-sv3wv
      @Henry-sv3wv 2 ปีที่แล้ว +1

      @@petermuller608 doesn't work if you want to have none blocking wait

    • @maksymiliank5135
      @maksymiliank5135 ปีที่แล้ว

      When I did some ATMega16 programming the chip had two clocks (one of them was 8-bit and the other 16-bit). You could write an interrupt function which would trigger when the counter reached a value set in the proper register. I'm guessing that there should be something like that on the arm chip as well. You need to reference the datasheet.

  • @admink8662
    @admink8662 ปีที่แล้ว

    Nice

  • @dertom1895
    @dertom1895 ปีที่แล้ว +2

    Amazing stuff! 👍But when you wrote the 'sleep'-logic I thought, that won't work (8:36), at least not as a 'sleeper'. It looks like a perfect example for a compiler like gcc(with -O2) to optimize the loop out and replace it just with setting i to the value of 0x800000. Thought you should have used 'volatile' keyword for i-variable or -O0. But no,...too many thoughts 😆, worked as intended... 👍
    Really need to try this at home 🤩

  • @lxw5231
    @lxw5231 2 หลายเดือนก่อน

    Thanks for the simple example. I just make and flashed kernel7.elf to a SD card. put it in RPI3. the LED connected to GPIO21 did not turn on and off.
    compile has some warnnings. and check BCM2837 datasheet, the GPIO_BASE is 0x7E20,0000. not 0x3F20,0000. Is there anyone meet the same issue?

  • @datbuiquang6251
    @datbuiquang6251 ปีที่แล้ว +1

    Why in the linker, start location is . = 0x8000

  • @armchairtin-kicker503
    @armchairtin-kicker503 ปีที่แล้ว

    Why not implement the delay routines as function calls, reducing code duplication, decluttering the mainline with open-code? Other than that, very nice. Thanks.

    • @DonVintaggio
      @DonVintaggio 8 หลายเดือนก่อน

      and on that note, since he's using C, why not use sleep(5) with the inclusion of the necessary headers (i.e. ) ?

  • @StEvUgnIn
    @StEvUgnIn 2 ปีที่แล้ว

    I disagree with the implementation but basically every concept shown on this channel is right

  • @sebimoe
    @sebimoe 2 ปีที่แล้ว

    unsigned int* GPFSEL = (unsigned int*)BCM2837_GPFSEL0;
    GPFSEL[2] |= (1

  • @haider_sh3692
    @haider_sh3692 หลายเดือนก่อน

    can you do the same to stm32f103c8t6?

  • @moustafanofal2919
    @moustafanofal2919 2 ปีที่แล้ว +2

    Am trying this for a couple of days and I saw your video. I wrote to the registers but I faced segmentation fault, do you have any idea?

    • @rylandavis2976
      @rylandavis2976 2 ปีที่แล้ว +3

      How do you know you are having a segmentation fault when the raspberry pi has no os or drivers to alert you that you are having a segmentation fault?

    • @gregoryfenn1462
      @gregoryfenn1462 2 ปีที่แล้ว

      The read function is wrong.

    • @williamdrum9899
      @williamdrum9899 2 ปีที่แล้ว

      If I had to guess it probably happened from either a command with a register in square brackets such as LDR R0, [R1] or moving a value into R13 or R15

  • @steffanjansenvanvuuren3257
    @steffanjansenvanvuuren3257 ปีที่แล้ว +1

    void does not need you to type return;

  • @jeffreymusser8450
    @jeffreymusser8450 2 ปีที่แล้ว

    Why read the register before configuring for output?

    • @largepimping
      @largepimping 2 ปีที่แล้ว

      Because he needs to only flip one bit within the register. I.e., you don't want to change any of the other bits, you only want to change the bit specific to the GPIO pin being used for the LED.

  • @Moronicsmurf
    @Moronicsmurf 2 ปีที่แล้ว +2

    Have you done a Raspberry Pi Rust Baremetal yet? :D

  • @NourMuhammad
    @NourMuhammad หลายเดือนก่อน

    now do this on i7!

  • @otaxhu8021
    @otaxhu8021 3 หลายเดือนก่อน

    wait, assembly isn't a compiled language?

    • @TooSlowTube
      @TooSlowTube 2 หลายเดือนก่อน

      It's not regarded as one, no. Assembly is assembled. There is a one to one correspondence between what you type and the machine code it produces... with the exception of macros, but they're also a literal substitution. Compiled languages use compilers, which are free to produce any code they like, so long as it gets the job done. The actual code can vary quite a bit, even just by using different optimisation setings.

  • @petermuller608
    @petermuller608 2 ปีที่แล้ว +8

    Nice tutorial, however I would have preferred using uint32_t from stdint.h instead of uint, especially when dealing with writing a certain amount of bits

  • @teksolucians6989
    @teksolucians6989 2 ปีที่แล้ว +6

    Wow I didn't even know people still write in C. I thought by now C++ is the preferred main family of C by now

    • @LowLevelLearning
      @LowLevelLearning  2 ปีที่แล้ว +13

      I think C is still the preferred language in embedded spaces. C++ is just as fast, although it tends to bloat code if you're concerned with size constraints.

    • @maxhouseman3129
      @maxhouseman3129 2 ปีที่แล้ว +9

      MCU standard language is C.

    • @EmbeddedSorcery
      @EmbeddedSorcery 2 ปีที่แล้ว

      I write firmware on Cortex-M exclusively with C++. Code size can still be quite small if careful. We use no dynamic memory allocation, and have a real-time kernel written in C++.

    • @Henry-sv3wv
      @Henry-sv3wv 2 ปีที่แล้ว

      libopencm3 ... is a pure C lib

    • @windowsxseven
      @windowsxseven 2 ปีที่แล้ว +4

      C++ gives me a gag reflex every time I see it

  • @aginghacker5602
    @aginghacker5602 2 ปีที่แล้ว +1

    ..sudo ping -f -s 60000 {russian domain} 🤔👍🖖

  • @anwar6971
    @anwar6971 2 ปีที่แล้ว

    You are saying Assembly is hard, but write in C. But you are still writing in Assembly.

  • @KarstenGongoll
    @KarstenGongoll 2 ปีที่แล้ว +3

    warning: passing argument 1 of ‘read32’ makes pointer from integer without a cast [-Wint-conversion]
    3 | #define BCM2835_GPFSEL2 0x0008
    | ^~~~~~
    | |
    | int
    I cant figure out why this is happening can someone pleas help me (I'm new to C...)

    • @ShootingUtah
      @ShootingUtah 2 ปีที่แล้ว +1

      It's hard to tell not seeing all the code but it seems like you're trying to give a function an integer when it wants a pointer. Or vice versa. So if you're currently passing it an int just use &myInt to pass the address of the int, if that doesn't work make a new pointer that points to your integer and pass read32 that pointer. It's probably not as big of a problem as it seems and you just need to figure out exactly what you need to give to read32 and cast your integer into the correct format. Hopefully this helps, I'm no expert but know a bit about this stuff

    • @DFPercush
      @DFPercush 2 ปีที่แล้ว +1

      Easiest way is probably change the parameters of read32 to take an integer instead of a void*. It's being explicitly cast to a pointer inside read32 anyway.
      But the way I would do it, is change the way those addresses are defined in the header:
      #define GPIO_BASE *(volatile uint32_t*)0x3F200000
      That way you can just say
      GPIO_BASE |= 0x40;
      and treat it like a variable. Just make sure you use the right integer type for the size of the register. Some are arrays, so probably uint8_t or unsigned char.

  • @Indi_DevJames
    @Indi_DevJames ปีที่แล้ว

    what did i just watch