mirror of
https://github.com/iceHtwoO/novaOS.git
synced 2026-04-16 20:22:26 +00:00
migrate read and write volatile to a function
This commit is contained in:
@@ -1,10 +1,9 @@
|
||||
use core::{
|
||||
arch::asm,
|
||||
ptr::{read_volatile, write_volatile},
|
||||
sync::atomic::{compiler_fence, Ordering},
|
||||
};
|
||||
|
||||
use crate::peripherals::uart::print;
|
||||
use crate::{mmio_read, mmio_write, peripherals::uart::print};
|
||||
|
||||
const INTERRUPT_BASE: u32 = 0x3F00_B000;
|
||||
const IRQ_PENDING_BASE: u32 = INTERRUPT_BASE + 0x204;
|
||||
@@ -57,7 +56,7 @@ pub fn read_gpio_event_detect_status(id: u32) -> bool {
|
||||
let register = GPEDS_BASE + (id / 32) * 4;
|
||||
let register_offset = id % 32;
|
||||
|
||||
let val = unsafe { read_volatile(register as *const u32) >> register_offset };
|
||||
let val = mmio_read(register) >> register_offset;
|
||||
(val & 0b1) != 0
|
||||
}
|
||||
|
||||
@@ -66,7 +65,7 @@ pub fn reset_gpio_event_detect_status(id: u32) {
|
||||
let register = GPEDS_BASE + (id / 32) * 4;
|
||||
let register_offset = id % 32;
|
||||
|
||||
unsafe { write_volatile(register as *mut u32, 0b1 << register_offset) }
|
||||
mmio_write(register, 0b1 << register_offset);
|
||||
compiler_fence(Ordering::SeqCst);
|
||||
}
|
||||
|
||||
@@ -75,12 +74,10 @@ pub fn enable_irq_source(state: IRQState) {
|
||||
let nr = state as u32;
|
||||
let register = ENABLE_IRQ_BASE + 4 * (nr / 32);
|
||||
let register_offset = nr % 32;
|
||||
unsafe {
|
||||
let current = read_volatile(register as *const u32);
|
||||
let current = mmio_read(register);
|
||||
let mask = 0b1 << register_offset;
|
||||
let new_val = current | mask;
|
||||
write_volatile(register as *mut u32, new_val);
|
||||
}
|
||||
mmio_write(register, new_val);
|
||||
}
|
||||
|
||||
/// Disable IRQ Source
|
||||
@@ -88,12 +85,10 @@ pub fn disable_irq_source(state: IRQState) {
|
||||
let nr = state as u32;
|
||||
let register = DISABLE_IRQ_BASE + 4 * (nr / 32);
|
||||
let register_offset = nr % 32;
|
||||
unsafe {
|
||||
let current = read_volatile(register as *const u32);
|
||||
let current = mmio_read(register);
|
||||
let mask = 0b1 << register_offset;
|
||||
let new_val = current | mask;
|
||||
write_volatile(register as *mut u32, new_val);
|
||||
}
|
||||
mmio_write(register, new_val);
|
||||
}
|
||||
|
||||
/// Read current IRQ Source status
|
||||
@@ -101,7 +96,7 @@ pub fn read_irq_source_status(state: IRQState) -> u32 {
|
||||
let nr = state as u32;
|
||||
let register = ENABLE_IRQ_BASE + 4 * (nr / 32);
|
||||
let register_offset = nr % 32;
|
||||
unsafe { (read_volatile(register as *const u32) >> register_offset) & 0b1 }
|
||||
(mmio_read(register) >> register_offset) & 0b1
|
||||
}
|
||||
|
||||
/// Status if a IRQ Source is enabled
|
||||
@@ -109,7 +104,7 @@ pub fn read_irq_pending(state: IRQState) -> bool {
|
||||
let nr = state as u32;
|
||||
let register = IRQ_PENDING_BASE + 4 * (nr / 32);
|
||||
let register_offset = nr % 32;
|
||||
(unsafe { (read_volatile(register as *const u32) >> register_offset) & 0b1 }) != 0
|
||||
((mmio_read(register) >> register_offset) & 0b1) != 0
|
||||
}
|
||||
|
||||
/// Clears the IRQ DAIF Mask
|
||||
|
||||
11
src/lib.rs
11
src/lib.rs
@@ -1,6 +1,17 @@
|
||||
#![no_std]
|
||||
|
||||
use core::ptr::{read_volatile, write_volatile};
|
||||
|
||||
pub mod peripherals;
|
||||
|
||||
pub mod irq_interrupt;
|
||||
pub mod mailbox;
|
||||
pub mod timer;
|
||||
|
||||
pub fn mmio_read(address: u32) -> u32 {
|
||||
unsafe { read_volatile(address as *const u32) }
|
||||
}
|
||||
|
||||
pub fn mmio_write(address: u32, data: u32) {
|
||||
unsafe { write_volatile(address as *mut u32, data) }
|
||||
}
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
use core::ptr::{read_volatile, write_volatile};
|
||||
use core::result::Result;
|
||||
use core::result::Result::Ok;
|
||||
|
||||
use crate::timer::delay_nops;
|
||||
use crate::{mmio_read, mmio_write};
|
||||
|
||||
const GPFSEL_BASE: u32 = 0x3F20_0000;
|
||||
const GPSET_BASE: u32 = 0x3F20_001C;
|
||||
@@ -30,16 +30,14 @@ pub fn set_gpio_function(gpio: u8, state: GPIOFunction) -> Result<(), &'static s
|
||||
let register_index = gpio / 10;
|
||||
let register_offset = (gpio % 10) * 3;
|
||||
let register_addr = GPFSEL_BASE + (register_index as u32 * 4);
|
||||
unsafe {
|
||||
let current = core::ptr::read_volatile(register_addr as *const u32);
|
||||
let current = mmio_read(register_addr);
|
||||
|
||||
let mask = !(0b111 << register_offset);
|
||||
let cleared = current & mask;
|
||||
|
||||
let new_val = cleared | ((state as u32) << register_offset);
|
||||
|
||||
core::ptr::write_volatile(register_addr as *mut u32, new_val);
|
||||
}
|
||||
mmio_write(register_addr, new_val);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -47,13 +45,11 @@ pub fn set_gpio_function(gpio: u8, state: GPIOFunction) -> Result<(), &'static s
|
||||
///
|
||||
/// Should be used when GPIO function is set to `OUTPUT` via `set_gpio_function`
|
||||
pub fn gpio_high(gpio: u8) -> Result<(), &'static str> {
|
||||
unsafe {
|
||||
let register_index = gpio / 32;
|
||||
let register_offset = gpio % 32;
|
||||
let register_addr = GPSET_BASE + (register_index as u32 * 4);
|
||||
|
||||
core::ptr::write_volatile(register_addr as *mut u32, 1 << register_offset);
|
||||
}
|
||||
mmio_write(register_addr, 1 << register_offset);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -61,26 +57,22 @@ pub fn gpio_high(gpio: u8) -> Result<(), &'static str> {
|
||||
///
|
||||
/// Should be used when GPIO function is set to `OUTPUT` via `set_gpio_function`
|
||||
pub fn gpio_low(gpio: u8) -> Result<(), &'static str> {
|
||||
unsafe {
|
||||
let register_index = gpio / 32;
|
||||
let register_offset = gpio % 32;
|
||||
let register_addr = GPCLR_BASE + (register_index as u32 * 4);
|
||||
|
||||
core::ptr::write_volatile(register_addr as *mut u32, 1 << register_offset);
|
||||
}
|
||||
mmio_write(register_addr, 1 << register_offset);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Read the current GPIO power state
|
||||
pub fn gpio_get_state(gpio: u8) -> u8 {
|
||||
unsafe {
|
||||
let register_index = gpio / 32;
|
||||
let register_offset = gpio % 32;
|
||||
let register_addr = GPLEV_BASE + (register_index as u32 * 4);
|
||||
|
||||
let state = core::ptr::read_volatile(register_addr as *mut u32);
|
||||
let state = mmio_read(register_addr);
|
||||
return ((state >> register_offset) & 0b1) as u8;
|
||||
}
|
||||
}
|
||||
|
||||
/// Pull GPIO up
|
||||
@@ -104,55 +96,50 @@ fn gpio_pull_up_down(gpio: u8, val: u32) {
|
||||
let register_offset = gpio % 32;
|
||||
|
||||
// 1. Write Pull up
|
||||
write_volatile(GPPUD as *mut u32, val);
|
||||
mmio_write(GPPUD, val);
|
||||
|
||||
// 2. Delay 150 cycles
|
||||
delay_nops(150);
|
||||
|
||||
// 3. Write to clock
|
||||
let new_val = 0b1 << register_offset;
|
||||
write_volatile(register_addr as *mut u32, new_val);
|
||||
mmio_write(register_addr, new_val);
|
||||
|
||||
// 4. Delay 150 cycles
|
||||
delay_nops(150);
|
||||
|
||||
// 5. reset GPPUD
|
||||
write_volatile(GPPUD as *mut u32, 0);
|
||||
mmio_write(GPPUD, 0);
|
||||
|
||||
// 6. reset clock
|
||||
write_volatile(register_addr as *mut u32, 0);
|
||||
mmio_write(register_addr, 0);
|
||||
}
|
||||
}
|
||||
|
||||
/// Get the current status if falling edge detection is set
|
||||
pub fn read_falling_edge_detect(gpio: u8) -> bool {
|
||||
unsafe {
|
||||
let register_addr = GPFEN_BASE + 4 * (gpio as u32 / 32);
|
||||
let register_offset = gpio % 32;
|
||||
|
||||
let current = read_volatile(register_addr as *const u32);
|
||||
let current = mmio_read(register_addr);
|
||||
((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);
|
||||
let current = mmio_read(register_addr);
|
||||
((current >> register_offset) & 0b1) != 0
|
||||
}
|
||||
}
|
||||
|
||||
/// Enables falling edge detection
|
||||
pub fn set_falling_edge_detect(gpio: u8, enable: bool) {
|
||||
unsafe {
|
||||
let register_addr = GPFEN_BASE + 4 * (gpio as u32 / 32);
|
||||
let register_offset = gpio % 32;
|
||||
|
||||
let current = read_volatile(register_addr as *const u32);
|
||||
let current = mmio_read(register_addr);
|
||||
let mask = 0b1 << register_offset;
|
||||
let new_val = if enable {
|
||||
current | mask
|
||||
@@ -160,17 +147,15 @@ pub fn set_falling_edge_detect(gpio: u8, enable: bool) {
|
||||
current & !mask
|
||||
};
|
||||
|
||||
write_volatile(register_addr as *mut u32, new_val);
|
||||
}
|
||||
mmio_write(register_addr, new_val);
|
||||
}
|
||||
|
||||
/// Enables rising edge detection
|
||||
pub fn set_rising_edge_detect(gpio: u8, enable: 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);
|
||||
let current = mmio_read(register_addr);
|
||||
|
||||
let mask = 0b1 << register_offset;
|
||||
let new_val = if enable {
|
||||
@@ -179,6 +164,5 @@ pub fn set_rising_edge_detect(gpio: u8, enable: bool) {
|
||||
current & !mask
|
||||
};
|
||||
|
||||
write_volatile(register_addr as *mut u32, new_val);
|
||||
}
|
||||
mmio_write(register_addr, new_val);
|
||||
}
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
use crate::{mmio_read, mmio_write};
|
||||
|
||||
const BAUD: u32 = 115200;
|
||||
const UART_CLK: u32 = 48_000_000;
|
||||
|
||||
@@ -19,13 +21,11 @@ const UART0_LCRH_FEN: u32 = 1 << 4;
|
||||
/// Print `s` over UART
|
||||
pub fn print(s: &str) {
|
||||
for byte in s.bytes() {
|
||||
unsafe {
|
||||
while core::ptr::read_volatile(UART0_FR as *const u32) & UART0_FR_TXFF != 0 {}
|
||||
core::ptr::write_volatile(UART0_DR as *mut u32, byte as u32);
|
||||
}
|
||||
while mmio_read(UART0_FR) & UART0_FR_TXFF != 0 {}
|
||||
mmio_write(UART0_DR, byte as u32);
|
||||
}
|
||||
// wait till uart is not busy anymore
|
||||
unsafe { while (core::ptr::read_volatile(UART0_FR as *const u32) >> 3) & 0b1 != 0 {} }
|
||||
while (mmio_read(UART0_FR) >> 3) & 0b1 != 0 {}
|
||||
}
|
||||
|
||||
/// Initialize UART peripheral
|
||||
@@ -35,27 +35,24 @@ pub fn uart_init() {
|
||||
let ibrd = baud_div_times_64 / 64;
|
||||
let fbrd = baud_div_times_64 % 64;
|
||||
|
||||
unsafe {
|
||||
uart_enable(false);
|
||||
uart_fifo_enable(false);
|
||||
|
||||
core::ptr::write_volatile(UART0_IBRD as *mut u32, ibrd);
|
||||
core::ptr::write_volatile(UART0_FBRD as *mut u32, fbrd);
|
||||
mmio_write(UART0_IBRD, ibrd);
|
||||
mmio_write(UART0_FBRD, fbrd);
|
||||
|
||||
uart_set_lcrh(0b11, true);
|
||||
|
||||
// Enable transmit and uart
|
||||
let mut cr = core::ptr::read_volatile(UART0_CR as *mut u32);
|
||||
let mut cr = mmio_read(UART0_CR);
|
||||
cr |= UART0_CR_UARTEN | UART0_CR_TXE;
|
||||
|
||||
core::ptr::write_volatile(UART0_CR as *mut u32, cr);
|
||||
}
|
||||
mmio_write(UART0_CR, cr);
|
||||
}
|
||||
|
||||
/// Enable UARTEN
|
||||
fn uart_enable(enable: bool) {
|
||||
unsafe {
|
||||
let mut cr = core::ptr::read_volatile(UART0_CR as *mut u32);
|
||||
let mut cr = mmio_read(UART0_CR);
|
||||
|
||||
if enable {
|
||||
cr |= UART0_CR_UARTEN;
|
||||
@@ -63,14 +60,12 @@ fn uart_enable(enable: bool) {
|
||||
cr &= !UART0_CR_UARTEN;
|
||||
}
|
||||
|
||||
core::ptr::write_volatile(UART0_CR as *mut u32, cr);
|
||||
}
|
||||
mmio_write(UART0_CR, cr);
|
||||
}
|
||||
|
||||
/// Enable UART FIFO
|
||||
fn uart_fifo_enable(enable: bool) {
|
||||
unsafe {
|
||||
let mut lcrh = core::ptr::read_volatile(UART0_LCRH as *mut u32);
|
||||
let mut lcrh = mmio_read(UART0_LCRH);
|
||||
|
||||
if enable {
|
||||
lcrh |= UART0_LCRH_FEN;
|
||||
@@ -78,17 +73,14 @@ fn uart_fifo_enable(enable: bool) {
|
||||
lcrh &= !UART0_LCRH_FEN;
|
||||
}
|
||||
|
||||
core::ptr::write_volatile(UART0_LCRH as *mut u32, lcrh);
|
||||
}
|
||||
mmio_write(UART0_LCRH, lcrh);
|
||||
}
|
||||
|
||||
/// Set UART word length and set FIFO status
|
||||
fn uart_set_lcrh(wlen: u32, enable_fifo: bool) {
|
||||
unsafe {
|
||||
let mut value = (wlen & 0b11) << 5;
|
||||
if enable_fifo {
|
||||
value |= UART0_LCRH_FEN;
|
||||
}
|
||||
core::ptr::write_volatile(UART0_LCRH as *mut u32, value);
|
||||
}
|
||||
mmio_write(UART0_LCRH, value);
|
||||
}
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
use crate::mmio_read;
|
||||
|
||||
const TIMER_CLO: u32 = 0x3F00_3004;
|
||||
|
||||
fn read_clo() -> u32 {
|
||||
unsafe { return core::ptr::read_volatile(TIMER_CLO as *const u32) }
|
||||
return mmio_read(TIMER_CLO);
|
||||
}
|
||||
|
||||
/// Sleep for `us` microseconds
|
||||
|
||||
Reference in New Issue
Block a user