Skip to content
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

Serial changes v3 #417

Merged
merged 9 commits into from
Mar 10, 2022
12 changes: 12 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,18 @@ and this project adheres to [Semantic Versioning](http://semver.org/).

- `gpio`: port and pin generics first, then mode, `PinMode` for modes instead of pins, other cleanups

### Breaking changes

- Passing the `Clock` parameter to `Serial` by reference.
- `Serial::usart1/2/3` -> `Serial::new`.
- `Serial` implements `Write<WORD>` and `Read<WORD>` for `WORD` simultaneously as u8 and u16.

### Added

- Allow access to the `Tx` and `Rx` parts of the `Serial` without the need for splitting.
- Allow `Serial` reconfiguration by references to the `Tx` and `Rx` parts.
- Allow `Serial` release after splitting.

## [v0.9.0] - 2022-03-02

### Added
Expand Down
1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ heapless = "0.7.10"
mfrc522 = "0.2.0"
usb-device = "0.2.8"
usbd-serial = "0.1.1"
unwrap-infallible = "0.1.5"

[features]
device-selected = []
Expand Down
6 changes: 3 additions & 3 deletions examples/serial-dma-circ.rs
Original file line number Diff line number Diff line change
Expand Up @@ -48,15 +48,15 @@ fn main() -> ! {
// let tx = gpiob.pb10.into_alternate_push_pull(&mut gpiob.crh);
// let rx = gpiob.pb11;

let serial = Serial::usart1(
let serial = Serial::new(
p.USART1,
(tx, rx),
&mut afio.mapr,
Config::default().baudrate(9_600.bps()),
clocks,
&clocks,
);

let rx = serial.split().1.with_dma(channels.5);
let rx = serial.rx.with_dma(channels.5);
let buf = singleton!(: [[u8; 8]; 2] = [[0; 8]; 2]).unwrap();

let mut circ_buffer = rx.circ_read(buf);
Expand Down
6 changes: 3 additions & 3 deletions examples/serial-dma-peek.rs
Original file line number Diff line number Diff line change
Expand Up @@ -47,15 +47,15 @@ fn main() -> ! {
// let tx = gpiob.pb10.into_alternate_push_pull(&mut gpiob.crh);
// let rx = gpiob.pb11;

let serial = Serial::usart1(
let serial = Serial::new(
p.USART1,
(tx, rx),
&mut afio.mapr,
Config::default(),
clocks,
&clocks,
);

let rx = serial.split().1.with_dma(channels.5);
let rx = serial.rx.with_dma(channels.5);
let buf = singleton!(: [u8; 8] = [0; 8]).unwrap();

let t = rx.read(buf);
Expand Down
6 changes: 3 additions & 3 deletions examples/serial-dma-rx.rs
Original file line number Diff line number Diff line change
Expand Up @@ -47,15 +47,15 @@ fn main() -> ! {
// let tx = gpiob.pb10.into_alternate_push_pull(&mut gpiob.crh);
// let rx = gpiob.pb11;

let serial = Serial::usart1(
let serial = Serial::new(
p.USART1,
(tx, rx),
&mut afio.mapr,
Config::default().baudrate(9_600.bps()),
clocks,
&clocks,
);

let rx = serial.split().1.with_dma(channels.5);
let rx = serial.rx.with_dma(channels.5);
let buf = singleton!(: [u8; 8] = [0; 8]).unwrap();

let (_buf, _rx) = rx.read(buf).wait();
Expand Down
6 changes: 3 additions & 3 deletions examples/serial-dma-tx.rs
Original file line number Diff line number Diff line change
Expand Up @@ -47,15 +47,15 @@ fn main() -> ! {
// let tx = gpiob.pb10.into_alternate_push_pull(&mut gpiob.crh);
// let rx = gpiob.pb11;

let serial = Serial::usart1(
let serial = Serial::new(
p.USART1,
(tx, rx),
&mut afio.mapr,
Config::default().baudrate(9600.bps()),
clocks,
&clocks,
);

let tx = serial.split().0.with_dma(channels.4);
let tx = serial.tx.with_dma(channels.4);

let (_, tx) = tx.write(b"The quick brown fox").wait();

Expand Down
6 changes: 3 additions & 3 deletions examples/serial-fmt.rs
Original file line number Diff line number Diff line change
Expand Up @@ -57,14 +57,14 @@ fn main() -> ! {
// Take ownership over pb11
let rx = gpiob.pb11;

// Set up the usart device. Taks ownership over the USART register and tx/rx pins. The rest of
// Set up the usart device. Take ownership over the USART register and tx/rx pins. The rest of
// the registers are used to enable and configure the device.
let serial = Serial::usart3(
let serial = Serial::new(
p.USART3,
(tx, rx),
&mut afio.mapr,
Config::default().baudrate(9600.bps()),
clocks,
&clocks,
);

// Split the serial struct into a receiving and a transmitting part
Expand Down
13 changes: 7 additions & 6 deletions examples/serial.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ use stm32f1xx_hal::{
prelude::*,
serial::{Config, Serial},
};
use unwrap_infallible::UnwrapInfallible;

#[entry]
fn main() -> ! {
Expand Down Expand Up @@ -58,22 +59,22 @@ fn main() -> ! {
// Take ownership over pb11
let rx = gpiob.pb11;

// Set up the usart device. Taks ownership over the USART register and tx/rx pins. The rest of
// Set up the usart device. Take ownership over the USART register and tx/rx pins. The rest of
// the registers are used to enable and configure the device.
let mut serial = Serial::usart3(
let mut serial = Serial::new(
p.USART3,
(tx, rx),
&mut afio.mapr,
Config::default().baudrate(9600.bps()),
clocks,
&clocks,
);

// Loopback test. Write `X` and wait until the write is successful.
let sent = b'X';
block!(serial.write(sent)).ok();
block!(serial.tx.write(sent)).unwrap_infallible();

// Read the byte that was just sent. Blocks until the read is complete
let received = block!(serial.read()).unwrap();
let received = block!(serial.rx.read()).unwrap();

// Since we have connected tx and rx, the byte we sent should be the one we received
assert_eq!(received, sent);
Expand All @@ -84,7 +85,7 @@ fn main() -> ! {
// You can also split the serial struct into a receiving and a transmitting part
let (mut tx, mut rx) = serial.split();
let sent = b'Y';
block!(tx.write(sent)).ok();
block!(tx.write(sent)).unwrap_infallible();
let received = block!(rx.read()).unwrap();
assert_eq!(received, sent);
asm::bkpt();
Expand Down
39 changes: 20 additions & 19 deletions examples/serial_9bits.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,16 @@
#![no_main]
#![no_std]

use core::convert::Infallible;
use cortex_m_rt::entry;
use nb::block;
use panic_halt as _;
use stm32f1xx_hal::{
pac,
prelude::*,
serial::{Config, Rx3_16, Serial, Tx3_16},
serial::{self, Config, Serial},
};
use unwrap_infallible::UnwrapInfallible;

// The address of the slave device.
const SLAVE_ADDR: u8 = 123;
Expand All @@ -25,7 +27,10 @@ const SLAVE_ADDR: u8 = 123;
const MSG_MAX_LEN: usize = u8::MAX as usize;

// Receives a message addressed to the slave device. Returns the size of the received message.
fn receive_msg(serial_rx: &mut Rx3_16, buf: &mut [u8; MSG_MAX_LEN]) -> usize {
fn receive_msg<RX>(serial_rx: &mut RX, buf: &mut [u8; MSG_MAX_LEN]) -> usize
where
RX: embedded_hal::serial::Read<u16, Error = serial::Error>,
{
enum RxPhase {
Start,
Length,
Expand Down Expand Up @@ -72,24 +77,22 @@ fn receive_msg(serial_rx: &mut Rx3_16, buf: &mut [u8; MSG_MAX_LEN]) -> usize {
}

// Send message.
fn send_msg(mut serial_tx: Tx3_16, msg: &[u8]) -> Tx3_16 {
fn send_msg<TX>(serial_tx: &mut TX, msg: &[u8])
where
TX: embedded_hal::serial::Write<u8, Error = Infallible>
+ embedded_hal::serial::Write<u16, Error = Infallible>,
{
// Send address.
block!(serial_tx.write(SLAVE_ADDR as u16 | 0x100)).ok();

// Switching from u16 to u8 data.
let mut serial_tx = serial_tx.with_u8_data();
block!(serial_tx.write(SLAVE_ADDR as u16 | 0x100)).unwrap_infallible();

// Send message len.
assert!(msg.len() <= MSG_MAX_LEN);
block!(serial_tx.write(msg.len() as u8)).ok();
block!(serial_tx.write(msg.len() as u8)).unwrap_infallible();

// Send message.
for &b in msg {
block!(serial_tx.write(b)).ok();
block!(serial_tx.write(b)).unwrap_infallible();
}

// Switching back from u8 to u16 data.
serial_tx.with_u16_data()
}

#[entry]
Expand All @@ -115,20 +118,18 @@ fn main() -> ! {
let tx_pin = gpiob.pb10.into_alternate_push_pull(&mut gpiob.crh);
let rx_pin = gpiob.pb11;

// Set up the usart device. Taks ownership over the USART register and tx/rx pins. The rest of
// Set up the usart device. Take ownership over the USART register and tx/rx pins. The rest of
// the registers are used to enable and configure the device.
let serial = Serial::usart3(
let serial = Serial::new(
p.USART3,
(tx_pin, rx_pin),
&mut afio.mapr,
Config::default()
.baudrate(9600.bps())
.wordlength_9bits()
.parity_none(),
clocks,
)
// Switching the 'Word' type parameter for the 'Read' and 'Write' traits from u8 to u16.
.with_u16_data();
&clocks,
);

// Split the serial struct into a transmitting and a receiving part.
let (mut serial_tx, mut serial_rx) = serial.split();
Expand All @@ -140,6 +141,6 @@ fn main() -> ! {
// Receive message from master device.
let received_msg_len = receive_msg(&mut serial_rx, &mut buf);
// Send the received message back.
serial_tx = send_msg(serial_tx, &buf[..received_msg_len]);
send_msg(&mut serial_tx, &buf[..received_msg_len]);
}
}
11 changes: 6 additions & 5 deletions examples/serial_config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ use stm32f1xx_hal::{
prelude::*,
serial::{self, Serial},
};
use unwrap_infallible::UnwrapInfallible;

#[entry]
fn main() -> ! {
Expand Down Expand Up @@ -56,9 +57,9 @@ fn main() -> ! {
// Take ownership over pb11
let rx = gpiob.pb11;

// Set up the usart device. Taks ownership over the USART register and tx/rx pins. The rest of
// Set up the usart device. Take ownership over the USART register and tx/rx pins. The rest of
// the registers are used to enable and configure the device.
let serial = Serial::usart3(
let serial = Serial::new(
p.USART3,
(tx, rx),
&mut afio.mapr,
Expand All @@ -67,15 +68,15 @@ fn main() -> ! {
.stopbits(serial::StopBits::STOP2)
.wordlength_9bits()
.parity_odd(),
clocks,
&clocks,
);

// Split the serial struct into a receiving and a transmitting part
let (mut tx, _rx) = serial.split();

let sent = b'U';
block!(tx.write(sent)).ok();
block!(tx.write(sent)).ok();
block!(tx.write(sent)).unwrap_infallible();
block!(tx.write(sent)).unwrap_infallible();

loop {}
}
29 changes: 20 additions & 9 deletions examples/serial_reconfigure.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,9 @@ use cortex_m_rt::entry;
use stm32f1xx_hal::{
pac,
prelude::*,
serial::{Config, Serial},
serial::{self, Config, Serial},
};
use unwrap_infallible::UnwrapInfallible;

#[entry]
fn main() -> ! {
Expand Down Expand Up @@ -58,22 +59,22 @@ fn main() -> ! {
// Take ownership over pb11
let rx = gpiob.pb11;

// Set up the usart device. Taks ownership over the USART register and tx/rx pins. The rest of
// Set up the usart device. Take ownership over the USART register and tx/rx pins. The rest of
// the registers are used to enable and configure the device.
let mut serial = Serial::usart3(
let mut serial = Serial::new(
p.USART3,
(tx, rx),
&mut afio.mapr,
Config::default().baudrate(9600.bps()),
clocks,
&clocks,
);

// Loopback test. Write `X` and wait until the write is successful.
let sent = b'X';
block!(serial.write(sent)).ok();
block!(serial.tx.write(sent)).unwrap_infallible();

// Read the byte that was just sent. Blocks until the read is complete
let received = block!(serial.read()).unwrap();
let received = block!(serial.rx.read()).unwrap();

// Since we have connected tx and rx, the byte we sent should be the one we received
assert_eq!(received, sent);
Expand All @@ -83,14 +84,24 @@ fn main() -> ! {

// You can reconfigure the serial port to use a different baud rate at runtime.
// This may block for a while if the transmission is still in progress.
block!(serial.reconfigure(Config::default().baudrate(115_200.bps()), clocks)).unwrap();
block!(serial.reconfigure(Config::default().baudrate(115_200.bps()), &clocks)).unwrap();

// Let's see if it works.'
let sent = b'Y';
block!(serial.write(sent)).ok();
let received = block!(serial.read()).unwrap();
block!(serial.tx.write(sent)).unwrap_infallible();
let received = block!(serial.rx.read()).unwrap();
assert_eq!(received, sent);
asm::bkpt();

// You can reconfigure the serial port after split.
let (mut tx, mut rx) = serial.split();
block!(serial::reconfigure(
&mut tx,
&mut rx,
Config::default().baudrate(9600.bps()),
&clocks
))
.unwrap();

loop {}
}
Loading