mirror of
https://github.com/iceHtwoO/novaOS.git
synced 2026-04-16 20:22:26 +00:00
Basic documentation
This commit is contained in:
10
README.md
10
README.md
@@ -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
|
||||||
|
|||||||
10
src/main.rs
10
src/main.rs
@@ -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() {
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user