Basic documentation

This commit is contained in:
2025-06-08 15:49:58 +02:00
parent c78d834742
commit 5f85a40f13
3 changed files with 47 additions and 17 deletions

View File

@@ -3,3 +3,13 @@
NovaOS is a expository project where I build a kernel from scratch for a Raspberry PI 3 B+. NovaOS is a expository project where I build a kernel from scratch for a Raspberry PI 3 B+.
[Technical write-up](https://blog.leafnova.net/projects/pi3_kernel/) [Technical write-up](https://blog.leafnova.net/projects/pi3_kernel/)
## Features
- Delay and sleep ✓
- UART ✓
- GPIOs ✓
- GPIO Interrupts ✓
- Frame Buffer
- MMU
- Basic Terminal over UART

View File

@@ -12,7 +12,7 @@ use nova::{
peripherals::{ peripherals::{
gpio::{ gpio::{
gpio_get_state, gpio_high, gpio_low, gpio_pull_up, set_falling_edge_detect, gpio_get_state, gpio_high, gpio_low, gpio_pull_up, set_falling_edge_detect,
set_gpio_state, GPIOState, set_gpio_function, GPIOFunction,
}, },
uart::{print, uart_init}, uart::{print, uart_init},
}, },
@@ -49,7 +49,7 @@ pub extern "C" fn main() -> ! {
enable_uart(); enable_uart();
// Set ACT Led to Outout // Set ACT Led to Outout
let _ = set_gpio_state(21, GPIOState::Output); let _ = set_gpio_function(21, GPIOFunction::Output);
print_current_el_str(); print_current_el_str();
@@ -72,7 +72,7 @@ pub extern "C" fn kernel_main() -> ! {
// Set GPIO 26 to Input // Set GPIO 26 to Input
enable_irq_source(nova::irq_interrupt::IRQState::GpioInt0); //26 is on the first GPIO bank enable_irq_source(nova::irq_interrupt::IRQState::GpioInt0); //26 is on the first GPIO bank
let _ = set_gpio_state(26, GPIOState::Input); let _ = set_gpio_function(26, GPIOFunction::Input);
gpio_pull_up(26); gpio_pull_up(26);
set_falling_edge_detect(26, true); set_falling_edge_detect(26, true);
@@ -112,8 +112,8 @@ pub fn get_current_el() -> u64 {
fn enable_uart() { fn enable_uart() {
uart_init(); uart_init();
// Set GPIO Pins to UART // Set GPIO Pins to UART
let _ = set_gpio_state(14, GPIOState::Alternative0); let _ = set_gpio_function(14, GPIOFunction::Alternative0);
let _ = set_gpio_state(15, GPIOState::Alternative0); let _ = set_gpio_function(15, GPIOFunction::Alternative0);
} }
fn print_current_el_str() { fn print_current_el_str() {

View File

@@ -1,6 +1,5 @@
use core::ptr::{read_volatile, write_volatile}; use core::ptr::{read_volatile, write_volatile};
use core::result::Result; use core::result::Result;
use core::result::Result::Err;
use core::result::Result::Ok; use core::result::Result::Ok;
use crate::timer::delay_nops; use crate::timer::delay_nops;
@@ -15,7 +14,7 @@ const GPREN_BASE: u32 = 0x3F20_004C;
const GPFEN_BASE: u32 = 0x3F20_0058; const GPFEN_BASE: u32 = 0x3F20_0058;
#[repr(u32)] #[repr(u32)]
pub enum GPIOState { pub enum GPIOFunction {
Input = 0b000, Input = 0b000,
Output = 0b001, Output = 0b001,
Alternative0 = 0b100, Alternative0 = 0b100,
@@ -26,11 +25,8 @@ pub enum GPIOState {
Alternative5 = 0b010, Alternative5 = 0b010,
} }
pub fn set_gpio_state(gpio: u8, state: GPIOState) -> Result<(), &'static str> { /// Set the function of the GPIO pin
if gpio > 53 { pub fn set_gpio_function(gpio: u8, state: GPIOFunction) -> Result<(), &'static str> {
return Err("GPIO out of range");
}
let register_index = gpio / 10; let register_index = gpio / 10;
let register_offset = (gpio % 10) * 3; let register_offset = (gpio % 10) * 3;
let register_addr = GPFSEL_BASE + (register_index as u32 * 4); let register_addr = GPFSEL_BASE + (register_index as u32 * 4);
@@ -47,6 +43,9 @@ pub fn set_gpio_state(gpio: u8, state: GPIOState) -> Result<(), &'static str> {
Ok(()) Ok(())
} }
/// Set the GPIO to high
///
/// Should be used when GPIO function is set to `OUTPUT` via `set_gpio_function`
pub fn gpio_high(gpio: u8) -> Result<(), &'static str> { pub fn gpio_high(gpio: u8) -> Result<(), &'static str> {
unsafe { unsafe {
let register_index = gpio / 32; let register_index = gpio / 32;
@@ -58,6 +57,9 @@ pub fn gpio_high(gpio: u8) -> Result<(), &'static str> {
Ok(()) Ok(())
} }
/// Set the GPIO to low
///
/// Should be used when GPIO function is set to `OUTPUT` via `set_gpio_function`
pub fn gpio_low(gpio: u8) -> Result<(), &'static str> { pub fn gpio_low(gpio: u8) -> Result<(), &'static str> {
unsafe { unsafe {
let register_index = gpio / 32; let register_index = gpio / 32;
@@ -69,6 +71,7 @@ pub fn gpio_low(gpio: u8) -> Result<(), &'static str> {
Ok(()) Ok(())
} }
/// Read the current GPIO power state
pub fn gpio_get_state(gpio: u8) -> u8 { pub fn gpio_get_state(gpio: u8) -> u8 {
unsafe { unsafe {
let register_index = gpio / 32; let register_index = gpio / 32;
@@ -80,10 +83,16 @@ pub fn gpio_get_state(gpio: u8) -> u8 {
} }
} }
/// Pull GPIO up
///
/// Should be used when GPIO function is set to `INPUT` via `set_gpio_function`
pub fn gpio_pull_up(gpio: u8) { pub fn gpio_pull_up(gpio: u8) {
gpio_pull_up_down(gpio, 0b10); gpio_pull_up_down(gpio, 0b10);
} }
/// Pull GPIO down
///
/// Should be used when GPIO function is set to `INPUT` via `set_gpio_function`
pub fn gpio_pull_down(gpio: u8) { pub fn gpio_pull_down(gpio: u8) {
gpio_pull_up_down(gpio, 0b01); gpio_pull_up_down(gpio, 0b01);
} }
@@ -115,20 +124,31 @@ fn gpio_pull_up_down(gpio: u8, val: u32) {
} }
} }
pub fn read_falling_edge_detect(gpio: u8) -> u32 { /// Get the current status if falling edge detection is set
pub fn read_falling_edge_detect(gpio: u8) -> bool {
unsafe { unsafe {
// Determine GPLEN Register
let register_addr = GPFEN_BASE + 4 * (gpio as u32 / 32); let register_addr = GPFEN_BASE + 4 * (gpio as u32 / 32);
let register_offset = gpio % 32; let register_offset = gpio % 32;
let current = read_volatile(register_addr as *const u32); let current = read_volatile(register_addr as *const u32);
return (current >> register_offset) & 0b1; ((current >> register_offset) & 0b1) != 0
} }
} }
/// Get the current status if falling edge detection is set
pub fn read_rising_edge_detect(gpio: u8) -> bool {
unsafe {
let register_addr = GPREN_BASE + 4 * (gpio as u32 / 32);
let register_offset = gpio % 32;
let current = read_volatile(register_addr as *const u32);
((current >> register_offset) & 0b1) != 0
}
}
/// Enables falling edge detection
pub fn set_falling_edge_detect(gpio: u8, enable: bool) { pub fn set_falling_edge_detect(gpio: u8, enable: bool) {
unsafe { unsafe {
// Determine GPLEN Register
let register_addr = GPFEN_BASE + 4 * (gpio as u32 / 32); let register_addr = GPFEN_BASE + 4 * (gpio as u32 / 32);
let register_offset = gpio % 32; let register_offset = gpio % 32;
@@ -144,9 +164,9 @@ pub fn set_falling_edge_detect(gpio: u8, enable: bool) {
} }
} }
/// Enables rising edge detection
pub fn set_rising_edge_detect(gpio: u8, enable: bool) { pub fn set_rising_edge_detect(gpio: u8, enable: bool) {
unsafe { unsafe {
// Determine GPHEN Register
let register_addr = GPREN_BASE + 4 * (gpio as u32 / 32); let register_addr = GPREN_BASE + 4 * (gpio as u32 / 32);
let register_offset = gpio % 32; let register_offset = gpio % 32;