use core::cell::Cell;
use kernel::deferred_call::{DeferredCall, DeferredCallClient};
use kernel::hil;
use kernel::hil::uart::ReceiveClient;
use kernel::hil::uart::{
Configure, Parameters, Parity, Receive, StopBits, Transmit, TransmitClient, Width,
};
use kernel::utilities::cells::{OptionalCell, TakeCell};
use kernel::utilities::registers::interfaces::{ReadWriteable, Readable, Writeable};
use kernel::utilities::registers::{register_bitfields, register_structs, ReadOnly, ReadWrite};
use kernel::utilities::StaticRef;
use kernel::ErrorCode;
use crate::clocks;
register_structs! {
UartRegisters {
(0x000 => uartdr: ReadWrite<u32, UARTDR::Register>),
(0x004 => uartrsr: ReadWrite<u32, UARTRSR::Register>),
(0x008 => _reserved0),
(0x018 => uartfr: ReadOnly<u32, UARTFR::Register>),
(0x01c => _reserved1),
(0x020 => uartilpr: ReadWrite<u32, UARTILPR::Register>),
(0x024 => uartibrd: ReadWrite<u32, UARTIBRD::Register>),
(0x028 => uartfbrd: ReadWrite<u32, UARTFBRD::Register>),
(0x02c => uartlcr_h: ReadWrite<u32, UARTLCR_H::Register>),
(0x030 => uartcr: ReadWrite<u32, UARTCR::Register>),
(0x034 => uartifls: ReadWrite<u32, UARTIFLS::Register>),
(0x038 => uartimsc: ReadWrite<u32, UARTIMSC::Register>),
(0x03c => uartris: ReadOnly<u32, UARTRIS::Register>),
(0x040 => uartmis: ReadOnly<u32, UARTMIS::Register>),
(0x044 => uarticr: ReadWrite<u32, UARTICR::Register>),
(0x048 => uartdmacr: ReadWrite<u32, UARTDMACR::Register>),
(0x04c => _reserved2),
(0xfe0 => uartperiphid0: ReadOnly<u32, UARTPERIPHID0::Register>),
(0xfe4 => uartperiphid1: ReadOnly<u32, UARTPERIPHID1::Register>),
(0xfe8 => uartperiphid2: ReadOnly<u32, UARTPERIPHID2::Register>),
(0xfec => uartperiphid3: ReadOnly<u32, UARTPERIPHID3::Register>),
(0xff0 => uartpcellid0: ReadOnly<u32, UARTPCELLID0::Register>),
(0xff4 => uartpcellid1: ReadOnly<u32, UARTPCELLID1::Register>),
(0xff8 => uartpcellid2: ReadOnly<u32, UARTPCELLID2::Register>),
(0xffc => uartpcellid3: ReadOnly<u32, UARTPCELLID3::Register>),
(0x1000 => @END),
}
}
register_bitfields! [u32,
UARTDR [
DATA OFFSET(0) NUMBITS(8) [],
FE OFFSET(8) NUMBITS(1) [],
PE OFFSET(9) NUMBITS(1) [],
BE OFFSET(10) NUMBITS(1) [],
OE OFFSET(11) NUMBITS(1) []
],
UARTRSR [
FE OFFSET(0) NUMBITS(1) [],
PE OFFSET(1) NUMBITS(1) [],
BE OFFSET(2) NUMBITS(1) [],
OE OFFSET(3) NUMBITS(1) []
],
UARTFR [
CTS OFFSET(0) NUMBITS(1) [],
DSR OFFSET(1) NUMBITS(1) [],
DCD OFFSET(2) NUMBITS(1) [],
BUSY OFFSET(3) NUMBITS(1) [],
RXFE OFFSET(4) NUMBITS(1) [],
TXFF OFFSET(5) NUMBITS(1) [],
RXFF OFFSET(6) NUMBITS(1) [],
TXFE OFFSET(7) NUMBITS(1) [],
RI OFFSET(8) NUMBITS(1) []
],
UARTILPR [
ILPDVSR OFFSET(0) NUMBITS(8) []
],
UARTIBRD [
BAUD_DIVINT OFFSET(0) NUMBITS(16) []
],
UARTFBRD [
BAUD_DIVFRAC OFFSET(0) NUMBITS(6) []
],
UARTLCR_H [
BRK OFFSET(0) NUMBITS(1) [],
PEN OFFSET(1) NUMBITS(1) [],
EPS OFFSET(2) NUMBITS(1) [],
STP2 OFFSET(3) NUMBITS(1) [],
FEN OFFSET(4) NUMBITS(1) [],
WLEN OFFSET(5) NUMBITS(2) [
BITS_8 = 0b11,
BITS_7 = 0b10,
BITS_6 = 0b01,
BITS_5 = 0b00
],
SPS OFFSET(7) NUMBITS(1) []
],
UARTCR [
UARTEN OFFSET(0) NUMBITS(1) [],
SIREN OFFSET(1) NUMBITS(1) [],
SIRLP OFFSET(2) NUMBITS(1) [],
LBE OFFSET(7) NUMBITS(1) [],
TXE OFFSET(8) NUMBITS(1) [],
RXE OFFSET(9) NUMBITS(1) [],
DTR OFFSET(10) NUMBITS(1) [],
RTS OFFSET(11) NUMBITS(1) [],
OUT1 OFFSET(12) NUMBITS(1) [],
OUT2 OFFSET(13) NUMBITS(1) [],
RTSEN OFFSET(14) NUMBITS(1) [],
CTSEN OFFSET(15) NUMBITS(1) []
],
UARTIFLS [
TXIFLSEL OFFSET(0) NUMBITS(3) [
FIFO_1_8 = 0b000,
FIFO_1_4 = 0b001,
FIFO_1_2 = 0b010,
FIFO_3_4 = 0b011,
FIFO_7_8 = 0b100,
],
RXIFLSEL OFFSET(3) NUMBITS(3) [
FIFO_1_8 = 0b000,
FIFO_1_4 = 0b001,
FIFO_1_2 = 0b010,
FIFO_3_4 = 0b011,
FIFO_7_8 = 0b100,
]
],
UARTIMSC [
RIMIM OFFSET(0) NUMBITS(1) [],
CTSMIM OFFSET(1) NUMBITS(1) [],
DCDMIM OFFSET(2) NUMBITS(1) [],
DSRMIM OFFSET(3) NUMBITS(1) [],
RXIM OFFSET(4) NUMBITS(1) [],
TXIM OFFSET(5) NUMBITS(1) [],
RTIM OFFSET(6) NUMBITS(1) [],
FEIM OFFSET(7) NUMBITS(1) [],
PEIM OFFSET(8) NUMBITS(1) [],
BEIM OFFSET(9) NUMBITS(1) [],
OEIM OFFSET(10) NUMBITS(1) []
],
UARTRIS [
RIRMIS OFFSET(0) NUMBITS(1) [],
CTSRMIS OFFSET(1) NUMBITS(1) [],
DCDRMIS OFFSET(2) NUMBITS(1) [],
DSRRMIS OFFSET(3) NUMBITS(1) [],
RXRIS OFFSET(4) NUMBITS(1) [],
TXRIS OFFSET(5) NUMBITS(1) [],
RTRIS OFFSET(6) NUMBITS(1) [],
FERIS OFFSET(7) NUMBITS(1) [],
PERIS OFFSET(8) NUMBITS(1) [],
BERIS OFFSET(9) NUMBITS(1) [],
OERIS OFFSET(10) NUMBITS(1) []
],
UARTMIS [
RIMMIS OFFSET(0) NUMBITS(1) [],
CTSMMIS OFFSET(1) NUMBITS(1) [],
DCDMMIS OFFSET(2) NUMBITS(1) [],
DSRMMIS OFFSET(3) NUMBITS(1) [],
RXMIS OFFSET(4) NUMBITS(1) [],
TXMIS OFFSET(5) NUMBITS(1) [],
RTMIS OFFSET(6) NUMBITS(1) [],
FEMIS OFFSET(7) NUMBITS(1) [],
PEMIS OFFSET(8) NUMBITS(1) [],
BEMIS OFFSET(9) NUMBITS(1) [],
OEMIS OFFSET(10) NUMBITS(1) []
],
UARTICR [
RIMIC OFFSET(0) NUMBITS(1) [],
CTSMIC OFFSET(1) NUMBITS(1) [],
DCDMIC OFFSET(2) NUMBITS(1) [],
DSRMIC OFFSET(3) NUMBITS(1) [],
RXIC OFFSET(4) NUMBITS(1) [],
TXIC OFFSET(5) NUMBITS(1) [],
RTIC OFFSET(6) NUMBITS(1) [],
FEIC OFFSET(7) NUMBITS(1) [],
PEIC OFFSET(8) NUMBITS(1) [],
BEIC OFFSET(9) NUMBITS(1) [],
OEIC OFFSET(10) NUMBITS(1) []
],
UARTDMACR [
RXDMAE OFFSET(0) NUMBITS(1) [],
TXDMAE OFFSET(1) NUMBITS(1) [],
DMAONERR OFFSET(2) NUMBITS(1) []
],
UARTPERIPHID0 [
PARTNUMBER0 OFFSET(0) NUMBITS(8) []
],
UARTPERIPHID1 [
PARTNUMBER1 OFFSET(0) NUMBITS(4) [],
DESIGNER0 OFFSET(4) NUMBITS(4) []
],
UARTPERIPHID2 [
DESIGNER1 OFFSET(0) NUMBITS(4) [],
REVISION OFFSET(4) NUMBITS(4) []
],
UARTPERIPHID3 [
CONFIGURATION OFFSET(0) NUMBITS(8) []
],
UARTPCELLID0 [
UARTPCELLID0 OFFSET(0) NUMBITS(8) []
],
UARTPCELLID1 [
UARTPCELLID1 OFFSET(0) NUMBITS(8) []
],
UARTPCELLID2 [
UARTPCELLID2 OFFSET(0) NUMBITS(8) []
],
UARTPCELLID3 [
UARTPCELLID3 OFFSET(0) NUMBITS(8) []
]
];
#[derive(Copy, Clone, PartialEq)]
enum UARTStateTX {
Idle,
Transmitting,
AbortRequested,
}
#[derive(Copy, Clone, PartialEq)]
enum UARTStateRX {
Idle,
Receiving,
AbortRequested,
}
const UART0_BASE: StaticRef<UartRegisters> =
unsafe { StaticRef::new(0x40034000 as *const UartRegisters) };
const UART1_BASE: StaticRef<UartRegisters> =
unsafe { StaticRef::new(0x40038000 as *const UartRegisters) };
pub struct Uart<'a> {
registers: StaticRef<UartRegisters>,
clocks: OptionalCell<&'a clocks::Clocks>,
tx_client: OptionalCell<&'a dyn TransmitClient>,
rx_client: OptionalCell<&'a dyn ReceiveClient>,
tx_buffer: TakeCell<'static, [u8]>,
tx_position: Cell<usize>,
tx_len: Cell<usize>,
tx_status: Cell<UARTStateTX>,
rx_buffer: TakeCell<'static, [u8]>,
rx_position: Cell<usize>,
rx_len: Cell<usize>,
rx_status: Cell<UARTStateRX>,
deferred_call: DeferredCall,
}
impl<'a> Uart<'a> {
pub fn new_uart0() -> Self {
Self {
registers: UART0_BASE,
clocks: OptionalCell::empty(),
tx_client: OptionalCell::empty(),
rx_client: OptionalCell::empty(),
tx_buffer: TakeCell::empty(),
tx_position: Cell::new(0),
tx_len: Cell::new(0),
tx_status: Cell::new(UARTStateTX::Idle),
rx_buffer: TakeCell::empty(),
rx_position: Cell::new(0),
rx_len: Cell::new(0),
rx_status: Cell::new(UARTStateRX::Idle),
deferred_call: DeferredCall::new(),
}
}
pub fn new_uart1() -> Self {
Self {
registers: UART1_BASE,
clocks: OptionalCell::empty(),
tx_client: OptionalCell::empty(),
rx_client: OptionalCell::empty(),
tx_buffer: TakeCell::empty(),
tx_position: Cell::new(0),
tx_len: Cell::new(0),
tx_status: Cell::new(UARTStateTX::Idle),
rx_buffer: TakeCell::empty(),
rx_position: Cell::new(0),
rx_len: Cell::new(0),
rx_status: Cell::new(UARTStateRX::Idle),
deferred_call: DeferredCall::new(),
}
}
pub(crate) fn set_clocks(&self, clocks: &'a clocks::Clocks) {
self.clocks.set(clocks);
}
pub fn enable(&self) {
self.registers.uartcr.modify(UARTCR::UARTEN::SET);
}
pub fn disable(&self) {
self.registers.uartcr.modify(UARTCR::UARTEN::CLEAR);
}
pub fn enable_transmit_interrupt(&self) {
self.registers.uartimsc.modify(UARTIMSC::TXIM::SET);
}
pub fn disable_transmit_interrupt(&self) {
self.registers.uartimsc.modify(UARTIMSC::TXIM::CLEAR);
}
pub fn enable_receive_interrupt(&self) {
self.registers.uartifls.modify(UARTIFLS::RXIFLSEL::FIFO_1_8);
self.registers.uartimsc.modify(UARTIMSC::RXIM::SET);
}
pub fn disable_receive_interrupt(&self) {
self.registers.uartimsc.modify(UARTIMSC::RXIM::CLEAR);
}
fn uart_is_writable(&self) -> bool {
!self.registers.uartfr.is_set(UARTFR::TXFF)
}
pub fn send_byte(&self, data: u8) {
while !self.uart_is_writable() {}
self.registers.uartdr.write(UARTDR::DATA.val(data as u32));
}
pub fn handle_interrupt(&self) {
if self.registers.uartimsc.is_set(UARTIMSC::TXIM) {
if self.registers.uartfr.is_set(UARTFR::TXFE) {
if self.tx_status.get() == UARTStateTX::Idle {
panic!("No data to transmit");
} else if self.tx_status.get() == UARTStateTX::Transmitting {
self.disable_transmit_interrupt();
if self.tx_position.get() < self.tx_len.get() {
self.fill_fifo();
self.enable_transmit_interrupt();
}
else {
self.tx_status.set(UARTStateTX::Idle);
self.tx_client.map(|client| {
self.tx_buffer.take().map(|buf| {
client.transmitted_buffer(buf, self.tx_position.get(), Ok(()));
});
});
}
}
}
}
if self.registers.uartimsc.is_set(UARTIMSC::RXIM) {
if self.registers.uartfr.is_set(UARTFR::RXFF) {
let byte = self.registers.uartdr.get() as u8;
self.disable_receive_interrupt();
if self.rx_status.get() == UARTStateRX::Receiving {
if self.rx_position.get() < self.rx_len.get() {
self.rx_buffer.map(|buf| {
buf[self.rx_position.get()] = byte;
self.rx_position.replace(self.rx_position.get() + 1);
});
}
if self.rx_position.get() == self.rx_len.get() {
self.rx_status.replace(UARTStateRX::Idle);
} else {
self.enable_receive_interrupt();
}
if self.rx_status.get() == UARTStateRX::Idle {
self.rx_client.map(|client| {
if let Some(buf) = self.rx_buffer.take() {
client.received_buffer(
buf,
self.rx_len.get(),
Ok(()),
hil::uart::Error::None,
);
}
});
}
}
}
}
}
fn fill_fifo(&self) {
while self.uart_is_writable() && self.tx_position.get() < self.tx_len.get() {
self.tx_buffer.map(|buf| {
self.registers
.uartdr
.set(buf[self.tx_position.get()].into());
self.tx_position.replace(self.tx_position.get() + 1);
});
}
}
pub fn is_configured(&self) -> bool {
self.registers.uartcr.is_set(UARTCR::UARTEN)
&& (self.registers.uartcr.is_set(UARTCR::RXE)
|| self.registers.uartcr.is_set(UARTCR::TXE))
}
}
impl DeferredCallClient for Uart<'_> {
fn register(&'static self) {
self.deferred_call.register(self)
}
fn handle_deferred_call(&self) {
if self.tx_status.get() == UARTStateTX::AbortRequested {
self.tx_client.map(|client| {
self.tx_buffer.take().map(|buf| {
client.transmitted_buffer(buf, self.tx_position.get(), Err(ErrorCode::CANCEL));
});
});
self.tx_status.set(UARTStateTX::Idle);
}
if self.rx_status.get() == UARTStateRX::AbortRequested {
self.rx_client.map(|client| {
self.rx_buffer.take().map(|buf| {
client.received_buffer(
buf,
self.rx_position.get(),
Err(ErrorCode::CANCEL),
hil::uart::Error::Aborted,
);
});
});
self.rx_status.set(UARTStateRX::Idle);
}
}
}
impl Configure for Uart<'_> {
fn configure(&self, params: Parameters) -> Result<(), ErrorCode> {
self.disable();
self.registers.uartlcr_h.modify(UARTLCR_H::FEN::CLEAR);
let clk = self.clocks.map_or(125_000_000, |clocks| {
clocks.get_frequency(clocks::Clock::Peripheral)
});
let baud_rate_div = 8 * clk / params.baud_rate;
let mut baud_ibrd = baud_rate_div >> 7;
let mut baud_fbrd = ((baud_rate_div & 0x7f) + 1) / 2;
if baud_ibrd == 0 {
baud_ibrd = 1;
baud_fbrd = 0;
} else if baud_ibrd >= 65535 {
baud_ibrd = 65535;
baud_fbrd = 0;
}
self.registers
.uartibrd
.write(UARTIBRD::BAUD_DIVINT.val(baud_ibrd));
self.registers
.uartfbrd
.write(UARTFBRD::BAUD_DIVFRAC.val(baud_fbrd));
self.registers.uartlcr_h.modify(UARTLCR_H::BRK::SET);
match params.width {
Width::Six => self.registers.uartlcr_h.modify(UARTLCR_H::WLEN::BITS_6),
Width::Seven => self.registers.uartlcr_h.modify(UARTLCR_H::WLEN::BITS_7),
Width::Eight => self.registers.uartlcr_h.modify(UARTLCR_H::WLEN::BITS_8),
}
match params.parity {
Parity::None => {
self.registers.uartlcr_h.modify(UARTLCR_H::PEN::CLEAR);
self.registers.uartlcr_h.modify(UARTLCR_H::EPS::CLEAR);
}
Parity::Odd => {
self.registers.uartlcr_h.modify(UARTLCR_H::PEN::SET);
self.registers.uartlcr_h.modify(UARTLCR_H::EPS::CLEAR);
}
Parity::Even => {
self.registers.uartlcr_h.modify(UARTLCR_H::PEN::SET);
self.registers.uartlcr_h.modify(UARTLCR_H::EPS::SET);
}
}
match params.stop_bits {
StopBits::One => self.registers.uartlcr_h.modify(UARTLCR_H::STP2::CLEAR),
StopBits::Two => self.registers.uartlcr_h.modify(UARTLCR_H::STP2::SET),
}
if params.hw_flow_control {
self.registers.uartcr.modify(UARTCR::RTSEN::SET);
self.registers.uartcr.modify(UARTCR::CTSEN::SET);
} else {
self.registers.uartcr.modify(UARTCR::RTSEN::CLEAR);
self.registers.uartcr.modify(UARTCR::CTSEN::CLEAR);
}
self.registers.uartlcr_h.modify(UARTLCR_H::BRK::CLEAR);
self.registers.uartlcr_h.modify(UARTLCR_H::FEN::CLEAR);
self.registers
.uartcr
.modify(UARTCR::UARTEN::SET + UARTCR::TXE::SET + UARTCR::RXE::SET);
self.registers
.uartdmacr
.write(UARTDMACR::TXDMAE::SET + UARTDMACR::RXDMAE::SET);
Ok(())
}
}
impl<'a> Transmit<'a> for Uart<'a> {
fn set_transmit_client(&self, client: &'a dyn TransmitClient) {
self.tx_client.set(client);
}
fn transmit_buffer(
&self,
tx_buffer: &'static mut [u8],
tx_len: usize,
) -> Result<(), (ErrorCode, &'static mut [u8])> {
if self.tx_status.get() == UARTStateTX::Idle {
if tx_len <= tx_buffer.len() {
self.tx_buffer.put(Some(tx_buffer));
self.tx_position.set(0);
self.tx_len.set(tx_len);
self.tx_status.set(UARTStateTX::Transmitting);
self.enable_transmit_interrupt();
self.fill_fifo();
Ok(())
} else {
Err((ErrorCode::SIZE, tx_buffer))
}
} else {
Err((ErrorCode::BUSY, tx_buffer))
}
}
fn transmit_word(&self, _word: u32) -> Result<(), ErrorCode> {
Err(ErrorCode::FAIL)
}
fn transmit_abort(&self) -> Result<(), ErrorCode> {
if self.tx_status.get() != UARTStateTX::Idle {
self.disable_transmit_interrupt();
self.tx_status.set(UARTStateTX::AbortRequested);
self.deferred_call.set();
Err(ErrorCode::BUSY)
} else {
Ok(())
}
}
}
impl<'a> Receive<'a> for Uart<'a> {
fn set_receive_client(&self, client: &'a dyn ReceiveClient) {
self.rx_client.set(client);
}
fn receive_buffer(
&self,
rx_buffer: &'static mut [u8],
rx_len: usize,
) -> Result<(), (ErrorCode, &'static mut [u8])> {
if self.rx_status.get() == UARTStateRX::Idle {
if rx_len <= rx_buffer.len() {
self.rx_buffer.put(Some(rx_buffer));
self.rx_position.set(0);
self.rx_len.set(rx_len);
self.rx_status.set(UARTStateRX::Receiving);
self.enable_receive_interrupt();
Ok(())
} else {
Err((ErrorCode::SIZE, rx_buffer))
}
} else {
Err((ErrorCode::BUSY, rx_buffer))
}
}
fn receive_word(&self) -> Result<(), ErrorCode> {
Err(ErrorCode::FAIL)
}
fn receive_abort(&self) -> Result<(), ErrorCode> {
if self.rx_status.get() != UARTStateRX::Idle {
self.disable_receive_interrupt();
self.rx_status.set(UARTStateRX::AbortRequested);
self.deferred_call.set();
Err(ErrorCode::BUSY)
} else {
Ok(())
}
}
}