Merge branch 'feat/main' into feat/start
commit
9374b8a3bf
2
Makefile
2
Makefile
|
|
@ -3,13 +3,11 @@ U=user
|
||||||
|
|
||||||
OBJS = \
|
OBJS = \
|
||||||
$K/entry.o \
|
$K/entry.o \
|
||||||
$K/start.o \
|
|
||||||
$K/console.o \
|
$K/console.o \
|
||||||
$K/printf.o \
|
$K/printf.o \
|
||||||
$K/kalloc.o \
|
$K/kalloc.o \
|
||||||
$K/spinlock.o \
|
$K/spinlock.o \
|
||||||
$K/string.o \
|
$K/string.o \
|
||||||
$K/main.o \
|
|
||||||
$K/vm.o \
|
$K/vm.o \
|
||||||
$K/proc.o \
|
$K/proc.o \
|
||||||
$K/swtch.o \
|
$K/swtch.o \
|
||||||
|
|
|
||||||
|
|
@ -1,43 +0,0 @@
|
||||||
#include "types.h"
|
|
||||||
#include "param.h"
|
|
||||||
#include "memlayout.h"
|
|
||||||
#include "riscv.h"
|
|
||||||
#include "defs.h"
|
|
||||||
|
|
||||||
volatile static int started = 0;
|
|
||||||
|
|
||||||
// start() jumps here in supervisor mode on all CPUs.
|
|
||||||
void main() {
|
|
||||||
if (cpuid() == 0) {
|
|
||||||
consoleinit();
|
|
||||||
printfinit();
|
|
||||||
printf("\n");
|
|
||||||
printf("xv6 kernel is booting\n");
|
|
||||||
printf("\n");
|
|
||||||
kinit(); // physical page allocator
|
|
||||||
kvminit(); // create kernel page table
|
|
||||||
kvminithart(); // turn on paging
|
|
||||||
procinit(); // process table
|
|
||||||
trapinit(); // trap vectors
|
|
||||||
trapinithart(); // install kernel trap vector
|
|
||||||
plicinit(); // set up interrupt controller
|
|
||||||
plicinithart(); // ask PLIC for device interrupts
|
|
||||||
binit(); // buffer cache
|
|
||||||
iinit(); // inode table
|
|
||||||
fileinit(); // file table
|
|
||||||
virtio_disk_init(); // emulated hard disk
|
|
||||||
userinit(); // first user process
|
|
||||||
__sync_synchronize();
|
|
||||||
started = 1;
|
|
||||||
} else {
|
|
||||||
while (started == 0)
|
|
||||||
;
|
|
||||||
__sync_synchronize();
|
|
||||||
printf("hart %d starting\n", cpuid());
|
|
||||||
kvminithart(); // turn on paging
|
|
||||||
trapinithart(); // install kernel trap vector
|
|
||||||
plicinithart(); // ask PLIC for device interrupts
|
|
||||||
}
|
|
||||||
|
|
||||||
scheduler();
|
|
||||||
}
|
|
||||||
|
|
@ -8,12 +8,6 @@
|
||||||
#include "proc.h"
|
#include "proc.h"
|
||||||
#include "defs.h"
|
#include "defs.h"
|
||||||
|
|
||||||
void initlock(struct spinlock *lk, char *name) {
|
|
||||||
lk->name = name;
|
|
||||||
lk->locked = 0;
|
|
||||||
lk->cpu = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Acquire the lock.
|
// Acquire the lock.
|
||||||
// Loops (spins) until the lock is acquired.
|
// Loops (spins) until the lock is acquired.
|
||||||
void acquire(struct spinlock *lk) {
|
void acquire(struct spinlock *lk) {
|
||||||
|
|
|
||||||
|
|
@ -1,45 +0,0 @@
|
||||||
#include "types.h"
|
|
||||||
#include "param.h"
|
|
||||||
#include "memlayout.h"
|
|
||||||
#include "riscv.h"
|
|
||||||
#include "defs.h"
|
|
||||||
|
|
||||||
void timerinit();
|
|
||||||
|
|
||||||
// a scratch area per CPU for machine-mode timer interrupts.
|
|
||||||
uint64 timer_scratch[NCPU][5];
|
|
||||||
|
|
||||||
// assembly code in kernelvec.S for machine-mode timer interrupt.
|
|
||||||
extern void timervec();
|
|
||||||
|
|
||||||
// arrange to receive timer interrupts.
|
|
||||||
// they will arrive in machine mode at
|
|
||||||
// at timervec in kernelvec.S,
|
|
||||||
// which turns them into software interrupts for
|
|
||||||
// devintr() in trap.c.
|
|
||||||
void timerinit() {
|
|
||||||
// each CPU has a separate source of timer interrupts.
|
|
||||||
int id = r_mhartid();
|
|
||||||
|
|
||||||
// ask the CLINT for a timer interrupt.
|
|
||||||
int interval = 1000000; // cycles; about 1/10th second in qemu.
|
|
||||||
*(uint64 *)CLINT_MTIMECMP(id) = *(uint64 *)CLINT_MTIME + interval;
|
|
||||||
|
|
||||||
// prepare information in scratch[] for timervec.
|
|
||||||
// scratch[0..2] : space for timervec to save registers.
|
|
||||||
// scratch[3] : address of CLINT MTIMECMP register.
|
|
||||||
// scratch[4] : desired interval (in cycles) between timer interrupts.
|
|
||||||
uint64 *scratch = &timer_scratch[id][0];
|
|
||||||
scratch[3] = CLINT_MTIMECMP(id);
|
|
||||||
scratch[4] = interval;
|
|
||||||
w_mscratch((uint64)scratch);
|
|
||||||
|
|
||||||
// set the machine-mode trap handler.
|
|
||||||
w_mtvec((uint64)timervec);
|
|
||||||
|
|
||||||
// enable machine-mode interrupts.
|
|
||||||
w_mstatus(r_mstatus() | MSTATUS_MIE);
|
|
||||||
|
|
||||||
// enable machine-mode timer interrupts.
|
|
||||||
w_mie(r_mie() | MIE_MTIE);
|
|
||||||
}
|
|
||||||
|
|
@ -0,0 +1,58 @@
|
||||||
|
use crate::riscv;
|
||||||
|
|
||||||
|
extern "C" {
|
||||||
|
fn cpuid() -> u64;
|
||||||
|
fn consoleinit();
|
||||||
|
fn printfinit();
|
||||||
|
// fn printf();
|
||||||
|
fn kinit();
|
||||||
|
fn kvminit();
|
||||||
|
fn kvminithart();
|
||||||
|
fn procinit();
|
||||||
|
fn trapinit();
|
||||||
|
fn trapinithart();
|
||||||
|
fn plicinit();
|
||||||
|
fn plicinithart();
|
||||||
|
fn binit();
|
||||||
|
fn iinit();
|
||||||
|
fn fileinit();
|
||||||
|
fn virtio_disk_init();
|
||||||
|
fn userinit();
|
||||||
|
fn scheduler();
|
||||||
|
}
|
||||||
|
|
||||||
|
pub static mut started: bool = false;
|
||||||
|
|
||||||
|
pub unsafe fn kmain() {
|
||||||
|
if cpuid() == 0 {
|
||||||
|
consoleinit();
|
||||||
|
printfinit();
|
||||||
|
// printf("\n");
|
||||||
|
// printf("xv6 kernel is booting\n");
|
||||||
|
// printf("\n");
|
||||||
|
kinit(); // physical page allocator
|
||||||
|
kvminit(); // create kernel page table
|
||||||
|
kvminithart(); // turn on paging
|
||||||
|
procinit(); // process table
|
||||||
|
trapinit(); // trap vectors
|
||||||
|
trapinithart(); // install kernel trap vector
|
||||||
|
plicinit(); // set up interrupt controller
|
||||||
|
plicinithart(); // ask PLIC for device interrupts
|
||||||
|
binit(); // buffer cache
|
||||||
|
iinit(); // inode table
|
||||||
|
fileinit(); // file table
|
||||||
|
virtio_disk_init(); // emulated hard disk
|
||||||
|
userinit(); // first user process
|
||||||
|
riscv::barrier();
|
||||||
|
started = true;
|
||||||
|
} else {
|
||||||
|
while !started {}
|
||||||
|
riscv::barrier();
|
||||||
|
// printf("hart %d starting\n", cpuid());
|
||||||
|
kvminithart(); // turn on paging
|
||||||
|
trapinithart(); // install kernel trap vector
|
||||||
|
plicinithart(); // ask PLIC for device interrupts
|
||||||
|
}
|
||||||
|
|
||||||
|
scheduler();
|
||||||
|
}
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
#![no_std]
|
#![no_std]
|
||||||
#![crate_type = "staticlib"]
|
#![crate_type = "staticlib"]
|
||||||
|
|
||||||
|
pub mod kmain;
|
||||||
pub mod memlayout;
|
pub mod memlayout;
|
||||||
pub mod param;
|
pub mod param;
|
||||||
pub mod riscv;
|
pub mod riscv;
|
||||||
|
|
|
||||||
|
|
@ -28,13 +28,12 @@ pub const VIRTIO0: i32 = 0x10001000;
|
||||||
pub const VIRTIO0_IRQ: i32 = 1;
|
pub const VIRTIO0_IRQ: i32 = 1;
|
||||||
|
|
||||||
// core local interruptor (CLINT), which contains the timer.
|
// core local interruptor (CLINT), which contains the timer.
|
||||||
pub const CLINT: i64 = 0x2000000;
|
pub const CLINT: u64 = 0x2000000;
|
||||||
// const CLINT_MTIMECMP(hartid) (CLINT + 0x4000 + 8 * (hartid));
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn CLINT_MTIMECMP(hartid: i32) -> i64 {
|
pub fn CLINT_MTIMECMP(hartid: u64) -> *mut u64 {
|
||||||
CLINT + 0x4000 + 8 * hartid as i64
|
(CLINT + 0x4000 + 8 * hartid) as *mut u64
|
||||||
}
|
}
|
||||||
pub const CLINT_MTIME: i64 = CLINT + 0xBFF8; // cycles since boot.
|
pub const CLINT_MTIME: *mut u64 = (CLINT + 0xBFF8) as *mut u64; // cycles since boot.
|
||||||
|
|
||||||
// qemu puts platform-level interrupt controller (PLIC) here.
|
// qemu puts platform-level interrupt controller (PLIC) here.
|
||||||
pub const PLIC: i64 = 0x0c000000;
|
pub const PLIC: i64 = 0x0c000000;
|
||||||
|
|
|
||||||
|
|
@ -93,16 +93,21 @@ pub unsafe fn w_sie(x: u64) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// // Machine-mode Interrupt Enable
|
// // Machine-mode Interrupt Enable
|
||||||
// #define MIE_MEIE (1L << 11) // external
|
pub const MIE_MEIE: u64 = 1 << 11; // external
|
||||||
// #define MIE_MTIE (1L << 7) // timer
|
pub const MIE_MTIE: u64 = 1 << 7; // timer
|
||||||
// #define MIE_MSIE (1L << 3) // software
|
pub const MIE_MSIE: u64 = 1 << 3; // software
|
||||||
// static inline uint64 r_mie() {
|
|
||||||
// uint64 x;
|
|
||||||
// asm volatile("csrr %0, mie" : "=r"(x));
|
|
||||||
// return x;
|
|
||||||
// }
|
|
||||||
|
|
||||||
// static inline void w_mie(uint64 x) { asm volatile("csrw mie, %0" : : "r"(x)); }
|
#[inline]
|
||||||
|
pub unsafe fn r_mie() -> u64 {
|
||||||
|
let x: u64;
|
||||||
|
asm!("csrr {x}, mie", x = out(reg) x);
|
||||||
|
x
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub unsafe fn w_mie(x: u64) {
|
||||||
|
asm!("csrw mie, {x}", x = in(reg) x);
|
||||||
|
}
|
||||||
|
|
||||||
// // supervisor exception program counter, holds the
|
// // supervisor exception program counter, holds the
|
||||||
// // instruction address to which a return from
|
// // instruction address to which a return from
|
||||||
|
|
@ -124,9 +129,6 @@ pub unsafe fn w_sie(x: u64) {
|
||||||
// return x;
|
// return x;
|
||||||
// }
|
// }
|
||||||
|
|
||||||
// static inline void w_medeleg(uint64 x) {
|
|
||||||
// asm volatile("csrw medeleg, %0" : : "r"(x));
|
|
||||||
// }
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub unsafe fn w_medeleg(x: u64) {
|
pub unsafe fn w_medeleg(x: u64) {
|
||||||
asm!("csrw medeleg, {x}", x = in(reg) x);
|
asm!("csrw medeleg, {x}", x = in(reg) x);
|
||||||
|
|
@ -139,9 +141,6 @@ pub unsafe fn w_medeleg(x: u64) {
|
||||||
// return x;
|
// return x;
|
||||||
// }
|
// }
|
||||||
|
|
||||||
// static inline void w_mideleg(uint64 x) {
|
|
||||||
// asm volatile("csrw mideleg, %0" : : "r"(x));
|
|
||||||
// }
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub unsafe fn w_mideleg(x: u64) {
|
pub unsafe fn w_mideleg(x: u64) {
|
||||||
asm!("csrw mideleg, {x}", x = in(reg) x);
|
asm!("csrw mideleg, {x}", x = in(reg) x);
|
||||||
|
|
@ -160,22 +159,17 @@ pub unsafe fn w_mideleg(x: u64) {
|
||||||
// }
|
// }
|
||||||
|
|
||||||
// // Machine-mode interrupt vector
|
// // Machine-mode interrupt vector
|
||||||
// static inline void w_mtvec(uint64 x) {
|
#[inline]
|
||||||
// asm volatile("csrw mtvec, %0" : : "r"(x));
|
pub unsafe fn w_mtvec(x: u64) {
|
||||||
// }
|
asm!("csrw mtvec, {x}", x = in(reg) x);
|
||||||
|
}
|
||||||
|
|
||||||
// // Physical Memory Protection
|
// Physical Memory Protection
|
||||||
// static inline void w_pmpcfg0(uint64 x) {
|
|
||||||
// asm volatile("csrw pmpcfg0, %0" : : "r"(x));
|
|
||||||
// }
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub unsafe fn w_pmpcfg0(x: u64) {
|
pub unsafe fn w_pmpcfg0(x: u64) {
|
||||||
asm!("csrw pmpcfg0, {x}", x = in(reg) x);
|
asm!("csrw pmpcfg0, {x}", x = in(reg) x);
|
||||||
}
|
}
|
||||||
|
|
||||||
// static inline void w_pmpaddr0(uint64 x) {
|
|
||||||
// asm volatile("csrw pmpaddr0, %0" : : "r"(x));
|
|
||||||
// }
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub unsafe fn w_pmpaddr0(x: u64) {
|
pub unsafe fn w_pmpaddr0(x: u64) {
|
||||||
asm!("csrw pmpaddr0, {x}", x = in(reg) x);
|
asm!("csrw pmpaddr0, {x}", x = in(reg) x);
|
||||||
|
|
@ -186,11 +180,8 @@ pub unsafe fn w_pmpaddr0(x: u64) {
|
||||||
|
|
||||||
// #define MAKE_SATP(pagetable) (SATP_SV39 | (((uint64)pagetable) >> 12))
|
// #define MAKE_SATP(pagetable) (SATP_SV39 | (((uint64)pagetable) >> 12))
|
||||||
|
|
||||||
// // supervisor address translation and protection;
|
// supervisor address translation and protection;
|
||||||
// // holds the address of the page table.
|
// holds the address of the page table.
|
||||||
// static inline void w_satp(uint64 x) {
|
|
||||||
// asm volatile("csrw satp, %0" : : "r"(x));
|
|
||||||
// }
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub unsafe fn w_satp(x: u64) {
|
pub unsafe fn w_satp(x: u64) {
|
||||||
asm!("csrw satp, {x}", x = in(reg) x);
|
asm!("csrw satp, {x}", x = in(reg) x);
|
||||||
|
|
@ -202,9 +193,10 @@ pub unsafe fn w_satp(x: u64) {
|
||||||
// return x;
|
// return x;
|
||||||
// }
|
// }
|
||||||
|
|
||||||
// static inline void w_mscratch(uint64 x) {
|
#[inline]
|
||||||
// asm volatile("csrw mscratch, %0" : : "r"(x));
|
pub unsafe fn w_mscratch(x: u64) {
|
||||||
// }
|
asm!("csrw mscratch, {x}", x = in(reg) x);
|
||||||
|
}
|
||||||
|
|
||||||
// // Supervisor Trap Cause
|
// // Supervisor Trap Cause
|
||||||
// static inline uint64 r_scause() {
|
// static inline uint64 r_scause() {
|
||||||
|
|
@ -335,3 +327,9 @@ pub fn PX(level: u64, va: u64) -> u64 {
|
||||||
// Sv39, to avoid having to sign-extend virtual addresses
|
// Sv39, to avoid having to sign-extend virtual addresses
|
||||||
// that have the high bit set.
|
// that have the high bit set.
|
||||||
pub const MAXVA: u64 = 1 << (9 + 9 + 9 + 12 - 1);
|
pub const MAXVA: u64 = 1 << (9 + 9 + 9 + 12 - 1);
|
||||||
|
|
||||||
|
/// Hardware memory barrier
|
||||||
|
#[inline]
|
||||||
|
pub unsafe fn barrier() {
|
||||||
|
asm!("fence")
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,18 @@
|
||||||
|
use core::ptr::null_mut;
|
||||||
|
|
||||||
// Mutual exclusion lock.
|
// Mutual exclusion lock.
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
pub struct SpinLock {
|
pub struct SpinLock {
|
||||||
// Is the lock held?
|
// Is the lock held?
|
||||||
pub locked: u32, // C boolean
|
pub locked: u32, // C boolean
|
||||||
// For debugging:
|
// For debugging:
|
||||||
pub name: Option<*mut ()>, // Name of lock.
|
pub name: *const u8, // Name of lock.
|
||||||
pub cpu: Option<*mut ()>, // The cpu holding the lock.
|
pub cpu: *mut (), // The cpu holding the lock.
|
||||||
|
}
|
||||||
|
|
||||||
|
#[no_mangle]
|
||||||
|
pub unsafe extern "C" fn initlock(lock: *mut SpinLock, name: *const u8) {
|
||||||
|
(*lock).name = name;
|
||||||
|
(*lock).locked = 0;
|
||||||
|
(*lock).cpu = null_mut();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,20 +1,25 @@
|
||||||
use core::arch::asm;
|
use core::arch::asm;
|
||||||
|
use core::usize;
|
||||||
|
|
||||||
|
use crate::kmain::kmain;
|
||||||
|
use crate::memlayout::{CLINT_MTIME, CLINT_MTIMECMP};
|
||||||
use crate::param::NCPU;
|
use crate::param::NCPU;
|
||||||
use crate::riscv as rv;
|
use crate::riscv as rv;
|
||||||
|
|
||||||
extern "C" {
|
extern "C" {
|
||||||
// start.c
|
// assembly code in kernelvec.S for machine-mode timer interrupt.
|
||||||
fn timerinit();
|
fn timervec();
|
||||||
|
|
||||||
// main.c
|
|
||||||
fn main();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[repr(align(16))]
|
#[repr(align(16))]
|
||||||
pub struct AlignedStack([u8; 4096 * NCPU]);
|
pub struct EntryStack([u8; 4096 * NCPU]);
|
||||||
|
|
||||||
|
// entry.S needs one stack per CPU.
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub static mut stack0: AlignedStack = AlignedStack([0; 4096 * NCPU]);
|
pub static mut stack0: EntryStack = EntryStack([0; 4096 * NCPU]);
|
||||||
|
|
||||||
|
// a scratch area per CPU for machine-mode timer interrupts.
|
||||||
|
static mut timer_scratch: [[u64; 5]; NCPU] = [[0; 5]; NCPU];
|
||||||
|
|
||||||
// entry.S jumps here in machine mode on stack0.
|
// entry.S jumps here in machine mode on stack0.
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
|
|
@ -27,7 +32,7 @@ pub unsafe extern "C" fn start() {
|
||||||
|
|
||||||
// set M Exception Program Counter to main, for mret.
|
// set M Exception Program Counter to main, for mret.
|
||||||
// requires gcc -mcmodel=medany
|
// requires gcc -mcmodel=medany
|
||||||
rv::w_mepc(main as *const () as u64);
|
rv::w_mepc(kmain as *const () as u64);
|
||||||
|
|
||||||
// disable paging for now.
|
// disable paging for now.
|
||||||
rv::w_satp(0);
|
rv::w_satp(0);
|
||||||
|
|
@ -52,3 +57,36 @@ pub unsafe extern "C" fn start() {
|
||||||
// switch to supervisor mode and jump to main().
|
// switch to supervisor mode and jump to main().
|
||||||
asm!("mret");
|
asm!("mret");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// arrange to receive timer interrupts.
|
||||||
|
// they will arrive in machine mode at
|
||||||
|
// at timervec in kernelvec.S,
|
||||||
|
// which turns them into software interrupts for
|
||||||
|
// devintr() in trap.c.
|
||||||
|
unsafe fn timerinit() {
|
||||||
|
// each CPU has a separate source of timer interrupts.
|
||||||
|
let id = rv::r_mhartid();
|
||||||
|
|
||||||
|
// ask the CLINT for a timer interrupt.
|
||||||
|
let interval: u64 = 1000000; // cycles; about 1/10th second in qemu.
|
||||||
|
*CLINT_MTIMECMP(id) = *CLINT_MTIME + interval;
|
||||||
|
|
||||||
|
// prepare information in scratch[] for timervec.
|
||||||
|
// scratch[0..2] : space for timervec to save registers.
|
||||||
|
// scratch[3] : address of CLINT MTIMECMP register.
|
||||||
|
// scratch[4] : desired interval (in cycles) between timer interrupts.
|
||||||
|
timer_scratch[id as usize][3] = CLINT_MTIMECMP(id) as u64;
|
||||||
|
timer_scratch[id as usize][4] = interval;
|
||||||
|
|
||||||
|
// w_mscratch((uint64)scratch);
|
||||||
|
rv::w_mscratch(timer_scratch[id as usize].as_ptr() as u64);
|
||||||
|
|
||||||
|
// set the machine-mode trap handler.
|
||||||
|
rv::w_mtvec(timervec as *const () as u64);
|
||||||
|
|
||||||
|
// enable machine-mode interrupts.
|
||||||
|
rv::w_mstatus(rv::r_mstatus() | rv::MSTATUS_MIE);
|
||||||
|
|
||||||
|
// enable machine-mode timer interrupts.
|
||||||
|
rv::w_mie(rv::r_mie() | rv::MIE_MTIE);
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,11 +1,13 @@
|
||||||
use crate::{memlayout::UART0, spinlock::SpinLock};
|
use crate::{
|
||||||
use core::ptr::addr_of_mut;
|
memlayout::UART0,
|
||||||
|
spinlock::{initlock, SpinLock},
|
||||||
|
};
|
||||||
|
use core::ptr::{addr_of_mut, null, null_mut};
|
||||||
|
|
||||||
extern "C" {
|
extern "C" {
|
||||||
// spinlock.c
|
// spinlock.c
|
||||||
fn push_off();
|
fn push_off();
|
||||||
fn pop_off();
|
fn pop_off();
|
||||||
fn initlock(spinlock: *mut SpinLock, name: *const u8);
|
|
||||||
fn acquire(spinlock: *mut SpinLock);
|
fn acquire(spinlock: *mut SpinLock);
|
||||||
fn release(spinlock: *mut SpinLock);
|
fn release(spinlock: *mut SpinLock);
|
||||||
|
|
||||||
|
|
@ -60,12 +62,12 @@ pub fn WriteReg(reg: u8, v: u8) {
|
||||||
// the transmit output buffer.
|
// the transmit output buffer.
|
||||||
static mut uart_tx_lock: crate::spinlock::SpinLock = crate::spinlock::SpinLock {
|
static mut uart_tx_lock: crate::spinlock::SpinLock = crate::spinlock::SpinLock {
|
||||||
locked: 0,
|
locked: 0,
|
||||||
cpu: None,
|
cpu: null_mut(),
|
||||||
name: None,
|
name: null(),
|
||||||
};
|
};
|
||||||
|
|
||||||
// NOTE: string 'uart\0' for c-implmentation of spinlock. Stupid but works.
|
// NOTE: string 'uart\0' for c-implmentation of spinlock. Stupid but works.
|
||||||
static UART_LOCK_NAME: [u8; 5] = [117, 97, 114, 116, 0];
|
static UART_LOCK_NAME: [u8; 5] = [0x75, 0x61, 0x72, 0x74, 0];
|
||||||
|
|
||||||
const UART_TX_BUF_SIZE: usize = 32;
|
const UART_TX_BUF_SIZE: usize = 32;
|
||||||
static mut uart_tx_buf: [u8; UART_TX_BUF_SIZE] = [0; UART_TX_BUF_SIZE];
|
static mut uart_tx_buf: [u8; UART_TX_BUF_SIZE] = [0; UART_TX_BUF_SIZE];
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue