Raspberry Pi Bare Bones: Difference between revisions
Fixed discrepancy between rpi1, 2 & 3, fixed typos, made code more sane and altered info.
[unchecked revision] | [unchecked revision] |
(Fixed discrepancy between rpi1, 2 & 3, fixed typos, made code more sane and altered info.) |
|||
Line 1:
{{Rating|1}}{{Template:Kernel designs}}
This is a tutorial on operating systems development on the [[Raspberry Pi]]. This tutorial is written specifically for the Raspberry Pi Model B Rev 2 because the author has no other hardware to test on. But so far the models are basically identical for the purpose of this tutorial (Rev 1 has 256MB ram, Model A has no ethernet) in every way other than the memory-mapped location of serial I/O. This will serve as an example of how to create a minimal system, but not as an example of how to properly structure your project.
<big><b>WAIT! Have you read [[Getting Started]], [[Beginner Mistakes]], and some of the related [[:Category:OS theory|OS theory]]?</b></big>
Line 88:
=== Freestanding and Hosted Environments ===
If you have done C or C++ programming in user-space, you have used a so-called Hosted Environment. Hosted means that there is a C standard library and other useful runtime features. Alternatively, there is the Freestanding version, which is what we are using here. Freestanding means that there is no C standard library, only what we provide ourselves. However, some header files are actually not part of the C standard library, but rather the compiler. These remain available even in freestanding C source code. In this case we use
=== Writing a kernel in C ===
Line 95:
<source lang="cpp">
#include <stddef.h>
#include <stdint.h>
// Memory-Mapped I/O output
static inline void mmio_write(uint32_t reg, uint32_t data)
{
*(volatile uint32_t
}
// Memory-Mapped I/O input
static inline uint32_t mmio_read(uint32_t reg)
{
return *(volatile uint32_t
}
/
static inline void delay(int32_t count)
{
asm volatile("__delay_%=: subs %[count], %[count], #1; bne __delay_%=\n"
: "=r"(count): [count]"0"(count) : "cc");
}
Line 129 ⟶ 120:
{
// The GPIO registers base address.
GPIO_BASE =
// The offsets for reach register.
Line 140 ⟶ 131:
// The base address for UART.
UART0_BASE =
// The offsets for reach register for the UART.
Line 189 ⟶ 180:
// Divider = 3000000 / (16 * 115200) = 1.627 = ~1.
// Fractional part register = (.627 * 64) + 0.5 = 40.6 = ~40.▼
mmio_write(UART0_IBRD, 1);
▲ // Fractional part register = (.627 * 64) + 0.5 = 40.6 = ~40.
mmio_write(UART0_FBRD, 40);
Line 204 ⟶ 195:
}
void uart_putc(unsigned char
{
// Wait for UART to become ready to transmit.
while ( mmio_read(UART0_FR) & (1 << 5) ) { }
mmio_write(UART0_DR,
}
unsigned char uart_getc()
{
// Wait for UART to have
while ( mmio_read(UART0_FR) & (1 << 4) ) { }
return mmio_read(UART0_DR);
for ( size_t i = 0; i < size; i++ )▼
uart_putc(buffer[i]);▼
}
void uart_puts(const char* str)
{
}
Line 234 ⟶ 220:
void kernel_main(uint32_t r0, uint32_t r1, uint32_t atags)
{
// Declare as unused
(void) r0;
(void) r1;
Line 241 ⟶ 228:
uart_puts("Hello, kernel World!\r\n");
while (
uart_putc(uart_getc());
}
Line 389 ⟶ 376:
<source lang=text>
$YOURINSTALLLOCATION/bin/qemu-system-arm
</source>
|