Merge branch 'main' of https://github.com/embassy-rs/embassy into rtc-lp

This commit is contained in:
xoviat
2023-08-22 16:58:43 -05:00
145 changed files with 3933 additions and 1276 deletions

View File

@ -40,9 +40,9 @@ embassy-net-driver = { version = "0.1.0", path = "../embassy-net-driver" }
embassy-usb-driver = {version = "0.1.0", path = "../embassy-usb-driver", optional = true }
embedded-hal-02 = { package = "embedded-hal", version = "0.2.6", features = ["unproven"] }
embedded-hal-1 = { package = "embedded-hal", version = "=1.0.0-alpha.11", optional = true}
embedded-hal-async = { version = "=0.2.0-alpha.2", optional = true}
embedded-hal-nb = { version = "=1.0.0-alpha.3", optional = true}
embedded-hal-1 = { package = "embedded-hal", version = "=1.0.0-rc.1", optional = true}
embedded-hal-async = { version = "=1.0.0-rc.1", optional = true}
embedded-hal-nb = { version = "=1.0.0-rc.1", optional = true}
embedded-storage = "0.3.0"
embedded-storage-async = { version = "0.4.0", optional = true }
@ -57,7 +57,7 @@ sdio-host = "0.5.0"
embedded-sdmmc = { git = "https://github.com/embassy-rs/embedded-sdmmc-rs", rev = "a4f293d3a6f72158385f79c98634cb8a14d0d2fc", optional = true }
critical-section = "1.1"
atomic-polyfill = "1.0.1"
stm32-metapac = { git = "https://github.com/embassy-rs/stm32-data-generated", tag = "stm32-data-82a24863823a3daf0ca664c7fdf008379d0a0d42" }
stm32-metapac = { git = "https://github.com/embassy-rs/stm32-data-generated", tag = "stm32-data-2b87e34c661e19ff6dc603fabfe7fe99ab7261f7" }
vcell = "0.1.3"
bxcan = "0.7.0"
nb = "1.0.0"
@ -76,7 +76,7 @@ critical-section = { version = "1.1", features = ["std"] }
[build-dependencies]
proc-macro2 = "1.0.36"
quote = "1.0.15"
stm32-metapac = { git = "https://github.com/embassy-rs/stm32-data-generated", tag = "stm32-data-82a24863823a3daf0ca664c7fdf008379d0a0d42", default-features = false, features = ["metadata"]}
stm32-metapac = { git = "https://github.com/embassy-rs/stm32-data-generated", tag = "stm32-data-2b87e34c661e19ff6dc603fabfe7fe99ab7261f7", default-features = false, features = ["metadata"]}
[features]
default = ["rt"]

View File

