support raspi3b+ serial && uart interrupt

This commit is contained in:
Ivan Tan
2023-12-05 23:00:26 +08:00
committed by Jeremy Soller
parent 44b14f994a
commit a8329956ca
3 changed files with 51 additions and 24 deletions
+13 -2
View File
@@ -159,8 +159,19 @@ impl InterruptController for Bcm2835ArmInterruptController {
fn irq_ack(&mut self) -> u32 {
//TODO: support smp self.read(LOCAL_IRQ_PENDING + 4 * cpu)
let sources = unsafe { self.read(PENDING_0) & 0x3ff };
let sources = unsafe { self.read(PENDING_0) };
let pending_num = ffs(sources) - 1;
let fast_irq = [
7 + 32, 9 + 32, 10 + 32, 18 + 32, 19 + 32,
21 + 64, 22 + 64, 23 + 64, 24 + 64, 25 + 64, 30 + 64
];
//fast irq
if pending_num >= 10 && pending_num <= 20 {
return fast_irq[(pending_num - 10) as usize];
}
let pending_num = ffs(sources & 0x3ff) - 1;
match pending_num {
num@0..=7 => {
println!("inner interrupt {}", num);
@@ -177,7 +188,7 @@ impl InterruptController for Bcm2835ArmInterruptController {
return irq_32_63 + 64;
},
num => {
println!("unexpected irq pending in BASIC PENDING: {}", num);
println!("unexpected irq pending in BASIC PENDING: 0x{}, sources = 0x{:08x}", num, sources);
return num;
}
}
+2 -2
View File
@@ -35,10 +35,10 @@ pub unsafe fn init_early(dtb_base: usize, dtb_size: usize) {
let virt = crate::PHYS_OFFSET + phys;
{
let mut serial_port = SerialPort::new(virt);
serial_port.init(false);
//serial_port.init(false);
*COM1.lock() = Some(serial_port);
}
println!("UART at {:X}", virt);
println!("2 UART at {:X}", virt);
}
}
+36 -20
View File
@@ -9,7 +9,7 @@ use super::irqchip::InterruptHandler;
bitflags! {
/// UARTFR
struct UartFrFlags: u16 {
struct UartFrFlags: u32 {
const TXFE = 1 << 7;
const RXFF = 1 << 6;
const TXFF = 1 << 5;
@@ -20,7 +20,7 @@ bitflags! {
bitflags! {
/// UARTCR
struct UartCrFlags: u16 {
struct UartCrFlags: u32 {
const RXE = 1 << 9;
const TXE = 1 << 8;
const UARTEN = 1 << 0;
@@ -29,7 +29,7 @@ bitflags! {
bitflags! {
// UARTIMSC
struct UartImscFlags: u16 {
struct UartImscFlags: u32 {
const RTIM = 1 << 6;
const TXIM = 1 << 5;
const RXIM = 1 << 4;
@@ -38,7 +38,7 @@ bitflags! {
bitflags! {
// UARTICR
struct UartIcrFlags: u16 {
struct UartIcrFlags: u32 {
const RTIC = 1 << 6;
const TXIC = 1 << 5;
const RXIC = 1 << 4;
@@ -47,7 +47,7 @@ bitflags! {
bitflags! {
//UARTMIS
struct UartMisFlags: u16 {
struct UartMisFlags: u32 {
const TXMIS = 1 << 5;
const RXMIS = 1 << 4;
}
@@ -55,7 +55,7 @@ bitflags! {
bitflags! {
//UARTLCR_H
struct UartLcrhFlags: u16 {
struct UartLcrhFlags: u32 {
const FEN = 1 << 4;
}
}
@@ -102,28 +102,31 @@ impl SerialPort {
self.base
}
pub fn read_reg(&self, register: u8) -> u16 {
unsafe { ptr::read_volatile((self.base + register as usize) as *mut u16) }
pub fn read_reg(&self, register: u8) -> u32 {
unsafe { ptr::read_volatile((self.base + register as usize) as *mut u32) }
}
pub fn write_reg(&self, register: u8, data: u16) {
unsafe { ptr::write_volatile((self.base + register as usize) as *mut u16, data); }
pub fn write_reg(&self, register: u8, data: u32) {
unsafe { ptr::write_volatile((self.base + register as usize) as *mut u32, data); }
}
pub fn init(&mut self, with_irq: bool) {
/*
// Enable RX, TX, UART
let flags = UartCrFlags::RXE | UartCrFlags::TXE | UartCrFlags::UARTEN;
self.write_reg(self.ctrl_reg, flags.bits());
*/
// Disable FIFOs (use character mode instead)
//Enable FIFO
/*
let mut flags = UartLcrhFlags::from_bits_truncate(self.read_reg(self.line_ctrl_reg));
flags.remove(UartLcrhFlags::FEN);
flags |= UartLcrhFlags::FEN;
self.write_reg(self.line_ctrl_reg, flags.bits());
*/
if with_irq {
// Enable IRQs
let flags = UartImscFlags::RXIM;
self.write_reg(self.intr_mask_setclr_reg, flags.bits);
let flags = (1 << 4 | 1 << 6);
self.write_reg(self.intr_mask_setclr_reg, flags);
// Clear pending interrupts
self.write_reg(self.intr_clr_reg, 0x7ff);
@@ -136,18 +139,31 @@ impl SerialPort {
}
pub fn receive(&mut self) {
while self.line_sts().contains(UartFrFlags::RXFF) {
let c = self.read_reg(self.data_reg) as u8;
if c != 0 {
debug_input(c);
self.write_reg(self.intr_clr_reg, 0x00);
let _ = self.read_reg(self.intr_clr_reg);
let _ = self.read_reg(self.intr_clr_reg);
let mut status = self.read_reg(self.raw_intr_stat_reg) & (1 << 4 | 1 << 6);
while status != 0 {
for _ in 0..256 {
let reg_val = self.read_reg(self.flag_reg);
if (reg_val & 0x010) != 0 {
break;
}
let c = self.read_reg(self.data_reg) as u8;
if c != 0 {
debug_input(c);
self.send(c);
}
}
status = self.read_reg(self.raw_intr_stat_reg) & (1 << 4 | 1 << 6);
}
debug_notify();
}
pub fn send(&mut self, data: u8) {
while ! self.line_sts().contains(UartFrFlags::TXFE) {}
self.write_reg(self.data_reg, data as u16);
self.write_reg(self.data_reg, data as u32);
}
pub fn clear_all_irqs(&mut self) {