support raspi3b+ serial && uart interrupt
This commit is contained in:
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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) {
|
||||
|
||||
Reference in New Issue
Block a user