@ -310,7 +310,11 @@ fn main() {
for p in METADATA.peripherals {
// generating RccPeripheral impl for H7 ADC3 would result in bad frequency
if !singletons.contains(&p.name.to_string()) || (p.name == "ADC3" && METADATA.line.starts_with("STM32H7")) {
if !singletons.contains(&p.name.to_string())
|| (p.name == "ADC3" && METADATA.line.starts_with("STM32H7"))
|| (p.name.starts_with("ADC") && p.registers.as_ref().map_or(false, |r| r.version == "f3"))
|| (p.name.starts_with("ADC") && p.registers.as_ref().map_or(false, |r| r.version == "v4"))
{
continue;
}

View File

@ -1,6 +1,6 @@
#![macro_use]
#[cfg(not(adc_f3))]
#[cfg(not(any(adc_f3, adc_f3_v2)))]
#[cfg_attr(adc_f1, path = "f1.rs")]
#[cfg_attr(adc_v1, path = "v1.rs")]
#[cfg_attr(adc_v2, path = "v2.rs")]
@ -8,16 +8,16 @@
#[cfg_attr(adc_v4, path = "v4.rs")]
mod _version;
#[cfg(not(any(adc_f1, adc_f3)))]
#[cfg(not(any(adc_f1, adc_f3, adc_f3_v2)))]
mod resolution;
mod sample_time;
#[cfg(not(adc_f3))]
#[cfg(not(any(adc_f3, adc_f3_v2)))]
#[allow(unused)]
pub use _version::*;
#[cfg(not(any(adc_f1, adc_f3)))]
#[cfg(not(any(adc_f1, adc_f3, adc_f3_v2)))]
pub use resolution::Resolution;
#[cfg(not(adc_f3))]
#[cfg(not(any(adc_f3, adc_f3_v2)))]
pub use sample_time::SampleTime;
use crate::peripherals;
@ -25,14 +25,14 @@ use crate::peripherals;
pub struct Adc<'d, T: Instance> {
#[allow(unused)]
adc: crate::PeripheralRef<'d, T>,
#[cfg(not(adc_f3))]
#[cfg(not(any(adc_f3, adc_f3_v2)))]
sample_time: SampleTime,
}
pub(crate) mod sealed {
pub trait Instance {
fn regs() -> crate::pac::adc::Adc;
#[cfg(not(any(adc_f1, adc_v1, adc_f3)))]
#[cfg(not(any(adc_f1, adc_v1, adc_f3, adc_f3_v2)))]
fn common_regs() -> crate::pac::adccommon::AdcCommon;
}
@ -60,7 +60,7 @@ foreach_peripheral!(
fn regs() -> crate::pac::adc::Adc {
crate::pac::$inst
}
#[cfg(not(any(adc_f1, adc_v1, adc_f3)))]
#[cfg(not(any(adc_f1, adc_v1, adc_f3, adc_f3_v2)))]
fn common_regs() -> crate::pac::adccommon::AdcCommon {
foreach_peripheral!{
(adccommon, $common_inst:ident) => {

View File

@ -1,4 +1,4 @@
#[cfg(not(adc_f3))]
#[cfg(not(any(adc_f3, adc_f3_v2)))]
macro_rules! impl_sample_time {
($default_doc:expr, $default:ident, ($(($doc:expr, $variant:ident, $pac_variant:ident)),*)) => {
#[doc = concat!("ADC sample time\n\nThe default setting is ", $default_doc, " ADC clock cycles.")]

View File

@ -478,7 +478,7 @@ impl<'c, 'd, T: Instance> CanRx<'c, 'd, T> {
pub async fn read(&mut self) -> Result<Envelope, BusError> {
poll_fn(|cx| {
T::state().err_waker.register(cx.waker());
if let Poll::Ready(envelope) = T::state().rx_queue.recv().poll_unpin(cx) {
if let Poll::Ready(envelope) = T::state().rx_queue.receive().poll_unpin(cx) {
return Poll::Ready(Ok(envelope));
} else if let Some(err) = self.curr_error() {
return Poll::Ready(Err(err));
@ -493,7 +493,7 @@ impl<'c, 'd, T: Instance> CanRx<'c, 'd, T> {
///
/// Returns [Err(TryReadError::Empty)] if there are no frames in the rx queue.
pub fn try_read(&mut self) -> Result<Envelope, TryReadError> {
if let Ok(envelope) = T::state().rx_queue.try_recv() {
if let Ok(envelope) = T::state().rx_queue.try_receive() {
return Ok(envelope);
}
@ -506,14 +506,7 @@ impl<'c, 'd, T: Instance> CanRx<'c, 'd, T> {
/// Waits while receive queue is empty.
pub async fn wait_not_empty(&mut self) {
poll_fn(|cx| {
if T::state().rx_queue.poll_ready_to_receive(cx) {
Poll::Ready(())
} else {
Poll::Pending
}
})
.await
poll_fn(|cx| T::state().rx_queue.poll_ready_to_receive(cx)).await
}
fn curr_error(&self) -> Option<BusError> {

View File

@ -393,6 +393,10 @@ impl<'a, C: Channel> DmaCtrl for DmaCtrlImpl<'a, C> {
fn reset_complete_count(&mut self) -> usize {
STATE.complete_count[self.0.index()].swap(0, Ordering::AcqRel)
}
fn set_waker(&mut self, waker: &Waker) {
STATE.ch_wakers[self.0.index()].register(waker);
}
}
pub struct ReadableRingBuffer<'a, C: Channel, W: Word> {
@ -463,7 +467,7 @@ impl<'a, C: Channel, W: Word> ReadableRingBuffer<'a, C, W> {
}
pub fn clear(&mut self) {
self.ringbuf.clear(DmaCtrlImpl(self.channel.reborrow()));
self.ringbuf.clear(&mut DmaCtrlImpl(self.channel.reborrow()));
}
/// Read elements from the ring buffer
@ -472,7 +476,7 @@ impl<'a, C: Channel, W: Word> ReadableRingBuffer<'a, C, W> {
/// The length remaining is the capacity, ring_buf.len(), less the elements remaining after the read
/// OverrunError is returned if the portion to be read was overwritten by the DMA controller.
pub fn read(&mut self, buf: &mut [W]) -> Result<(usize, usize), OverrunError> {
self.ringbuf.read(DmaCtrlImpl(self.channel.reborrow()), buf)
self.ringbuf.read(&mut DmaCtrlImpl(self.channel.reborrow()), buf)
}
/// Read an exact number of elements from the ringbuffer.
@ -487,39 +491,18 @@ impl<'a, C: Channel, W: Word> ReadableRingBuffer<'a, C, W> {
/// - If M equals N/2 or N/2 divides evenly into M, this function will return every N/2 elements read on the DMA source.
/// - Otherwise, this function may need up to N/2 extra elements to arrive before returning.
pub async fn read_exact(&mut self, buffer: &mut [W]) -> Result<usize, OverrunError> {
use core::future::poll_fn;
use core::sync::atomic::compiler_fence;
let mut read_data = 0;
let buffer_len = buffer.len();
poll_fn(|cx| {
self.set_waker(cx.waker());
compiler_fence(Ordering::SeqCst);
match self.read(&mut buffer[read_data..buffer_len]) {
Ok((len, remaining)) => {
read_data += len;
if read_data == buffer_len {
Poll::Ready(Ok(remaining))
} else {
Poll::Pending
}
}
Err(e) => Poll::Ready(Err(e)),
}
})
.await
self.ringbuf
.read_exact(&mut DmaCtrlImpl(self.channel.reborrow()), buffer)
.await
}
/// The capacity of the ringbuffer.
pub fn cap(&self) -> usize {
pub const fn cap(&self) -> usize {
self.ringbuf.cap()
}
pub fn set_waker(&mut self, waker: &Waker) {
STATE.ch_wakers[self.channel.index()].register(waker);
DmaCtrlImpl(self.channel.reborrow()).set_waker(waker);
}
fn clear_irqs(&mut self) {
@ -628,50 +611,29 @@ impl<'a, C: Channel, W: Word> WritableRingBuffer<'a, C, W> {
}
pub fn clear(&mut self) {
self.ringbuf.clear(DmaCtrlImpl(self.channel.reborrow()));
self.ringbuf.clear(&mut DmaCtrlImpl(self.channel.reborrow()));
}
/// Write elements to the ring buffer
/// Return a tuple of the length written and the length remaining in the buffer
pub fn write(&mut self, buf: &[W]) -> Result<(usize, usize), OverrunError> {
self.ringbuf.write(DmaCtrlImpl(self.channel.reborrow()), buf)
self.ringbuf.write(&mut DmaCtrlImpl(self.channel.reborrow()), buf)
}
/// Write an exact number of elements to the ringbuffer.
pub async fn write_exact(&mut self, buffer: &[W]) -> Result<usize, OverrunError> {
use core::future::poll_fn;
use core::sync::atomic::compiler_fence;
let mut written_data = 0;
let buffer_len = buffer.len();
poll_fn(|cx| {
self.set_waker(cx.waker());
compiler_fence(Ordering::SeqCst);
match self.write(&buffer[written_data..buffer_len]) {
Ok((len, remaining)) => {
written_data += len;
if written_data == buffer_len {
Poll::Ready(Ok(remaining))
} else {
Poll::Pending
}
}
Err(e) => Poll::Ready(Err(e)),
}
})
.await
self.ringbuf
.write_exact(&mut DmaCtrlImpl(self.channel.reborrow()), buffer)
.await
}
/// The capacity of the ringbuffer.
pub fn cap(&self) -> usize {
pub const fn cap(&self) -> usize {
self.ringbuf.cap()
}
pub fn set_waker(&mut self, waker: &Waker) {
STATE.ch_wakers[self.channel.index()].register(waker);
DmaCtrlImpl(self.channel.reborrow()).set_waker(waker);
}
fn clear_irqs(&mut self) {

View File

@ -623,6 +623,10 @@ impl<'a, C: Channel> DmaCtrl for DmaCtrlImpl<'a, C> {
fn reset_complete_count(&mut self) -> usize {
STATE.complete_count[self.0.index()].swap(0, Ordering::AcqRel)
}
fn set_waker(&mut self, waker: &Waker) {
STATE.ch_wakers[self.0.index()].register(waker);
}
}
pub struct ReadableRingBuffer<'a, C: Channel, W: Word> {
@ -708,7 +712,7 @@ impl<'a, C: Channel, W: Word> ReadableRingBuffer<'a, C, W> {
}
pub fn clear(&mut self) {
self.ringbuf.clear(DmaCtrlImpl(self.channel.reborrow()));
self.ringbuf.clear(&mut DmaCtrlImpl(self.channel.reborrow()));
}
/// Read elements from the ring buffer
@ -717,7 +721,7 @@ impl<'a, C: Channel, W: Word> ReadableRingBuffer<'a, C, W> {
/// The length remaining is the capacity, ring_buf.len(), less the elements remaining after the read
/// OverrunError is returned if the portion to be read was overwritten by the DMA controller.
pub fn read(&mut self, buf: &mut [W]) -> Result<(usize, usize), OverrunError> {
self.ringbuf.read(DmaCtrlImpl(self.channel.reborrow()), buf)
self.ringbuf.read(&mut DmaCtrlImpl(self.channel.reborrow()), buf)
}
/// Read an exact number of elements from the ringbuffer.
@ -732,39 +736,18 @@ impl<'a, C: Channel, W: Word> ReadableRingBuffer<'a, C, W> {
/// - If M equals N/2 or N/2 divides evenly into M, this function will return every N/2 elements read on the DMA source.
/// - Otherwise, this function may need up to N/2 extra elements to arrive before returning.
pub async fn read_exact(&mut self, buffer: &mut [W]) -> Result<usize, OverrunError> {
use core::future::poll_fn;
use core::sync::atomic::compiler_fence;
let mut read_data = 0;
let buffer_len = buffer.len();
poll_fn(|cx| {
self.set_waker(cx.waker());
compiler_fence(Ordering::SeqCst);
match self.read(&mut buffer[read_data..buffer_len]) {
Ok((len, remaining)) => {
read_data += len;
if read_data == buffer_len {
Poll::Ready(Ok(remaining))
} else {
Poll::Pending
}
}
Err(e) => Poll::Ready(Err(e)),
}
})
.await
self.ringbuf
.read_exact(&mut DmaCtrlImpl(self.channel.reborrow()), buffer)
.await
}
// The capacity of the ringbuffer
pub fn cap(&self) -> usize {
pub const fn cap(&self) -> usize {
self.ringbuf.cap()
}
pub fn set_waker(&mut self, waker: &Waker) {
STATE.ch_wakers[self.channel.index()].register(waker);
DmaCtrlImpl(self.channel.reborrow()).set_waker(waker);
}
fn clear_irqs(&mut self) {
@ -890,50 +873,29 @@ impl<'a, C: Channel, W: Word> WritableRingBuffer<'a, C, W> {
}
pub fn clear(&mut self) {
self.ringbuf.clear(DmaCtrlImpl(self.channel.reborrow()));
self.ringbuf.clear(&mut DmaCtrlImpl(self.channel.reborrow()));
}
/// Write elements from the ring buffer
/// Return a tuple of the length written and the length remaining in the buffer
pub fn write(&mut self, buf: &[W]) -> Result<(usize, usize), OverrunError> {
self.ringbuf.write(DmaCtrlImpl(self.channel.reborrow()), buf)
self.ringbuf.write(&mut DmaCtrlImpl(self.channel.reborrow()), buf)
}
/// Write an exact number of elements to the ringbuffer.
pub async fn write_exact(&mut self, buffer: &[W]) -> Result<usize, OverrunError> {
use core::future::poll_fn;
use core::sync::atomic::compiler_fence;
let mut written_data = 0;
let buffer_len = buffer.len();
poll_fn(|cx| {
self.set_waker(cx.waker());
compiler_fence(Ordering::SeqCst);
match self.write(&buffer[written_data..buffer_len]) {
Ok((len, remaining)) => {
written_data += len;
if written_data == buffer_len {
Poll::Ready(Ok(remaining))
} else {
Poll::Pending
}
}
Err(e) => Poll::Ready(Err(e)),
}
})
.await
self.ringbuf
.write_exact(&mut DmaCtrlImpl(self.channel.reborrow()), buffer)
.await
}
// The capacity of the ringbuffer
pub fn cap(&self) -> usize {
pub const fn cap(&self) -> usize {
self.ringbuf.cap()
}
pub fn set_waker(&mut self, waker: &Waker) {
STATE.ch_wakers[self.channel.index()].register(waker);
DmaCtrlImpl(self.channel.reborrow()).set_waker(waker);
}
fn clear_irqs(&mut self) {

View File

@ -1,7 +1,9 @@
#![cfg_attr(gpdma, allow(unused))]
use core::future::poll_fn;
use core::ops::Range;
use core::sync::atomic::{compiler_fence, Ordering};
use core::task::{Poll, Waker};
use super::word::Word;
@ -49,6 +51,9 @@ pub trait DmaCtrl {
/// Reset the transfer completed counter to 0 and return the value just prior to the reset.
fn reset_complete_count(&mut self) -> usize;
/// Set the waker for a running poll_fn
fn set_waker(&mut self, waker: &Waker);
}
impl<'a, W: Word> ReadableDmaRingBuffer<'a, W> {
@ -57,7 +62,7 @@ impl<'a, W: Word> ReadableDmaRingBuffer<'a, W> {
}
/// Reset the ring buffer to its initial state
pub fn clear(&mut self, mut dma: impl DmaCtrl) {
pub fn clear(&mut self, dma: &mut impl DmaCtrl) {
self.start = 0;
dma.reset_complete_count();
}
@ -68,8 +73,43 @@ impl<'a, W: Word> ReadableDmaRingBuffer<'a, W> {
}
/// The current position of the ringbuffer
fn pos(&self, remaining_transfers: usize) -> usize {
self.cap() - remaining_transfers
fn pos(&self, dma: &mut impl DmaCtrl) -> usize {
self.cap() - dma.get_remaining_transfers()
}
/// Read an exact number of elements from the ringbuffer.
///
/// Returns the remaining number of elements available for immediate reading.
/// OverrunError is returned if the portion to be read was overwritten by the DMA controller.
///
/// Async/Wake Behavior:
/// The underlying DMA peripheral only can wake us when its buffer pointer has reached the halfway point,
/// and when it wraps around. This means that when called with a buffer of length 'M', when this
/// ring buffer was created with a buffer of size 'N':
/// - If M equals N/2 or N/2 divides evenly into M, this function will return every N/2 elements read on the DMA source.
/// - Otherwise, this function may need up to N/2 extra elements to arrive before returning.
pub async fn read_exact(&mut self, dma: &mut impl DmaCtrl, buffer: &mut [W]) -> Result<usize, OverrunError> {
let mut read_data = 0;
let buffer_len = buffer.len();
poll_fn(|cx| {
dma.set_waker(cx.waker());
compiler_fence(Ordering::SeqCst);
match self.read(dma, &mut buffer[read_data..buffer_len]) {
Ok((len, remaining)) => {
read_data += len;
if read_data == buffer_len {
Poll::Ready(Ok(remaining))
} else {
Poll::Pending
}
}
Err(e) => Poll::Ready(Err(e)),
}
})
.await
}
/// Read elements from the ring buffer
@ -77,7 +117,7 @@ impl<'a, W: Word> ReadableDmaRingBuffer<'a, W> {
/// If not all of the elements were read, then there will be some elements in the buffer remaining
/// The length remaining is the capacity, ring_buf.len(), less the elements remaining after the read
/// OverrunError is returned if the portion to be read was overwritten by the DMA controller.
pub fn read(&mut self, mut dma: impl DmaCtrl, buf: &mut [W]) -> Result<(usize, usize), OverrunError> {
pub fn read(&mut self, dma: &mut impl DmaCtrl, buf: &mut [W]) -> Result<(usize, usize), OverrunError> {
/*
This algorithm is optimistic: we assume we haven't overrun more than a full buffer and then check
after we've done our work to see we have. This is because on stm32, an interrupt is not guaranteed
@ -93,7 +133,7 @@ impl<'a, W: Word> ReadableDmaRingBuffer<'a, W> {
rather than the data we actually copied because it costs nothing and confirms an error condition
earlier.
*/
let end = self.pos(dma.get_remaining_transfers());
let end = self.pos(dma);
if self.start == end && dma.get_complete_count() == 0 {
// No elements are available in the buffer
Ok((0, self.cap()))
@ -114,8 +154,7 @@ impl<'a, W: Word> ReadableDmaRingBuffer<'a, W> {
then, get the current position of of the dma write and check
if it's inside data we could have copied
*/
let (pos, complete_count) =
critical_section::with(|_| (self.pos(dma.get_remaining_transfers()), dma.get_complete_count()));
let (pos, complete_count) = critical_section::with(|_| (self.pos(dma), dma.get_complete_count()));
if (pos >= self.start && pos < end) || (complete_count > 0 && pos >= end) || complete_count > 1 {
Err(OverrunError)
} else {
@ -141,7 +180,7 @@ impl<'a, W: Word> ReadableDmaRingBuffer<'a, W> {
then, get the current position of of the dma write and check
if it's inside data we could have copied
*/
let pos = self.pos(dma.get_remaining_transfers());
let pos = self.pos(dma);
if pos > self.start || pos < end || dma.get_complete_count() > 1 {
Err(OverrunError)
} else {
@ -169,7 +208,7 @@ impl<'a, W: Word> ReadableDmaRingBuffer<'a, W> {
then, get the current position of of the dma write and check
if it's inside data we could have copied
*/
let pos = self.pos(dma.get_remaining_transfers());
let pos = self.pos(dma);
if pos > self.start || pos < end || dma.reset_complete_count() > 1 {
Err(OverrunError)
} else {
@ -209,7 +248,7 @@ impl<'a, W: Word> WritableDmaRingBuffer<'a, W> {
}
/// Reset the ring buffer to its initial state
pub fn clear(&mut self, mut dma: impl DmaCtrl) {
pub fn clear(&mut self, dma: &mut impl DmaCtrl) {
self.end = 0;
dma.reset_complete_count();
}
@ -220,14 +259,39 @@ impl<'a, W: Word> WritableDmaRingBuffer<'a, W> {
}
/// The current position of the ringbuffer
fn pos(&self, remaining_transfers: usize) -> usize {
self.cap() - remaining_transfers
fn pos(&self, dma: &mut impl DmaCtrl) -> usize {
self.cap() - dma.get_remaining_transfers()
}
/// Write an exact number of elements to the ringbuffer.
pub async fn write_exact(&mut self, dma: &mut impl DmaCtrl, buffer: &[W]) -> Result<usize, OverrunError> {
let mut written_data = 0;
let buffer_len = buffer.len();
poll_fn(|cx| {
dma.set_waker(cx.waker());
compiler_fence(Ordering::SeqCst);
match self.write(dma, &buffer[written_data..buffer_len]) {
Ok((len, remaining)) => {
written_data += len;
if written_data == buffer_len {
Poll::Ready(Ok(remaining))
} else {
Poll::Pending
}
}
Err(e) => Poll::Ready(Err(e)),
}
})
.await
}
/// Write elements from the ring buffer
/// Return a tuple of the length written and the capacity remaining to be written in the buffer
pub fn write(&mut self, mut dma: impl DmaCtrl, buf: &[W]) -> Result<(usize, usize), OverrunError> {
let start = self.pos(dma.get_remaining_transfers());
pub fn write(&mut self, dma: &mut impl DmaCtrl, buf: &[W]) -> Result<(usize, usize), OverrunError> {
let start = self.pos(dma);
if start > self.end {
// The occupied portion in the ring buffer DOES wrap
let len = self.copy_from(buf, self.end..start);
@ -235,8 +299,7 @@ impl<'a, W: Word> WritableDmaRingBuffer<'a, W> {
compiler_fence(Ordering::SeqCst);
// Confirm that the DMA is not inside data we could have written
let (pos, complete_count) =
critical_section::with(|_| (self.pos(dma.get_remaining_transfers()), dma.get_complete_count()));
let (pos, complete_count) = critical_section::with(|_| (self.pos(dma), dma.get_complete_count()));
if (pos >= self.end && pos < start) || (complete_count > 0 && pos >= start) || complete_count > 1 {
Err(OverrunError)
} else {
@ -256,7 +319,7 @@ impl<'a, W: Word> WritableDmaRingBuffer<'a, W> {
compiler_fence(Ordering::SeqCst);
// Confirm that the DMA is not inside data we could have written
let pos = self.pos(dma.get_remaining_transfers());
let pos = self.pos(dma);
if pos > self.end || pos < start || dma.get_complete_count() > 1 {
Err(OverrunError)
} else {
@ -274,7 +337,7 @@ impl<'a, W: Word> WritableDmaRingBuffer<'a, W> {
compiler_fence(Ordering::SeqCst);
// Confirm that the DMA is not inside data we could have written
let pos = self.pos(dma.get_remaining_transfers());
let pos = self.pos(dma);
if pos > self.end || pos < start || dma.reset_complete_count() > 1 {
Err(OverrunError)
} else {
@ -323,7 +386,7 @@ mod tests {
requests: cell::RefCell<vec::Vec<TestCircularTransferRequest>>,
}
impl DmaCtrl for &mut TestCircularTransfer {
impl DmaCtrl for TestCircularTransfer {
fn get_remaining_transfers(&self) -> usize {
match self.requests.borrow_mut().pop().unwrap() {
TestCircularTransferRequest::PositionRequest(pos) => {
@ -350,6 +413,8 @@ mod tests {
_ => unreachable!(),
}
}
fn set_waker(&mut self, waker: &Waker) {}
}
impl TestCircularTransfer {

View File

@ -11,7 +11,7 @@ pub const fn is_default_layout() -> bool {
}
const fn is_dual_bank() -> bool {
FLASH_REGIONS.len() == 2
FLASH_REGIONS.len() >= 2
}
pub fn get_flash_regions() -> &'static [&'static FlashRegion] {
@ -49,6 +49,7 @@ pub(crate) unsafe fn blocking_write(start_address: u32, buf: &[u8; WRITE_SIZE])
};
bank.cr().write(|w| {
w.set_pg(true);
#[cfg(flash_h7)]
w.set_psize(2); // 32 bits at once
});
cortex_m::asm::isb();
@ -85,7 +86,10 @@ pub(crate) unsafe fn blocking_erase_sector(sector: &FlashSector) -> Result<(), E
let bank = pac::FLASH.bank(sector.bank as usize);
bank.cr().modify(|w| {
w.set_ser(true);
w.set_snb(sector.index_in_bank)
#[cfg(flash_h7)]
w.set_snb(sector.index_in_bank);
#[cfg(flash_h7ab)]
w.set_ssn(sector.index_in_bank);
});
bank.cr().modify(|w| {
@ -126,6 +130,10 @@ unsafe fn blocking_wait_ready(bank: pac::flash::Bank) -> Result<(), Error> {
error!("incerr");
return Err(Error::Seq);
}
if sr.crcrderr() {
error!("crcrderr");
return Err(Error::Seq);
}
if sr.operr() {
return Err(Error::Prog);
}

View File

@ -65,9 +65,11 @@ impl FlashRegion {
#[cfg_attr(flash_f7, path = "f7.rs")]
#[cfg_attr(flash_g0, path = "g0.rs")]
#[cfg_attr(flash_h7, path = "h7.rs")]
#[cfg_attr(flash_h7ab, path = "h7.rs")]
#[cfg_attr(
not(any(
flash_l0, flash_l1, flash_l4, flash_wl, flash_wb, flash_f0, flash_f3, flash_f4, flash_f7, flash_g0, flash_h7
flash_l0, flash_l1, flash_l4, flash_wl, flash_wb, flash_f0, flash_f3, flash_f4, flash_f7, flash_g0, flash_h7,
flash_h7ab
)),
path = "other.rs"
)]

View File

@ -378,22 +378,6 @@ pub(crate) unsafe fn init(config: Config) {
// Reference: STM32F215xx/217xx datasheet Table 13. General operating conditions
assert!(ahb_freq <= Hertz(120_000_000));
let flash_ws = unwrap!(config.voltage.wait_states(ahb_freq));
FLASH.acr().modify(|w| w.set_latency(flash_ws));
RCC.cfgr().modify(|w| {
w.set_sw(sw.into());
w.set_hpre(config.ahb_pre.into());
w.set_ppre1(config.apb1_pre.into());
w.set_ppre2(config.apb2_pre.into());
});
while RCC.cfgr().read().sws().to_bits() != sw.to_bits() {}
// Turn off HSI to save power if we don't need it
if !config.hsi {
RCC.cr().modify(|w| w.set_hsion(false));
}
let (apb1_freq, apb1_tim_freq) = match config.apb1_pre {
APBPrescaler::NotDivided => (ahb_freq, ahb_freq),
pre => {
@ -414,6 +398,22 @@ pub(crate) unsafe fn init(config: Config) {
// Reference: STM32F215xx/217xx datasheet Table 13. General operating conditions
assert!(apb2_freq <= Hertz(60_000_000));
let flash_ws = unwrap!(config.voltage.wait_states(ahb_freq));
FLASH.acr().modify(|w| w.set_latency(flash_ws));
RCC.cfgr().modify(|w| {
w.set_sw(sw.into());
w.set_hpre(config.ahb_pre.into());
w.set_ppre1(config.apb1_pre.into());
w.set_ppre2(config.apb2_pre.into());
});
while RCC.cfgr().read().sws().to_bits() != sw.to_bits() {}
// Turn off HSI to save power if we don't need it
if !config.hsi {
RCC.cr().modify(|w| w.set_hsion(false));
}
set_freqs(Clocks {
sys: sys_clk,
ahb1: ahb_freq,

View File

@ -200,6 +200,7 @@ fn flash_setup(rcc_aclk: u32, vos: VoltageScale) {
// See RM0433 Rev 7 Table 17. FLASH recommended number of wait
// states and programming delay
#[cfg(flash_h7)]
let (wait_states, progr_delay) = match vos {
// VOS 0 range VCORE 1.26V - 1.40V
VoltageScale::Scale0 => match rcc_aclk_mhz {
@ -239,6 +240,50 @@ fn flash_setup(rcc_aclk: u32, vos: VoltageScale) {
},
};
// See RM0455 Rev 10 Table 16. FLASH recommended number of wait
// states and programming delay
#[cfg(flash_h7ab)]
let (wait_states, progr_delay) = match vos {
// VOS 0 range VCORE 1.25V - 1.35V
VoltageScale::Scale0 => match rcc_aclk_mhz {
0..=42 => (0, 0),
43..=84 => (1, 0),
85..=126 => (2, 1),
127..=168 => (3, 1),
169..=210 => (4, 2),
211..=252 => (5, 2),
253..=280 => (6, 3),
_ => (7, 3),
},
// VOS 1 range VCORE 1.15V - 1.25V
VoltageScale::Scale1 => match rcc_aclk_mhz {
0..=38 => (0, 0),
39..=76 => (1, 0),
77..=114 => (2, 1),
115..=152 => (3, 1),
153..=190 => (4, 2),
191..=225 => (5, 2),
_ => (7, 3),
},
// VOS 2 range VCORE 1.05V - 1.15V
VoltageScale::Scale2 => match rcc_aclk_mhz {
0..=34 => (0, 0),
35..=68 => (1, 0),
69..=102 => (2, 1),
103..=136 => (3, 1),
137..=160 => (4, 2),
_ => (7, 3),
},
// VOS 3 range VCORE 0.95V - 1.05V
VoltageScale::Scale3 => match rcc_aclk_mhz {
0..=22 => (0, 0),
23..=44 => (1, 0),
45..=66 => (2, 1),
67..=88 => (3, 1),
_ => (7, 3),
},
};
FLASH.acr().write(|w| {
w.set_wrhighfreq(progr_delay);
w.set_latency(wait_states)
@ -538,8 +583,6 @@ pub(crate) unsafe fn init(mut config: Config) {
let requested_pclk4 = config.pclk4.map(|v| v.0).unwrap_or_else(|| pclk_max.min(rcc_hclk / 2));
let (rcc_pclk4, ppre4_bits, ppre4, _) = ppre_calculate(requested_pclk4, rcc_hclk, pclk_max, None);
flash_setup(rcc_aclk, pwr_vos);
// Start switching clocks -------------------
// Ensure CSI is on and stable
@ -595,6 +638,8 @@ pub(crate) unsafe fn init(mut config: Config) {
// core voltage
while RCC.d1cfgr().read().d1cpre().to_bits() != d1cpre_bits {}
flash_setup(rcc_aclk, pwr_vos);
// APB1 / APB2 Prescaler
RCC.d2cfgr().modify(|w| {
w.set_d2ppre1(Dppre::from_bits(ppre1_bits));

View File

@ -410,10 +410,11 @@ pub(crate) unsafe fn init(config: Config) {
while RCC.cfgr().read().sws() != Sw::MSI {}
}
RCC.apb1enr1().modify(|w| w.set_pwren(true));
match config.rtc_mux {
RtcClockSource::LSE32 => {
// 1. Unlock the backup domain
RCC.apb1enr1().modify(|w| w.set_pwren(true));
PWR.cr1().modify(|w| w.set_dbp(true));
// 2. Setup the LSE

View File

@ -9,7 +9,7 @@ use crate::time::Hertz;
#[cfg_attr(rcc_f0, path = "f0.rs")]
#[cfg_attr(any(rcc_f1, rcc_f100, rcc_f1cl), path = "f1.rs")]
#[cfg_attr(rcc_f2, path = "f2.rs")]
#[cfg_attr(rcc_f3, path = "f3.rs")]
#[cfg_attr(any(rcc_f3, rcc_f3_v2), path = "f3.rs")]
#[cfg_attr(any(rcc_f4, rcc_f410), path = "f4.rs")]
#[cfg_attr(rcc_f7, path = "f7.rs")]
#[cfg_attr(rcc_c0, path = "c0.rs")]

View File

@ -2,6 +2,7 @@ pub use super::common::{AHBPrescaler, APBPrescaler, VoltageScale};
use crate::pac::pwr::vals::Dbp;
use crate::pac::{FLASH, PWR, RCC};
use crate::rcc::{set_freqs, Clocks};
use crate::rtc::{Rtc, RtcClockSource as RCS};
use crate::time::Hertz;
/// Most of clock setup is copied from stm32l0xx-hal, and adopted to the generated PAC,
@ -229,6 +230,8 @@ pub(crate) unsafe fn init(config: Config) {
// Wait until LSE is running
while !RCC.bdcr().read().lserdy() {}
Rtc::set_clock_source(RCS::LSE);
}
RtcClockSource::LSI32 => {
// Turn on the internal 32 kHz LSI oscillator
@ -236,6 +239,8 @@ pub(crate) unsafe fn init(config: Config) {
// Wait until LSI is running
while !RCC.csr().read().lsirdy() {}
Rtc::set_clock_source(RCS::LSI);
}
}

View File

@ -73,15 +73,20 @@ impl<'d, T: Instance> Rng<'d, T> {
#[cfg(not(rng_v1))]
pub fn reset(&mut self) {
T::regs().cr().write(|reg| {
reg.set_rngen(false);
reg.set_condrst(true);
reg.set_nistc(pac::rng::vals::Nistc::CUSTOM);
// set RNG config "A" according to reference manual
// this has to be written within the same write access as setting the CONDRST bit
reg.set_nistc(pac::rng::vals::Nistc::DEFAULT);
reg.set_rng_config1(pac::rng::vals::RngConfig1::CONFIGA);
reg.set_clkdiv(pac::rng::vals::Clkdiv::NODIV);
reg.set_rng_config2(pac::rng::vals::RngConfig2::CONFIGA_B);
reg.set_rng_config3(pac::rng::vals::RngConfig3::CONFIGA);
reg.set_clkdiv(pac::rng::vals::Clkdiv::NODIV);
reg.set_ced(true);
reg.set_ie(false);
reg.set_rngen(true);
});
T::regs().cr().write(|reg| {
reg.set_ced(false);
});
// wait for CONDRST to be set
while !T::regs().cr().read().condrst() {}

View File

@ -72,6 +72,7 @@ impl core::ops::Sub for RtcInstant {
}
}
#[allow(dead_code)]
#[derive(Clone, Copy)]
pub(crate) enum WakeupPrescaler {
Div2,
@ -120,6 +121,7 @@ impl From<WakeupPrescaler> for u32 {
}
}
#[allow(dead_code)]
impl WakeupPrescaler {
pub fn compute_min(val: u32) -> Self {
*[

View File

@ -100,14 +100,19 @@ impl<'d, T: ComplementaryCaptureCompare16bitInstance> ComplementaryPwm<'d, T> {
}
pub fn get_max_duty(&self) -> u16 {
self.inner.get_max_compare_value()
self.inner.get_max_compare_value() + 1
}
pub fn set_duty(&mut self, channel: Channel, duty: u16) {
assert!(duty < self.get_max_duty());
assert!(duty <= self.get_max_duty());
self.inner.set_compare_value(channel, duty)
}
pub fn set_polarity(&mut self, channel: Channel, polarity: OutputPolarity) {
self.inner.set_output_polarity(channel, polarity);
self.inner.set_complementary_output_polarity(channel, polarity);
}
/// Set the dead time as a proportion of max_duty
pub fn set_dead_time(&mut self, value: u16) {
let (ckd, value) = compute_dead_time_value(value);

View File

@ -53,6 +53,8 @@ pub(crate) mod sealed {
fn set_output_compare_mode(&mut self, channel: Channel, mode: OutputCompareMode);
fn set_output_polarity(&mut self, channel: Channel, polarity: OutputPolarity);
fn enable_channel(&mut self, channel: Channel, enable: bool);
fn set_compare_value(&mut self, channel: Channel, value: u16);
@ -61,6 +63,8 @@ pub(crate) mod sealed {
}
pub trait ComplementaryCaptureCompare16bitInstance: CaptureCompare16bitInstance {
fn set_complementary_output_polarity(&mut self, channel: Channel, polarity: OutputPolarity);
fn set_dead_time_clock_division(&mut self, value: vals::Ckd);
fn set_dead_time_value(&mut self, value: u8);
@ -71,6 +75,8 @@ pub(crate) mod sealed {
pub trait CaptureCompare32bitInstance: GeneralPurpose32bitInstance {
fn set_output_compare_mode(&mut self, channel: Channel, mode: OutputCompareMode);
fn set_output_polarity(&mut self, channel: Channel, polarity: OutputPolarity);
fn enable_channel(&mut self, channel: Channel, enable: bool);
fn set_compare_value(&mut self, channel: Channel, value: u32);
@ -125,6 +131,21 @@ impl From<OutputCompareMode> for stm32_metapac::timer::vals::Ocm {
}
}
#[derive(Clone, Copy)]
pub enum OutputPolarity {
ActiveHigh,
ActiveLow,
}
impl From<OutputPolarity> for bool {
fn from(mode: OutputPolarity) -> Self {
match mode {
OutputPolarity::ActiveHigh => false,
OutputPolarity::ActiveLow => true,
}
}
}
pub trait Basic16bitInstance: sealed::Basic16bitInstance + 'static {}
pub trait GeneralPurpose16bitInstance: sealed::GeneralPurpose16bitInstance + 'static {}
@ -265,6 +286,13 @@ macro_rules! impl_compare_capable_16bit {
.modify(|w| w.set_ocm(raw_channel % 2, mode.into()));
}
fn set_output_polarity(&mut self, channel: Channel, polarity: OutputPolarity) {
use sealed::GeneralPurpose16bitInstance;
Self::regs_gp16()
.ccer()
.modify(|w| w.set_ccp(channel.raw(), polarity.into()));
}
fn enable_channel(&mut self, channel: Channel, enable: bool) {
use sealed::GeneralPurpose16bitInstance;
Self::regs_gp16()
@ -325,6 +353,13 @@ foreach_interrupt! {
Self::regs_gp32().ccmr_output(raw_channel / 2).modify(|w| w.set_ocm(raw_channel % 2, mode.into()));
}
fn set_output_polarity(&mut self, channel: Channel, polarity: OutputPolarity) {
use crate::timer::sealed::GeneralPurpose32bitInstance;
Self::regs_gp32()
.ccer()
.modify(|w| w.set_ccp(channel.raw(), polarity.into()));
}
fn enable_channel(&mut self, channel: Channel, enable: bool) {
use crate::timer::sealed::GeneralPurpose32bitInstance;
Self::regs_gp32().ccer().modify(|w| w.set_cce(channel.raw(), enable));
@ -388,6 +423,13 @@ foreach_interrupt! {
.modify(|w| w.set_ocm(raw_channel % 2, mode.into()));
}
fn set_output_polarity(&mut self, channel: Channel, polarity: OutputPolarity) {
use crate::timer::sealed::AdvancedControlInstance;
Self::regs_advanced()
.ccer()
.modify(|w| w.set_ccp(channel.raw(), polarity.into()));
}
fn enable_channel(&mut self, channel: Channel, enable: bool) {
use crate::timer::sealed::AdvancedControlInstance;
Self::regs_advanced()
@ -409,6 +451,13 @@ foreach_interrupt! {
}
impl sealed::ComplementaryCaptureCompare16bitInstance for crate::peripherals::$inst {
fn set_complementary_output_polarity(&mut self, channel: Channel, polarity: OutputPolarity) {
use crate::timer::sealed::AdvancedControlInstance;
Self::regs_advanced()
.ccer()
.modify(|w| w.set_ccnp(channel.raw(), polarity.into()));
}
fn set_dead_time_clock_division(&mut self, value: vals::Ckd) {
use crate::timer::sealed::AdvancedControlInstance;
Self::regs_advanced().cr1().modify(|w| w.set_ckd(value));

View File

@ -97,11 +97,15 @@ impl<'d, T: CaptureCompare16bitInstance> SimplePwm<'d, T> {
}
pub fn get_max_duty(&self) -> u16 {
self.inner.get_max_compare_value()
self.inner.get_max_compare_value() + 1
}
pub fn set_duty(&mut self, channel: Channel, duty: u16) {
assert!(duty < self.get_max_duty());
assert!(duty <= self.get_max_duty());
self.inner.set_compare_value(channel, duty)
}
pub fn set_polarity(&mut self, channel: Channel, polarity: OutputPolarity) {
self.inner.set_output_polarity(channel, polarity);
}
}

View File

@ -584,15 +584,15 @@ mod eh02 {
mod eh1 {
use super::*;
impl<'d, T: BasicInstance> embedded_hal_1::serial::ErrorType for BufferedUart<'d, T> {
impl<'d, T: BasicInstance> embedded_hal_nb::serial::ErrorType for BufferedUart<'d, T> {
type Error = Error;
}
impl<'d, T: BasicInstance> embedded_hal_1::serial::ErrorType for BufferedUartTx<'d, T> {
impl<'d, T: BasicInstance> embedded_hal_nb::serial::ErrorType for BufferedUartTx<'d, T> {
type Error = Error;
}
impl<'d, T: BasicInstance> embedded_hal_1::serial::ErrorType for BufferedUartRx<'d, T> {
impl<'d, T: BasicInstance> embedded_hal_nb::serial::ErrorType for BufferedUartRx<'d, T> {
type Error = Error;
}
@ -602,16 +602,6 @@ mod eh1 {
}
}
impl<'d, T: BasicInstance> embedded_hal_1::serial::Write for BufferedUartTx<'d, T> {
fn write(&mut self, buffer: &[u8]) -> Result<(), Self::Error> {
self.blocking_write(buffer).map(drop)
}
fn flush(&mut self) -> Result<(), Self::Error> {
self.blocking_flush()
}
}
impl<'d, T: BasicInstance> embedded_hal_nb::serial::Write for BufferedUartTx<'d, T> {
fn write(&mut self, char: u8) -> nb::Result<(), Self::Error> {
self.blocking_write(&[char]).map(drop).map_err(nb::Error::Other)
@ -628,16 +618,6 @@ mod eh1 {
}
}
impl<'d, T: BasicInstance> embedded_hal_1::serial::Write for BufferedUart<'d, T> {
fn write(&mut self, buffer: &[u8]) -> Result<(), Self::Error> {
self.tx.blocking_write(buffer).map(drop)
}
fn flush(&mut self) -> Result<(), Self::Error> {
self.tx.blocking_flush()
}
}
impl<'d, T: BasicInstance> embedded_hal_nb::serial::Write for BufferedUart<'d, T> {
fn write(&mut self, char: u8) -> nb::Result<(), Self::Error> {
self.tx.blocking_write(&[char]).map(drop).map_err(nb::Error::Other)

View File

@ -809,45 +809,57 @@ fn configure(r: Regs, config: &Config, pclk_freq: Hertz, kind: Kind, enable_rx:
Kind::Uart => (1, 0x10, 0x1_0000),
};
fn calculate_brr(baud: u32, pclk: u32, presc: u32, mul: u32) -> u32 {
// The calculation to be done to get the BRR is `mul * pclk / presc / baud`
// To do this in 32-bit only we can't multiply `mul` and `pclk`
let clock = pclk / presc;
// The mul is applied as the last operation to prevent overflow
let brr = clock / baud * mul;
// The BRR calculation will be a bit off because of integer rounding.
// Because we multiplied our inaccuracy with mul, our rounding now needs to be in proportion to mul.
let rounding = ((clock % baud) * mul + (baud / 2)) / baud;
brr + rounding
}
#[cfg(not(usart_v1))]
let mut over8 = false;
let mut found = None;
let mut found_brr = None;
for &(presc, _presc_val) in &DIVS {
let denom = (config.baudrate * presc as u32) as u64;
let div = (pclk_freq.0 as u64 * mul + (denom / 2)) / denom;
let brr = calculate_brr(config.baudrate, pclk_freq.0, presc as u32, mul);
trace!(
"USART: presc={}, div=0x{:08x} (mantissa = {}, fraction = {})",
presc,
div,
div >> 4,
div & 0x0F
brr,
brr >> 4,
brr & 0x0F
);
if div < brr_min {
if brr < brr_min {
#[cfg(not(usart_v1))]
if div * 2 >= brr_min && kind == Kind::Uart && !cfg!(usart_v1) {
if brr * 2 >= brr_min && kind == Kind::Uart && !cfg!(usart_v1) {
over8 = true;
let div = div as u32;
r.brr().write_value(regs::Brr(((div << 1) & !0xF) | (div & 0x07)));
r.brr().write_value(regs::Brr(((brr << 1) & !0xF) | (brr & 0x07)));
#[cfg(usart_v4)]
r.presc().write(|w| w.set_prescaler(_presc_val));
found = Some(div);
found_brr = Some(brr);
break;
}
panic!("USART: baudrate too high");
}
if div < brr_max {
let div = div as u32;
r.brr().write_value(regs::Brr(div));
if brr < brr_max {
r.brr().write_value(regs::Brr(brr));
#[cfg(usart_v4)]
r.presc().write(|w| w.set_prescaler(_presc_val));
found = Some(div);
found_brr = Some(brr);
break;
}
}
let div = found.expect("USART: baudrate too low");
let brr = found_brr.expect("USART: baudrate too low");
#[cfg(not(usart_v1))]
let oversampling = if over8 { "8 bit" } else { "16 bit" };
@ -857,7 +869,7 @@ fn configure(r: Regs, config: &Config, pclk_freq: Hertz, kind: Kind, enable_rx:
"Using {} oversampling, desired baudrate: {}, actual baudrate: {}",
oversampling,
config.baudrate,
(pclk_freq.0 * mul as u32) / div
pclk_freq.0 / brr * mul
);
r.cr2().write(|w| {
@ -943,27 +955,27 @@ mod eh02 {
mod eh1 {
use super::*;
impl embedded_hal_1::serial::Error for Error {
fn kind(&self) -> embedded_hal_1::serial::ErrorKind {
impl embedded_hal_nb::serial::Error for Error {
fn kind(&self) -> embedded_hal_nb::serial::ErrorKind {
match *self {
Self::Framing => embedded_hal_1::serial::ErrorKind::FrameFormat,
Self::Noise => embedded_hal_1::serial::ErrorKind::Noise,
Self::Overrun => embedded_hal_1::serial::ErrorKind::Overrun,
Self::Parity => embedded_hal_1::serial::ErrorKind::Parity,
Self::BufferTooLong => embedded_hal_1::serial::ErrorKind::Other,
Self::Framing => embedded_hal_nb::serial::ErrorKind::FrameFormat,
Self::Noise => embedded_hal_nb::serial::ErrorKind::Noise,
Self::Overrun => embedded_hal_nb::serial::ErrorKind::Overrun,
Self::Parity => embedded_hal_nb::serial::ErrorKind::Parity,
Self::BufferTooLong => embedded_hal_nb::serial::ErrorKind::Other,
}
}
}
impl<'d, T: BasicInstance, TxDma, RxDma> embedded_hal_1::serial::ErrorType for Uart<'d, T, TxDma, RxDma> {
impl<'d, T: BasicInstance, TxDma, RxDma> embedded_hal_nb::serial::ErrorType for Uart<'d, T, TxDma, RxDma> {
type Error = Error;
}
impl<'d, T: BasicInstance, TxDma> embedded_hal_1::serial::ErrorType for UartTx<'d, T, TxDma> {
impl<'d, T: BasicInstance, TxDma> embedded_hal_nb::serial::ErrorType for UartTx<'d, T, TxDma> {
type Error = Error;
}
impl<'d, T: BasicInstance, RxDma> embedded_hal_1::serial::ErrorType for UartRx<'d, T, RxDma> {
impl<'d, T: BasicInstance, RxDma> embedded_hal_nb::serial::ErrorType for UartRx<'d, T, RxDma> {
type Error = Error;
}
@ -973,16 +985,6 @@ mod eh1 {
}
}
impl<'d, T: BasicInstance, TxDma> embedded_hal_1::serial::Write for UartTx<'d, T, TxDma> {
fn write(&mut self, buffer: &[u8]) -> Result<(), Self::Error> {
self.blocking_write(buffer)
}
fn flush(&mut self) -> Result<(), Self::Error> {
self.blocking_flush()
}
}
impl<'d, T: BasicInstance, TxDma> embedded_hal_nb::serial::Write for UartTx<'d, T, TxDma> {
fn write(&mut self, char: u8) -> nb::Result<(), Self::Error> {
self.blocking_write(&[char]).map_err(nb::Error::Other)
@ -999,16 +1001,6 @@ mod eh1 {
}
}
impl<'d, T: BasicInstance, TxDma, RxDma> embedded_hal_1::serial::Write for Uart<'d, T, TxDma, RxDma> {
fn write(&mut self, buffer: &[u8]) -> Result<(), Self::Error> {
self.blocking_write(buffer)
}
fn flush(&mut self) -> Result<(), Self::Error> {
self.blocking_flush()
}
}
impl<'d, T: BasicInstance, TxDma, RxDma> embedded_hal_nb::serial::Write for Uart<'d, T, TxDma, RxDma> {
fn write(&mut self, char: u8) -> nb::Result<(), Self::Error> {
self.blocking_write(&[char]).map_err(nb::Error::Other)