mirror of
https://github.com/iceHtwoO/novaOS.git
synced 2026-04-16 20:22:26 +00:00
Implement blinking LED
This commit is contained in:
68
src/gpio.rs
Normal file
68
src/gpio.rs
Normal file
@@ -0,0 +1,68 @@
|
|||||||
|
use crate::{
|
||||||
|
delay,
|
||||||
|
uart::{self},
|
||||||
|
};
|
||||||
|
|
||||||
|
const GPFSEL4: u32 = 0x3F20_0010; //GPIO 40-49
|
||||||
|
const GPPUD: u32 = 0x3F20_0094;
|
||||||
|
const GPPUD_CLK: u32 = 0x3F20_0098; // GPIO 32-53
|
||||||
|
|
||||||
|
unsafe fn set_gpio47_to_output() {
|
||||||
|
let value: u32 = 0b001 << 21;
|
||||||
|
|
||||||
|
core::ptr::write_volatile(GPFSEL4 as *mut u32, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe fn enable_pull_up() {
|
||||||
|
let value: u32 = 0b10;
|
||||||
|
|
||||||
|
core::ptr::write_volatile(GPPUD as *mut u32, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe fn enable_pull_down() {
|
||||||
|
let value: u32 = 0b01;
|
||||||
|
|
||||||
|
core::ptr::write_volatile(GPPUD as *mut u32, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe fn disable_GPPUD() {
|
||||||
|
core::ptr::write_volatile(GPPUD as *mut u32, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe fn enable_clock_gpio47() {
|
||||||
|
let value: u32 = 0b1 << 13;
|
||||||
|
|
||||||
|
core::ptr::write_volatile(GPPUD as *mut u32, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe fn disable_GPPUD_CLK() {
|
||||||
|
core::ptr::write_volatile(GPPUD as *mut u32, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn pull_up_gpio47() {
|
||||||
|
unsafe {
|
||||||
|
uart::print("Pull Up\n");
|
||||||
|
set_gpio47_to_output();
|
||||||
|
enable_pull_up();
|
||||||
|
// Wait 150 cycles
|
||||||
|
delay(150);
|
||||||
|
enable_clock_gpio47();
|
||||||
|
delay(150);
|
||||||
|
disable_GPPUD();
|
||||||
|
disable_GPPUD_CLK();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn pull_down_gpio47() {
|
||||||
|
unsafe {
|
||||||
|
uart::print("Pull Down\n");
|
||||||
|
set_gpio47_to_output();
|
||||||
|
enable_pull_down();
|
||||||
|
// Wait 150 cycles
|
||||||
|
delay(150);
|
||||||
|
enable_clock_gpio47();
|
||||||
|
delay(150);
|
||||||
|
disable_GPPUD();
|
||||||
|
disable_GPPUD_CLK();
|
||||||
|
}
|
||||||
|
}
|
||||||
124
src/main.rs
124
src/main.rs
@@ -2,47 +2,17 @@
|
|||||||
#![no_std]
|
#![no_std]
|
||||||
#![feature(asm_experimental_arch)]
|
#![feature(asm_experimental_arch)]
|
||||||
|
|
||||||
use core::{
|
use core::panic::PanicInfo;
|
||||||
arch::asm,
|
|
||||||
fmt::{self, Write},
|
use gpio::{pull_down_gpio47, pull_up_gpio47};
|
||||||
panic::PanicInfo,
|
|
||||||
};
|
mod gpio;
|
||||||
|
mod uart;
|
||||||
|
|
||||||
#[panic_handler]
|
#[panic_handler]
|
||||||
fn panic(_panic: &PanicInfo) -> ! {
|
fn panic(_panic: &PanicInfo) -> ! {
|
||||||
loop {}
|
loop {
|
||||||
}
|
uart::print("Panic");
|
||||||
|
|
||||||
const BAUD: u32 = 115200;
|
|
||||||
const UART_CLK: u32 = 48_000_000;
|
|
||||||
|
|
||||||
const UART0_DR: u32 = 0x3F20_1000;
|
|
||||||
|
|
||||||
const UART0_FR: u32 = 0x3F20_1018;
|
|
||||||
const UART0_FR_TXFF: u32 = 1 << 5;
|
|
||||||
|
|
||||||
const UART0_IBRD: u32 = 0x3F20_1024;
|
|
||||||
const UART0_FBRD: u32 = 0x3F20_1028;
|
|
||||||
|
|
||||||
const UART0_CR: u32 = 0x3F20_1030;
|
|
||||||
const UART0_CR_UARTEN: u32 = 1 << 0;
|
|
||||||
const UART0_CR_TXE: u32 = 1 << 8;
|
|
||||||
|
|
||||||
const UART0_LCRH: u32 = 0x3F20_102c;
|
|
||||||
const UART0_LCRH_FEN: u32 = 1 << 4;
|
|
||||||
const UART0_LCRH_WLEN: u32 = 11 << 5;
|
|
||||||
|
|
||||||
struct Uart;
|
|
||||||
|
|
||||||
impl Write for Uart {
|
|
||||||
fn write_str(&mut self, s: &str) -> fmt::Result {
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Ok(())
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -54,77 +24,23 @@ pub extern "C" fn _start() -> ! {
|
|||||||
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
fn main() {
|
fn main() {
|
||||||
configure_uart();
|
uart::configure_uart();
|
||||||
delay(50000);
|
|
||||||
let mut uart = Uart {};
|
// Delay so clock speed can stabilize
|
||||||
|
unsafe { delay(50000) }
|
||||||
|
uart::print("Hello World!\n");
|
||||||
|
|
||||||
loop {
|
loop {
|
||||||
writeln!(uart, "Hello World!");
|
pull_up_gpio47();
|
||||||
|
unsafe { delay(10_000_000) } // ~0.5s
|
||||||
|
pull_down_gpio47();
|
||||||
|
unsafe { delay(10_000_000) }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn configure_uart() {
|
unsafe fn delay(count: u32) {
|
||||||
let baud_div_times_64 = (UART_CLK * 4) / BAUD;
|
|
||||||
|
|
||||||
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);
|
|
||||||
|
|
||||||
uart_set_lcrh(0b11, true);
|
|
||||||
|
|
||||||
// Enable transmit and uart
|
|
||||||
let mut cr = core::ptr::read_volatile(UART0_CR as *mut u32);
|
|
||||||
cr |= UART0_CR_UARTEN | UART0_CR_TXE;
|
|
||||||
core::ptr::write_volatile(UART0_CR as *mut u32, cr);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn uart_enable(enable: bool) {
|
|
||||||
unsafe {
|
|
||||||
let mut cr = core::ptr::read_volatile(UART0_CR as *mut u32);
|
|
||||||
|
|
||||||
if enable {
|
|
||||||
cr |= UART0_CR_UARTEN;
|
|
||||||
} else {
|
|
||||||
cr &= !UART0_CR_UARTEN;
|
|
||||||
}
|
|
||||||
|
|
||||||
core::ptr::write_volatile(UART0_CR as *mut u32, cr);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn uart_fifo_enable(enable: bool) {
|
|
||||||
unsafe {
|
|
||||||
let mut lcrh = core::ptr::read_volatile(UART0_LCRH as *mut u32);
|
|
||||||
|
|
||||||
if enable {
|
|
||||||
lcrh |= UART0_LCRH_FEN;
|
|
||||||
} else {
|
|
||||||
lcrh &= !UART0_LCRH_FEN;
|
|
||||||
}
|
|
||||||
|
|
||||||
core::ptr::write_volatile(UART0_LCRH as *mut u32, lcrh);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn delay(count: u32) {
|
|
||||||
for _ in 0..count {
|
for _ in 0..count {
|
||||||
// Prevent compiler optimizing away the loop
|
// Prevent compiler optimizing away the loop
|
||||||
core::sync::atomic::spin_loop_hint();
|
core::arch::asm!("nop");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
86
src/uart.rs
Normal file
86
src/uart.rs
Normal file
@@ -0,0 +1,86 @@
|
|||||||
|
const BAUD: u32 = 115200;
|
||||||
|
const UART_CLK: u32 = 48_000_000;
|
||||||
|
|
||||||
|
const UART0_DR: u32 = 0x3F20_1000;
|
||||||
|
|
||||||
|
const UART0_FR: u32 = 0x3F20_1018;
|
||||||
|
const UART0_FR_TXFF: u32 = 1 << 5;
|
||||||
|
|
||||||
|
const UART0_IBRD: u32 = 0x3F20_1024;
|
||||||
|
const UART0_FBRD: u32 = 0x3F20_1028;
|
||||||
|
|
||||||
|
const UART0_CR: u32 = 0x3F20_1030;
|
||||||
|
const UART0_CR_UARTEN: u32 = 1 << 0;
|
||||||
|
const UART0_CR_TXE: u32 = 1 << 8;
|
||||||
|
|
||||||
|
const UART0_LCRH: u32 = 0x3F20_102c;
|
||||||
|
const UART0_LCRH_FEN: u32 = 1 << 4;
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn configure_uart() {
|
||||||
|
let baud_div_times_64 = (UART_CLK * 4) / BAUD;
|
||||||
|
|
||||||
|
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);
|
||||||
|
|
||||||
|
uart_set_lcrh(0b11, true);
|
||||||
|
|
||||||
|
// Enable transmit and uart
|
||||||
|
let mut cr = core::ptr::read_volatile(UART0_CR as *mut u32);
|
||||||
|
cr |= UART0_CR_UARTEN | UART0_CR_TXE;
|
||||||
|
core::ptr::write_volatile(UART0_CR as *mut u32, cr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn uart_enable(enable: bool) {
|
||||||
|
unsafe {
|
||||||
|
let mut cr = core::ptr::read_volatile(UART0_CR as *mut u32);
|
||||||
|
|
||||||
|
if enable {
|
||||||
|
cr |= UART0_CR_UARTEN;
|
||||||
|
} else {
|
||||||
|
cr &= !UART0_CR_UARTEN;
|
||||||
|
}
|
||||||
|
|
||||||
|
core::ptr::write_volatile(UART0_CR as *mut u32, cr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn uart_fifo_enable(enable: bool) {
|
||||||
|
unsafe {
|
||||||
|
let mut lcrh = core::ptr::read_volatile(UART0_LCRH as *mut u32);
|
||||||
|
|
||||||
|
if enable {
|
||||||
|
lcrh |= UART0_LCRH_FEN;
|
||||||
|
} else {
|
||||||
|
lcrh &= !UART0_LCRH_FEN;
|
||||||
|
}
|
||||||
|
|
||||||
|
core::ptr::write_volatile(UART0_LCRH as *mut u32, lcrh);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user