mirror of
https://github.com/iceHtwoO/novaOS.git
synced 2026-04-16 20:22:26 +00:00
Refactor
This commit is contained in:
@@ -1,34 +0,0 @@
|
||||
use core::ptr::{read_volatile, write_volatile};
|
||||
|
||||
use crate::uart::print;
|
||||
|
||||
const INTERRUPT_BASE: u32 = 0x3F00_B000;
|
||||
const ENABLE_IRQ_BASE: u32 = INTERRUPT_BASE + 0x210;
|
||||
const DISABLE_IRQ_BASE: u32 = INTERRUPT_BASE + 0x21C;
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn irq_handler() {
|
||||
print("Interrupt\r\n");
|
||||
}
|
||||
|
||||
pub fn enable_iqr_source(nr: u32) {
|
||||
let register = ENABLE_IRQ_BASE + 4 * (nr / 32);
|
||||
let register_offset = nr % 32;
|
||||
unsafe {
|
||||
let current = read_volatile(register as *const u32);
|
||||
let mask = 0b1 << register_offset;
|
||||
let new_val = current | mask;
|
||||
write_volatile(register as *mut u32, new_val);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn disable_iqr_source(nr: u32) {
|
||||
let register = DISABLE_IRQ_BASE + 4 * (nr / 32);
|
||||
let register_offset = nr % 32;
|
||||
unsafe {
|
||||
let current = read_volatile(register as *const u32);
|
||||
let mask = 0b1 << register_offset;
|
||||
let new_val = current | mask;
|
||||
write_volatile(register as *mut u32, new_val);
|
||||
}
|
||||
}
|
||||
127
src/irq_interrupt.rs
Normal file
127
src/irq_interrupt.rs
Normal file
@@ -0,0 +1,127 @@
|
||||
use core::{
|
||||
arch::asm,
|
||||
ptr::{read_volatile, write_volatile},
|
||||
sync::atomic::{compiler_fence, Ordering},
|
||||
};
|
||||
|
||||
use crate::peripherals::uart::print;
|
||||
|
||||
const INTERRUPT_BASE: u32 = 0x3F00_B000;
|
||||
const IRQ_PENDING_BASE: u32 = INTERRUPT_BASE + 0x204;
|
||||
const ENABLE_IRQ_BASE: u32 = INTERRUPT_BASE + 0x210;
|
||||
const DISABLE_IRQ_BASE: u32 = INTERRUPT_BASE + 0x21C;
|
||||
|
||||
// GPIO
|
||||
const GPEDS_BASE: u32 = 0x3F20_0040;
|
||||
|
||||
#[repr(u32)]
|
||||
pub enum IRQState {
|
||||
AuxInt = 29,
|
||||
I2cSpiSlvInt = 44,
|
||||
Pwa0 = 45,
|
||||
Pwa1 = 46,
|
||||
Smi = 48,
|
||||
GpioInt0 = 49,
|
||||
GpioInt1 = 50,
|
||||
GpioInt2 = 51,
|
||||
GpioInt3 = 52,
|
||||
I2cInt = 53,
|
||||
SpiInt = 54,
|
||||
PcmInt = 55,
|
||||
UartInt = 57,
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
unsafe extern "C" fn irq_handler() {
|
||||
handle_gpio_interrupt();
|
||||
}
|
||||
|
||||
fn handle_gpio_interrupt() {
|
||||
for i in 0..=53u32 {
|
||||
let val = read_gpio_event_detect_status(i);
|
||||
|
||||
if val {
|
||||
match i {
|
||||
26 => print("Button Pressed"),
|
||||
_ => {}
|
||||
}
|
||||
// Reset GPIO Interrupt handler by writing a 1
|
||||
reset_gpio_event_detect_status(i);
|
||||
}
|
||||
}
|
||||
enable_irq();
|
||||
}
|
||||
|
||||
/// Get current interrupt status of a GPIO pin
|
||||
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 };
|
||||
(val & 0b1) != 0
|
||||
}
|
||||
|
||||
/// Resets current interrupt status of a GPIO pin
|
||||
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) }
|
||||
compiler_fence(Ordering::SeqCst);
|
||||
}
|
||||
|
||||
/// Enables IRQ Source
|
||||
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 mask = 0b1 << register_offset;
|
||||
let new_val = current | mask;
|
||||
write_volatile(register as *mut u32, new_val);
|
||||
}
|
||||
}
|
||||
|
||||
/// Disable IRQ Source
|
||||
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 mask = 0b1 << register_offset;
|
||||
let new_val = current | mask;
|
||||
write_volatile(register as *mut u32, new_val);
|
||||
}
|
||||
}
|
||||
|
||||
/// Read current IRQ Source status
|
||||
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 }
|
||||
}
|
||||
|
||||
/// Status if a IRQ Source is enabled
|
||||
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
|
||||
}
|
||||
|
||||
/// Clears the IRQ DAIF Mask
|
||||
///
|
||||
/// Enables IRQ interrupts
|
||||
pub fn enable_irq() {
|
||||
unsafe { asm!("msr DAIFClr, #0x2") }
|
||||
}
|
||||
|
||||
/// Clears the IRQ DAIF Mask
|
||||
///
|
||||
/// Disable IRQ interrupts
|
||||
pub fn disable_irq() {
|
||||
unsafe { asm!("msr DAIFSet, #0x2") }
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
#![no_std]
|
||||
|
||||
pub mod gpio;
|
||||
pub mod interrupt;
|
||||
pub mod peripherals;
|
||||
|
||||
pub mod irq_interrupt;
|
||||
pub mod timer;
|
||||
pub mod uart;
|
||||
|
||||
42
src/main.rs
42
src/main.rs
@@ -8,13 +8,15 @@ use core::{
|
||||
};
|
||||
|
||||
use nova::{
|
||||
irq_interrupt::enable_irq_source,
|
||||
peripherals::{
|
||||
gpio::{
|
||||
gpio_enable_low_detect, gpio_get_state, gpio_high, gpio_low, gpio_pull_up, set_gpio_state,
|
||||
GPIOState,
|
||||
gpio_get_state, gpio_high, gpio_low, gpio_pull_up, set_falling_edge_detect,
|
||||
set_gpio_state, GPIOState,
|
||||
},
|
||||
interrupt::enable_iqr_source,
|
||||
timer::{delay_nops, sleep},
|
||||
uart::{print, uart_init},
|
||||
},
|
||||
timer::{delay_nops, sleep_ms, sleep_us},
|
||||
};
|
||||
|
||||
global_asm!(include_str!("vector.S"));
|
||||
@@ -44,14 +46,11 @@ pub unsafe extern "C" fn _start() {
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn main() -> ! {
|
||||
uart_init();
|
||||
enable_uart();
|
||||
|
||||
// Set ACT Led to Outout
|
||||
let _ = set_gpio_state(21, GPIOState::Output);
|
||||
|
||||
// Set GPIO Pins to UART
|
||||
let _ = set_gpio_state(14, GPIOState::Alternative0);
|
||||
let _ = set_gpio_state(15, GPIOState::Alternative0);
|
||||
|
||||
print_current_el_str();
|
||||
|
||||
// Delay so clock speed can stabilize
|
||||
@@ -69,26 +68,26 @@ pub extern "C" fn main() -> ! {
|
||||
pub extern "C" fn kernel_main() -> ! {
|
||||
print_current_el_str();
|
||||
|
||||
sleep(500_000);
|
||||
sleep_us(500_000);
|
||||
|
||||
// Set GPIO 21 to Input
|
||||
enable_iqr_source(49); //21 is on the first GPIO bank
|
||||
let _ = set_gpio_state(21, GPIOState::Input);
|
||||
gpio_pull_up(21);
|
||||
gpio_enable_low_detect(21, true);
|
||||
// Set GPIO 26 to Input
|
||||
enable_irq_source(nova::irq_interrupt::IRQState::GpioInt0); //26 is on the first GPIO bank
|
||||
let _ = set_gpio_state(26, GPIOState::Input);
|
||||
gpio_pull_up(26);
|
||||
set_falling_edge_detect(26, true);
|
||||
|
||||
loop {
|
||||
let _ = gpio_high(29);
|
||||
|
||||
sleep(500_000); // 0.5s
|
||||
sleep_ms(500); // 0.5s
|
||||
let _ = gpio_low(29);
|
||||
sleep(500_000); // 0.5s
|
||||
sleep_ms(500); // 0.5s
|
||||
print_gpio_state();
|
||||
}
|
||||
}
|
||||
|
||||
fn print_gpio_state() {
|
||||
let state = gpio_get_state(21);
|
||||
let state = gpio_get_state(26);
|
||||
|
||||
let ascii_byte = b'0' + state;
|
||||
let data = [ascii_byte];
|
||||
@@ -110,6 +109,13 @@ pub fn get_current_el() -> u64 {
|
||||
el >> 2
|
||||
}
|
||||
|
||||
fn enable_uart() {
|
||||
uart_init();
|
||||
// Set GPIO Pins to UART
|
||||
let _ = set_gpio_state(14, GPIOState::Alternative0);
|
||||
let _ = set_gpio_state(15, GPIOState::Alternative0);
|
||||
}
|
||||
|
||||
fn print_current_el_str() {
|
||||
let el = get_current_el();
|
||||
let el_str = match el {
|
||||
|
||||
@@ -115,7 +115,18 @@ fn gpio_pull_up_down(gpio: u8, val: u32) {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn gpio_enable_low_detect(gpio: u8, enable: bool) {
|
||||
pub fn read_falling_edge_detect(gpio: u8) -> u32 {
|
||||
unsafe {
|
||||
// Determine GPLEN Register
|
||||
let register_addr = GPFEN_BASE + 4 * (gpio as u32 / 32);
|
||||
let register_offset = gpio % 32;
|
||||
|
||||
let current = read_volatile(register_addr as *const u32);
|
||||
return (current >> register_offset) & 0b1;
|
||||
}
|
||||
}
|
||||
|
||||
pub fn set_falling_edge_detect(gpio: u8, enable: bool) {
|
||||
unsafe {
|
||||
// Determine GPLEN Register
|
||||
let register_addr = GPFEN_BASE + 4 * (gpio as u32 / 32);
|
||||
@@ -133,7 +144,7 @@ pub fn gpio_enable_low_detect(gpio: u8, enable: bool) {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn gpio_enable_high_detect(gpio: u8, enable: bool) {
|
||||
pub fn set_rising_edge_detect(gpio: u8, enable: bool) {
|
||||
unsafe {
|
||||
// Determine GPHEN Register
|
||||
let register_addr = GPREN_BASE + 4 * (gpio as u32 / 32);
|
||||
2
src/peripherals/mod.rs
Normal file
2
src/peripherals/mod.rs
Normal file
@@ -0,0 +1,2 @@
|
||||
pub mod gpio;
|
||||
pub mod uart;
|
||||
@@ -16,6 +16,7 @@ const UART0_CR_TXE: u32 = 1 << 8;
|
||||
const UART0_LCRH: u32 = 0x3F20_102c;
|
||||
const UART0_LCRH_FEN: u32 = 1 << 4;
|
||||
|
||||
/// Print `s` over UART
|
||||
pub fn print(s: &str) {
|
||||
for byte in s.bytes() {
|
||||
unsafe {
|
||||
@@ -27,6 +28,7 @@ pub fn print(s: &str) {
|
||||
unsafe { while (core::ptr::read_volatile(UART0_FR as *const u32) >> 3) & 0b1 != 0 {} }
|
||||
}
|
||||
|
||||
/// Initialize UART peripheral
|
||||
pub fn uart_init() {
|
||||
let baud_div_times_64 = (UART_CLK * 4) / BAUD;
|
||||
|
||||
@@ -50,6 +52,7 @@ pub fn uart_init() {
|
||||
}
|
||||
}
|
||||
|
||||
/// Enable UARTEN
|
||||
fn uart_enable(enable: bool) {
|
||||
unsafe {
|
||||
let mut cr = core::ptr::read_volatile(UART0_CR as *mut u32);
|
||||
@@ -64,6 +67,7 @@ fn uart_enable(enable: bool) {
|
||||
}
|
||||
}
|
||||
|
||||
/// Enable UART FIFO
|
||||
fn uart_fifo_enable(enable: bool) {
|
||||
unsafe {
|
||||
let mut lcrh = core::ptr::read_volatile(UART0_LCRH as *mut u32);
|
||||
@@ -78,6 +82,7 @@ fn uart_fifo_enable(enable: bool) {
|
||||
}
|
||||
}
|
||||
|
||||
/// Set UART word length and set FIFO status
|
||||
fn uart_set_lcrh(wlen: u32, enable_fifo: bool) {
|
||||
unsafe {
|
||||
let mut value = (wlen & 0b11) << 5;
|
||||
16
src/timer.rs
16
src/timer.rs
@@ -4,13 +4,25 @@ fn read_clo() -> u32 {
|
||||
unsafe { return core::ptr::read_volatile(TIMER_CLO as *const u32) }
|
||||
}
|
||||
|
||||
pub fn sleep(microseconds: u32) {
|
||||
/// Sleep for `us` microseconds
|
||||
pub fn sleep_us(us: u32) {
|
||||
let start = read_clo();
|
||||
while read_clo() - start < microseconds {
|
||||
while read_clo() - start < us {
|
||||
unsafe { core::arch::asm!("nop") }
|
||||
}
|
||||
}
|
||||
|
||||
/// Sleep for `ms` milliseconds
|
||||
pub fn sleep_ms(ms: u32) {
|
||||
sleep_us(ms * 1000);
|
||||
}
|
||||
|
||||
/// Sleep for `s` seconds
|
||||
pub fn sleep_s(s: u32) {
|
||||
sleep_us(s * 1000);
|
||||
}
|
||||
|
||||
/// Wait for `count` operations to pass
|
||||
pub fn delay_nops(count: u32) {
|
||||
for _ in 0..count {
|
||||
unsafe { core::arch::asm!("nop") }
|
||||
|
||||
Reference in New Issue
Block a user