Skip to content

Add serial is_rxne is_idle is_txe #360

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Aug 11, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -149,3 +149,8 @@ required-features = ["has-can", "rt"]
[[example]]
name = "gpio_input"
required-features = ["stm32f103"]

[[example]]
name = "serial-interrupt-idle"
required-features = ["stm32f103", "rt", "medium"]
default-target = "thumbv7m-none-eabi"
102 changes: 102 additions & 0 deletions examples/serial-interrupt-idle.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
//! Serial interface loopback test
//!
//! You have to short the TX and RX pins to make this program work

#![no_main]
#![no_std]

use panic_halt as _;

use cortex_m_rt::entry;
use stm32f1xx_hal::{
pac,
pac::interrupt,
pac::USART1,
prelude::*,
serial::{Config, Rx, Serial, Tx},
};

static mut RX: Option<Rx<USART1>> = None;
static mut TX: Option<Tx<USART1>> = None;
#[entry]
fn main() -> ! {
// Get access to the device specific peripherals from the peripheral access crate
let p = pac::Peripherals::take().unwrap();

// Take ownership over the raw flash and rcc devices and convert them into the corresponding
// HAL structs
let mut flash = p.FLASH.constrain();
let rcc = p.RCC.constrain();

// Freeze the configuration of all the clocks in the system and store the frozen frequencies in
// `clocks`
let clocks = rcc.cfgr.freeze(&mut flash.acr);

// Prepare the alternate function I/O registers
let mut afio = p.AFIO.constrain();

// Prepare the GPIOB peripheral
let mut gpiob = p.GPIOB.split();

// USART1
let tx = gpiob.pb6.into_alternate_push_pull(&mut gpiob.crl);
let rx = gpiob.pb7;

// Set up the usart device. Taks ownership over the USART register and tx/rx pins. The rest of
// the registers are used to enable and configure the device.
let (mut tx, mut rx) = Serial::usart1(
p.USART1,
(tx, rx),
&mut afio.mapr,
Config::default().baudrate(115200.bps()),
clocks,
)
.split();
tx.listen();
rx.listen();
rx.listen_idle();

cortex_m::interrupt::free(|_| unsafe {
TX.replace(tx);
RX.replace(rx);
});
unsafe {
cortex_m::peripheral::NVIC::unmask(pac::Interrupt::USART1);
}

loop {
cortex_m::asm::wfi()
}
}
const BUFFER_LEN: usize = 4096;
static mut BUFFER: &mut [u8; BUFFER_LEN] = &mut [0; BUFFER_LEN];
static mut WIDX: usize = 0;

unsafe fn write(buf: &[u8]) {
if let Some(tx) = TX.as_mut() {
buf.iter()
.for_each(|w| if let Err(_err) = nb::block!(tx.write(*w)) {})
}
}
#[interrupt]
unsafe fn USART1() {
cortex_m::interrupt::free(|_| {
if let Some(rx) = RX.as_mut() {
if rx.is_rxne() {
if let Ok(w) = nb::block!(rx.read()) {
BUFFER[WIDX] = w;
WIDX += 1;
if WIDX >= BUFFER_LEN - 1 {
write(&BUFFER[..]);
WIDX = 0;
}
}
rx.listen_idle();
} else if rx.is_idle() {
rx.unlisten_idle();
write(&BUFFER[0..WIDX]);
WIDX = 0;
}
}
})
}
35 changes: 35 additions & 0 deletions src/serial.rs
Original file line number Diff line number Diff line change
Expand Up @@ -342,6 +342,21 @@ where
}
}

/// Return true if the line idle status is set
pub fn is_idle(&self) -> bool {
self.usart.sr.read().idle().bit_is_set()
}

/// Return true if the tx register is empty (and can accept data)
pub fn is_txe(&self) -> bool {
self.usart.sr.read().txe().bit_is_set()
}

/// Return true if the rx register is not empty (and can be read)
pub fn is_rxne(&self) -> bool {
self.usart.sr.read().rxne().bit_is_set()
}

/// Returns ownership of the borrowed register handles
pub fn release(self) -> (USART, PINS) {
(self.usart, self.pins)
Expand Down Expand Up @@ -418,6 +433,10 @@ macro_rules! hal {
pub fn unlisten(&mut self) {
unsafe { (*$USARTX::ptr()).cr1.modify(|_, w| w.txeie().clear_bit()) };
}

pub fn is_txe(&self) -> bool {
unsafe { (*$USARTX::ptr()).sr.read().txe().bit_is_set() }
}
}

impl Rx<$USARTX> {
Expand All @@ -428,6 +447,22 @@ macro_rules! hal {
pub fn unlisten(&mut self) {
unsafe { (*$USARTX::ptr()).cr1.modify(|_, w| w.rxneie().clear_bit()) };
}

pub fn listen_idle(&mut self) {
unsafe { (*$USARTX::ptr()).cr1.modify(|_, w| w.idleie().set_bit()) };
}

pub fn unlisten_idle(&mut self) {
unsafe { (*$USARTX::ptr()).cr1.modify(|_, w| w.idleie().clear_bit()) };
}

pub fn is_idle(&self) -> bool {
unsafe { (*$USARTX::ptr()).sr.read().idle().bit_is_set() }
}

pub fn is_rxne(&self) -> bool {
unsafe { (*$USARTX::ptr()).sr.read().rxne().bit_is_set() }
}
}

impl crate::hal::serial::Read<u8> for Rx<$USARTX> {
Expand Down