6 ms·
Bare Metal Programming on Raspberry Pi 3
- neverartful 6y agoThe project creator makes the following statements regarding 64-bit capabilities: "Second, it's a 64 bit machine. I gave up programming for 32 bit long long time ago. The 64 bit is so much more interesting, as it's address space is increadibly huge, bigger than the storage capacity which allows us to use some interesting new solutions." I find it odd to make this argument in the context of Raspberry Pi 3 since it only has 1GB RAM onboard. This is only 1/4 of the total space that can addressed by 32-bit addresses.
- jandrese 6y agoProbably more thinking about mapping large files to virtual address spaces and treating them like memory. Try to map a 50GB file into memory on a 32 bit system and you run into complications that you don't have on a 64 bit system.
- beached_whale 6y agoAnd the system that allows that, is the system that allows for paging of unused memory in/out. Once you have virtual memory, you can do some really interesting things. But 32bit of VM is hugely constrained for a lot of things. Then again, having 2x the size of a pointer is a cost that must be accounted for too.
- IshKebab 6y agoIt's about the address space size, not the available memory. For example you can't really have large stacks with 32-bit because if you spin up a few thousand threads you run out of address space, even if you don't run out of physical memory. Not a problem on 64 bit.
- LeifCarrotson 6y agoPhysical RAM is completely different from the address space. For a simple example, the control register for the UART serial port peripheral allows you to 'flip an off switch' by writing a 0 to the whole register, or to turn the UART transmit and receive functions by writing a one to the ninth and tenth bits, and to turn on the FIFO buffer by writing a 1 to the first bits. In this code, that control register has an address defined: #define UART0_CR ((volatile unsigned int*)(0x3F000000+0x00201030)) And the code can interact with the peripheral as described by writing `UART0_CR = 0;` or `UART0_CR = 0x301;`. There is no RAM storage at 4,236,263,616 bytes from the start of memory, but this peripheral exists at and handles writes to that address space. Take a look at https://www.raspberrypi.org/app/uploads/2012/02/BCM2835-ARM-Peripherals.pdf https://www.raspberrypi.org/app/uploads/2012/02/BCM2835-ARM-..., page 5. It's part of the address space, but not part of RAM. Relatedly, one useful feature of some ARM processors is the bitwise section of the address space. You want to set the FIFO bit above, but you don't know if the Tx, Rx, or both is on? You need to do the equivalent of: temp = UART0_CR; // Either 0x100, 0x200 0x300, or 0x000 // UART0_CR = 0x001; <- Won't work, you've deleted the Tx and Rx temp = temp | 0x001; // Bitwise OR sets last bit only UART0_CR = temp; which takes 3 cycles and a scratch register. Instead, on at least some Cortex M microcontrollers, there's a copy of UART0_CR (and all the other peripheral registers) expanded in a part of the address space where each word is just one bit of the nominal register, so you can write in a single cycle without a scratch register.
- neverartful 6y agoCool! Thanks for the detailed explanation and example.
- duskwuff 6y agoRe. bit-banding (the "expanded" form of a register) -- I don't think that's available outside Cortex-M3/M4. It isn't even available on Cortex-M7, as it interacts poorly with caching.
- MrBuddyCasino 6y ago> Rust is a much higher level language than preferable for bare metal, something like with C++. But if you provide the required runtime libraries, you can do it. What does he mean by this? Rust has no-std mode, you can run it on an ARM M0 if you so desire.
- Yeroc 6y agoNot sure exactly what he means by that but he does link to another effort that implements everything using Rust: https://github.com/rust-embedded/rust-raspberrypi-OS-tutorials https://github.com/rust-embedded/rust-raspberrypi-OS-tutoria...
- 95014_refugee 6y agoSome people have romantic notions about how bare-metal programming should be difficult, or done in some traditional, artisanal fashion. Most of these people have never built a modern bare-metal product; they're either stuck in the 90s, or they're dilettantes.
- sigjuice 6y agoWhat would be some good examples of modern bare-metal products?
- Sophistifunk 6y agoFrankly I'd like examples of actually-documented bare metal that you can actually buy.
- anitil 6y agoI worked on some echosounders a few years ago that were bare metal, and before that some power management equipment. Though if I was doing it again I'd probably have a bare-metal chip running the timing critical, and throw a cheap arm core on there running linux just to make life easier. And I'm pretty sure I could probably do away with the bare-metal and just pin some userspace code to a core and it'd work just as well. Edit: *'days' -> 'years'
- conductor 6y agoThank you. UART using polling[0] instead of interrupts, i.e. sending a character and waiting in a busy loop until it gets sent, isn't it quite wasteful? [0] https://github.com/bztsrc/raspi3-tutorial/blob/master/03_uart1/uart.c https://github.com/bztsrc/raspi3-tutorial/blob/master/03_uar...
- monocasa 6y agoDepends on your goal. A lot of the time you want your printfs to be blocking on embedded systems, even if literally the rest of the system is asynchronous so that you don't miss the interesting prints right before the crash because they were queued and not sent yet.
- ppf 6y agoIt's not really bare-metal, given that a ThreadX OS controls booting of the raspberry pi and continues to run afterwards https://ownyourbits.com/2019/02/02/whats-wrong-with-the-raspberry-pi/ https://ownyourbits.com/2019/02/02/whats-wrong-with-the-rasp... Side note: Microsoft bought ThreadX in 2019.
- justinclift 6y agoInterestingly, it seems to have been renamed to "Azure RTOS ThreadX". The source is on GitHub: https://github.com/azure-rtos/threadx https://github.com/azure-rtos/threadx
- oytis 6y agoOh, turns out I can't write bare metal software in C++, I should stop doing this probably.