mirror of
https://github.com/esp-rs/esp-hal.git
synced 2025-10-02 06:40:47 +00:00
Extract UART peripheral implementation, prelude into esp-hal-common
This commit is contained in:
parent
dfab5d6c1b
commit
579c5ba71b
@ -7,6 +7,9 @@ pub use esp32c3 as pac;
|
|||||||
#[cfg(feature = "esp32s2")]
|
#[cfg(feature = "esp32s2")]
|
||||||
pub use esp32s2 as pac;
|
pub use esp32s2 as pac;
|
||||||
|
|
||||||
|
pub mod prelude;
|
||||||
|
pub mod serial;
|
||||||
pub mod timer;
|
pub mod timer;
|
||||||
|
|
||||||
|
pub use serial::Serial;
|
||||||
pub use timer::Timer;
|
pub use timer::Timer;
|
||||||
|
@ -1,15 +1,8 @@
|
|||||||
//! UART Functionality (UART)
|
|
||||||
//!
|
|
||||||
//! Reference: ESP32-C3 TRM v0.3 Section 20 (as TRM)
|
|
||||||
//!
|
|
||||||
//! The ESP32-C3 has two identical UART groups UART0 and UART1.
|
|
||||||
//!
|
|
||||||
//! TODO:
|
|
||||||
//! - Interrupt support
|
|
||||||
|
|
||||||
use embedded_hal::serial::{Read, Write};
|
use embedded_hal::serial::{Read, Write};
|
||||||
|
|
||||||
use crate::pac::{uart0::RegisterBlock, UART0, UART1, UART2};
|
#[cfg(feature = "enable-esp32")]
|
||||||
|
use crate::pac::UART2;
|
||||||
|
use crate::pac::{uart0::RegisterBlock, UART0, UART1};
|
||||||
|
|
||||||
const UART_FIFO_SIZE: u16 = 128;
|
const UART_FIFO_SIZE: u16 = 128;
|
||||||
|
|
||||||
@ -96,12 +89,22 @@ pub trait Instance {
|
|||||||
|
|
||||||
/// Check if the UART TX statemachine is is idle
|
/// Check if the UART TX statemachine is is idle
|
||||||
fn is_tx_idle(&mut self) -> bool {
|
fn is_tx_idle(&mut self) -> bool {
|
||||||
self.as_uart0().status.read().st_utx_out().bits() == 0x0u8
|
#[cfg(feature = "enable-esp32")]
|
||||||
|
let ret = self.as_uart0().status.read().st_utx_out().bits() == 0x0u8;
|
||||||
|
#[cfg(not(feature = "enable-esp32"))]
|
||||||
|
let ret = self.as_uart0().fsm_status.read().st_utx_out().bits() == 0x0u8;
|
||||||
|
|
||||||
|
ret
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Check if the UART RX statemachine is is idle
|
/// Check if the UART RX statemachine is is idle
|
||||||
fn is_rx_idle(&mut self) -> bool {
|
fn is_rx_idle(&mut self) -> bool {
|
||||||
self.as_uart0().status.read().st_urx_out().bits() == 0x0u8
|
#[cfg(feature = "enable-esp32")]
|
||||||
|
let ret = self.as_uart0().status.read().st_urx_out().bits() == 0x0u8;
|
||||||
|
#[cfg(not(feature = "enable-esp32"))]
|
||||||
|
let ret = self.as_uart0().fsm_status.read().st_urx_out().bits() == 0x0u8;
|
||||||
|
|
||||||
|
ret
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -171,6 +174,7 @@ impl Instance for UART1 {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "enable-esp32")]
|
||||||
/// Specific instance implementation for the UART2 peripheral
|
/// Specific instance implementation for the UART2 peripheral
|
||||||
impl Instance for UART2 {
|
impl Instance for UART2 {
|
||||||
#[inline(always)]
|
#[inline(always)]
|
@ -2,12 +2,7 @@
|
|||||||
|
|
||||||
pub use embedded_hal as ehal;
|
pub use embedded_hal as ehal;
|
||||||
pub use esp32 as pac;
|
pub use esp32 as pac;
|
||||||
pub use esp_hal_common::Timer;
|
pub use esp_hal_common::{prelude, Serial, Timer};
|
||||||
|
|
||||||
pub mod prelude;
|
|
||||||
pub mod serial;
|
|
||||||
|
|
||||||
pub use serial::Serial;
|
|
||||||
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
extern "C" fn DefaultHandler(_level: u32, _interrupt: pac::Interrupt) {}
|
extern "C" fn DefaultHandler(_level: u32, _interrupt: pac::Interrupt) {}
|
||||||
|
@ -2,11 +2,8 @@
|
|||||||
|
|
||||||
pub use embedded_hal as ehal;
|
pub use embedded_hal as ehal;
|
||||||
pub use esp32c3 as pac;
|
pub use esp32c3 as pac;
|
||||||
pub use esp_hal_common::Timer;
|
pub use esp_hal_common::{prelude, Serial, Timer};
|
||||||
|
|
||||||
pub mod prelude;
|
|
||||||
pub mod rtc_cntl;
|
pub mod rtc_cntl;
|
||||||
pub mod serial;
|
|
||||||
|
|
||||||
pub use rtc_cntl::RtcCntl;
|
pub use rtc_cntl::RtcCntl;
|
||||||
pub use serial::Serial;
|
|
||||||
|
@ -1,9 +0,0 @@
|
|||||||
pub use embedded_hal::{
|
|
||||||
digital::v2::{
|
|
||||||
InputPin as _,
|
|
||||||
OutputPin as _,
|
|
||||||
StatefulOutputPin as _,
|
|
||||||
ToggleableOutputPin as _,
|
|
||||||
},
|
|
||||||
prelude::*,
|
|
||||||
};
|
|
@ -1,171 +0,0 @@
|
|||||||
//! UART Functionality (UART)
|
|
||||||
//!
|
|
||||||
//! Reference: ESP32-C3 TRM v0.3 Section 20 (as TRM)
|
|
||||||
//!
|
|
||||||
//! The ESP32-C3 has two identical UART groups UART0 and UART1.
|
|
||||||
//!
|
|
||||||
//! TODO:
|
|
||||||
//! - Interrupt support
|
|
||||||
|
|
||||||
use embedded_hal::serial::{Read, Write};
|
|
||||||
|
|
||||||
use crate::pac::{uart0::RegisterBlock, UART0, UART1};
|
|
||||||
|
|
||||||
const UART_FIFO_SIZE: u16 = 128;
|
|
||||||
|
|
||||||
/// UART-specific errors
|
|
||||||
#[derive(Debug)]
|
|
||||||
pub enum Error {}
|
|
||||||
|
|
||||||
/// UART peripheral (UART)
|
|
||||||
pub struct Serial<T> {
|
|
||||||
uart: T,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T: Instance> Serial<T> {
|
|
||||||
pub fn new(uart: T) -> Result<Self, Error> {
|
|
||||||
let mut serial = Serial { uart };
|
|
||||||
serial.uart.disable_rx_interrupts();
|
|
||||||
serial.uart.disable_tx_interrupts();
|
|
||||||
Ok(serial)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub trait Instance {
|
|
||||||
/// Return registerblock of uart instance as if it were UART0
|
|
||||||
fn as_uart0(&self) -> &RegisterBlock;
|
|
||||||
|
|
||||||
/// Clear and disable all tx-related interrupts
|
|
||||||
fn disable_tx_interrupts(&mut self) {
|
|
||||||
// Disable UART TX interrupts
|
|
||||||
self.as_uart0().int_clr.write(|w| {
|
|
||||||
w.txfifo_empty_int_clr()
|
|
||||||
.set_bit()
|
|
||||||
.tx_brk_done_int_clr()
|
|
||||||
.set_bit()
|
|
||||||
.tx_brk_idle_done_int_clr()
|
|
||||||
.set_bit()
|
|
||||||
.tx_done_int_clr()
|
|
||||||
.set_bit()
|
|
||||||
});
|
|
||||||
|
|
||||||
self.as_uart0().int_ena.write(|w| {
|
|
||||||
w.txfifo_empty_int_ena()
|
|
||||||
.clear_bit()
|
|
||||||
.tx_brk_done_int_ena()
|
|
||||||
.clear_bit()
|
|
||||||
.tx_brk_idle_done_int_ena()
|
|
||||||
.clear_bit()
|
|
||||||
.tx_done_int_ena()
|
|
||||||
.clear_bit()
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Clear and disable all rx-related interrupts
|
|
||||||
fn disable_rx_interrupts(&mut self) {
|
|
||||||
// Disable UART RX interrupts
|
|
||||||
self.as_uart0().int_clr.write(|w| {
|
|
||||||
w.rxfifo_full_int_clr()
|
|
||||||
.set_bit()
|
|
||||||
.rxfifo_ovf_int_clr()
|
|
||||||
.set_bit()
|
|
||||||
.rxfifo_tout_int_clr()
|
|
||||||
.set_bit()
|
|
||||||
});
|
|
||||||
|
|
||||||
self.as_uart0().int_ena.write(|w| {
|
|
||||||
w.rxfifo_full_int_ena()
|
|
||||||
.clear_bit()
|
|
||||||
.rxfifo_ovf_int_ena()
|
|
||||||
.clear_bit()
|
|
||||||
.rxfifo_tout_int_ena()
|
|
||||||
.clear_bit()
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Get the number of occupied entries in the tx fifo buffer
|
|
||||||
fn get_tx_fifo_count(&mut self) -> u16 {
|
|
||||||
self.as_uart0().status.read().txfifo_cnt().bits()
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Get the number of occupied entries in the rx fifo buffer
|
|
||||||
fn get_rx_fifo_count(&mut self) -> u16 {
|
|
||||||
self.as_uart0().status.read().rxfifo_cnt().bits()
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Check if the UART TX statemachine is is idle
|
|
||||||
fn is_tx_idle(&mut self) -> bool {
|
|
||||||
self.as_uart0().fsm_status.read().st_utx_out().bits() == 0x0u8
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Check if the UART RX statemachine is is idle
|
|
||||||
fn is_rx_idle(&mut self) -> bool {
|
|
||||||
self.as_uart0().fsm_status.read().st_urx_out().bits() == 0x0u8
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Write half of a serial interface
|
|
||||||
impl<T: Instance> Write<u8> for Serial<T> {
|
|
||||||
type Error = Error;
|
|
||||||
|
|
||||||
/// Writes a single word to the serial interface
|
|
||||||
fn write(&mut self, word: u8) -> nb::Result<(), Self::Error> {
|
|
||||||
if self.uart.get_tx_fifo_count() >= UART_FIFO_SIZE {
|
|
||||||
Err(nb::Error::WouldBlock)
|
|
||||||
} else {
|
|
||||||
self.uart
|
|
||||||
.as_uart0()
|
|
||||||
.fifo
|
|
||||||
.write(|w| unsafe { w.rxfifo_rd_byte().bits(word) });
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Ensures that none of the previously written words are still buffered
|
|
||||||
fn flush(&mut self) -> nb::Result<(), Self::Error> {
|
|
||||||
if self.uart.is_tx_idle() {
|
|
||||||
Ok(())
|
|
||||||
} else {
|
|
||||||
Err(nb::Error::WouldBlock)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Write half of a serial interface
|
|
||||||
impl<T: Instance> Read<u8> for Serial<T> {
|
|
||||||
type Error = Error;
|
|
||||||
|
|
||||||
/// Reads a single word from the serial interface
|
|
||||||
fn read(&mut self) -> nb::Result<u8, Self::Error> {
|
|
||||||
if self.uart.get_rx_fifo_count() > 0 {
|
|
||||||
Ok(self.uart.as_uart0().fifo.read().rxfifo_rd_byte().bits())
|
|
||||||
} else {
|
|
||||||
Err(nb::Error::WouldBlock)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T: Instance> core::fmt::Write for Serial<T> {
|
|
||||||
fn write_str(&mut self, s: &str) -> core::fmt::Result {
|
|
||||||
s.as_bytes()
|
|
||||||
.iter()
|
|
||||||
.try_for_each(|c| nb::block!(self.write(*c)))
|
|
||||||
.map_err(|_| core::fmt::Error)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Specific instance implementation for the UART0 peripheral
|
|
||||||
impl Instance for UART0 {
|
|
||||||
#[inline(always)]
|
|
||||||
fn as_uart0(&self) -> &RegisterBlock {
|
|
||||||
self
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Specific instance implementation for the UART1 peripheral
|
|
||||||
impl Instance for UART1 {
|
|
||||||
#[inline(always)]
|
|
||||||
fn as_uart0(&self) -> &RegisterBlock {
|
|
||||||
self
|
|
||||||
}
|
|
||||||
}
|
|
Loading…
x
Reference in New Issue
Block a user