Merge branch 'main' of https://github.com/embassy-rs/embassy into rtc-lp
This commit is contained in:
@ -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"]
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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) => {
|
||||
|
@ -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.")]
|
||||
|
@ -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> {
|
||||
|
@ -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) {
|
||||
|
@ -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) {
|
||||
|
@ -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 {
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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"
|
||||
)]
|
||||
|
@ -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,
|
||||
|
@ -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));
|
||||
|
@ -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
|
||||
|
@ -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")]
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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() {}
|
||||
|
@ -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 {
|
||||
*[
|
||||
|
@ -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);
|
||||
|
@ -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));
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
@ -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)
|
||||
|
@ -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)
|
||||
|
Reference in New Issue
Block a user