Merge branch 'master' of https://github.com/embassy-rs/embassy into embassy-stm32/rtc

This commit is contained in:
Mathias
2022-10-11 09:19:55 +02:00
85 changed files with 536 additions and 148 deletions

View File

@ -2,6 +2,7 @@
name = "embassy-stm32"
version = "0.1.0"
edition = "2021"
license = "MIT OR Apache-2.0"
[package.metadata.embassy_docs]
src_base = "https://github.com/embassy-rs/embassy/blob/embassy-stm32-v$VERSION/embassy-stm32/src/"
@ -44,6 +45,7 @@ embassy-usb-driver = {version = "0.1.0", path = "../embassy-usb-driver", optiona
embedded-hal-02 = { package = "embedded-hal", version = "0.2.6", features = ["unproven"] }
embedded-hal-1 = { package = "embedded-hal", version = "=1.0.0-alpha.9", optional = true}
embedded-hal-async = { version = "=0.1.0-alpha.2", optional = true}
embedded-hal-nb = { version = "=1.0.0-alpha.1", optional = true}
embedded-storage = "0.3.0"
embedded-storage-async = { version = "0.3.0", optional = true }
@ -103,7 +105,7 @@ unstable-pac = []
# Implement embedded-hal 1.0 alpha traits.
# Implement embedded-hal-async traits if `nightly` is set as well.
unstable-traits = ["embedded-hal-1"]
unstable-traits = ["embedded-hal-1", "dep:embedded-hal-nb"]
# BEGIN GENERATED FEATURES
# Generated by stm32-gen-features. DO NOT EDIT.

View File

@ -28,15 +28,20 @@ pub(crate) mod sealed {
pub trait AdcPin<T: Instance> {
fn channel(&self) -> u8;
}
pub trait InternalChannel<T> {
fn channel(&self) -> u8;
}
}
#[cfg(not(adc_f1))]
#[cfg(not(any(adc_f1, adc_v2)))]
pub trait Instance: sealed::Instance + 'static {}
#[cfg(adc_f1)]
#[cfg(any(adc_f1, adc_v2))]
pub trait Instance: sealed::Instance + crate::rcc::RccPeripheral + 'static {}
#[cfg(all(not(adc_f1), not(adc_v1)))]
pub trait Common: sealed::Common + 'static {}
pub trait AdcPin<T: Instance>: sealed::AdcPin<T> {}
pub trait InternalChannel<T>: sealed::InternalChannel<T> {}
#[cfg(not(stm32h7))]
foreach_peripheral!(

View File

@ -3,7 +3,9 @@ use core::marker::PhantomData;
use embassy_hal_common::into_ref;
use embedded_hal_02::blocking::delay::DelayUs;
use super::InternalChannel;
use crate::adc::{AdcPin, Instance};
use crate::peripherals::ADC1;
use crate::time::Hertz;
use crate::Peripheral;
@ -12,20 +14,8 @@ pub const VREF_DEFAULT_MV: u32 = 3300;
/// VREF voltage used for factory calibration of VREFINTCAL register.
pub const VREF_CALIB_MV: u32 = 3300;
#[cfg(not(any(rcc_f4, rcc_f7)))]
fn enable() {
todo!()
}
#[cfg(any(rcc_f4, rcc_f7))]
fn enable() {
critical_section::with(|_| unsafe {
// TODO do not enable all adc clocks if not needed
crate::pac::RCC.apb2enr().modify(|w| w.set_adc1en(true));
crate::pac::RCC.apb2enr().modify(|w| w.set_adc2en(true));
crate::pac::RCC.apb2enr().modify(|w| w.set_adc3en(true));
});
}
/// ADC turn-on time
pub const ADC_POWERUP_TIME_US: u32 = 3;
pub enum Resolution {
TwelveBit,
@ -61,24 +51,53 @@ impl Resolution {
}
pub struct VrefInt;
impl<T: Instance> AdcPin<T> for VrefInt {}
impl<T: Instance> super::sealed::AdcPin<T> for VrefInt {
impl InternalChannel<ADC1> for VrefInt {}
impl super::sealed::InternalChannel<ADC1> for VrefInt {
fn channel(&self) -> u8 {
17
}
}
impl VrefInt {
/// Time needed for internal voltage reference to stabilize
pub fn start_time_us() -> u32 {
10
}
}
pub struct Temperature;
impl<T: Instance> AdcPin<T> for Temperature {}
impl<T: Instance> super::sealed::AdcPin<T> for Temperature {
impl InternalChannel<ADC1> for Temperature {}
impl super::sealed::InternalChannel<ADC1> for Temperature {
fn channel(&self) -> u8 {
16
cfg_if::cfg_if! {
if #[cfg(any(stm32f40, stm32f41))] {
16
} else {
18
}
}
}
}
impl Temperature {
/// Converts temperature sensor reading in millivolts to degrees celcius
pub fn to_celcius(sample_mv: u16) -> f32 {
// From 6.3.22 Temperature sensor characteristics
const V25: i32 = 760; // mV
const AVG_SLOPE: f32 = 2.5; // mV/C
(sample_mv as i32 - V25) as f32 / AVG_SLOPE + 25.0
}
/// Time needed for temperature sensor readings to stabilize
pub fn start_time_us() -> u32 {
10
}
}
pub struct Vbat;
impl<T: Instance> AdcPin<T> for Vbat {}
impl<T: Instance> super::sealed::AdcPin<T> for Vbat {
impl InternalChannel<ADC1> for Vbat {}
impl super::sealed::InternalChannel<ADC1> for Vbat {
fn channel(&self) -> u8 {
18
}
@ -164,21 +183,19 @@ where
{
pub fn new(_peri: impl Peripheral<P = T> + 'd, delay: &mut impl DelayUs<u32>) -> Self {
into_ref!(_peri);
enable();
T::enable();
T::reset();
let presc = unsafe { Prescaler::from_pclk2(crate::rcc::get_freqs().apb2) };
let presc = Prescaler::from_pclk2(T::frequency());
unsafe {
T::common_regs().ccr().modify(|w| w.set_adcpre(presc.adcpre()));
}
unsafe {
// disable before config is set
T::regs().cr2().modify(|reg| {
reg.set_adon(crate::pac::adc::vals::Adon::DISABLED);
reg.set_adon(crate::pac::adc::vals::Adon::ENABLED);
});
}
delay.delay_us(20); // TODO?
delay.delay_us(ADC_POWERUP_TIME_US);
Self {
sample_time: Default::default(),
@ -208,6 +225,45 @@ where
((u32::from(sample) * self.vref_mv) / self.resolution.to_max_count()) as u16
}
/// Enables internal voltage reference and returns [VrefInt], which can be used in
/// [Adc::read_internal()] to perform conversion.
pub fn enable_vrefint(&self) -> VrefInt {
unsafe {
T::common_regs().ccr().modify(|reg| {
reg.set_tsvrefe(crate::pac::adccommon::vals::Tsvrefe::ENABLED);
});
}
VrefInt {}
}
/// Enables internal temperature sensor and returns [Temperature], which can be used in
/// [Adc::read_internal()] to perform conversion.
///
/// On STM32F42 and STM32F43 this can not be used together with [Vbat]. If both are enabled,
/// temperature sensor will return vbat value.
pub fn enable_temperature(&self) -> Temperature {
unsafe {
T::common_regs().ccr().modify(|reg| {
reg.set_tsvrefe(crate::pac::adccommon::vals::Tsvrefe::ENABLED);
});
}
Temperature {}
}
/// Enables vbat input and returns [Vbat], which can be used in
/// [Adc::read_internal()] to perform conversion.
pub fn enable_vbat(&self) -> Vbat {
unsafe {
T::common_regs().ccr().modify(|reg| {
reg.set_vbate(crate::pac::adccommon::vals::Vbate::ENABLED);
});
}
Vbat {}
}
/// Perform a single conversion.
fn convert(&mut self) -> u16 {
unsafe {
@ -238,44 +294,31 @@ where
P: crate::gpio::sealed::Pin,
{
unsafe {
// dissable ADC
T::regs().cr2().modify(|reg| {
reg.set_swstart(false);
});
T::regs().cr2().modify(|reg| {
reg.set_adon(crate::pac::adc::vals::Adon::DISABLED);
});
pin.set_as_analog();
// Configure ADC
T::regs().cr1().modify(|reg| reg.set_res(self.resolution.res()));
// Select channel
T::regs().sqr3().write(|reg| reg.set_sq(0, pin.channel()));
// Configure channel
Self::set_channel_sample_time(pin.channel(), self.sample_time);
// enable adc
T::regs().cr2().modify(|reg| {
reg.set_adon(crate::pac::adc::vals::Adon::ENABLED);
});
let val = self.convert();
// dissable ADC
T::regs().cr2().modify(|reg| {
reg.set_swstart(false);
});
T::regs().cr2().modify(|reg| {
reg.set_adon(crate::pac::adc::vals::Adon::DISABLED);
});
val
self.read_channel(pin.channel())
}
}
pub fn read_internal(&mut self, channel: &mut impl InternalChannel<T>) -> u16 {
unsafe { self.read_channel(channel.channel()) }
}
unsafe fn read_channel(&mut self, channel: u8) -> u16 {
// Configure ADC
T::regs().cr1().modify(|reg| reg.set_res(self.resolution.res()));
// Select channel
T::regs().sqr3().write(|reg| reg.set_sq(0, channel));
// Configure channel
Self::set_channel_sample_time(channel, self.sample_time);
let val = self.convert();
val
}
unsafe fn set_channel_sample_time(ch: u8, sample_time: SampleTime) {
if ch <= 9 {
T::regs()
@ -288,3 +331,9 @@ where
}
}
}
impl<'d, T: Instance> Drop for Adc<'d, T> {
fn drop(&mut self) {
T::disable();
}
}

View File

@ -5,7 +5,7 @@ use embedded_hal_02::blocking::delay::DelayUs;
use pac::adc::vals::{Adcaldif, Boost, Difsel, Exten, Pcsel};
use pac::adccommon::vals::Presc;
use super::{AdcPin, Instance};
use super::{AdcPin, Instance, InternalChannel};
use crate::time::Hertz;
use crate::{pac, Peripheral};
@ -50,18 +50,10 @@ impl Resolution {
}
}
pub trait InternalChannel<T>: sealed::InternalChannel<T> {}
mod sealed {
pub trait InternalChannel<T> {
fn channel(&self) -> u8;
}
}
// NOTE: Vrefint/Temperature/Vbat are only available on ADC3 on H7, this currently cannot be modeled with stm32-data, so these are available from the software on all ADCs
pub struct VrefInt;
impl<T: Instance> InternalChannel<T> for VrefInt {}
impl<T: Instance> sealed::InternalChannel<T> for VrefInt {
impl<T: Instance> super::sealed::InternalChannel<T> for VrefInt {
fn channel(&self) -> u8 {
19
}
@ -69,7 +61,7 @@ impl<T: Instance> sealed::InternalChannel<T> for VrefInt {
pub struct Temperature;
impl<T: Instance> InternalChannel<T> for Temperature {}
impl<T: Instance> sealed::InternalChannel<T> for Temperature {
impl<T: Instance> super::sealed::InternalChannel<T> for Temperature {
fn channel(&self) -> u8 {
18
}
@ -77,7 +69,7 @@ impl<T: Instance> sealed::InternalChannel<T> for Temperature {
pub struct Vbat;
impl<T: Instance> InternalChannel<T> for Vbat {}
impl<T: Instance> sealed::InternalChannel<T> for Vbat {
impl<T: Instance> super::sealed::InternalChannel<T> for Vbat {
fn channel(&self) -> u8 {
// TODO this should be 14 for H7a/b/35
17

View File

@ -23,17 +23,6 @@ impl<'d> Flash<'d> {
Self { _inner: p }
}
pub fn unlock(p: impl Peripheral<P = FLASH> + 'd) -> Self {
let flash = Self::new(p);
unsafe { family::unlock() };
flash
}
pub fn lock(&mut self) {
unsafe { family::lock() };
}
pub fn blocking_read(&mut self, offset: u32, bytes: &mut [u8]) -> Result<(), Error> {
let offset = FLASH_BASE as u32 + offset;
if offset as usize >= FLASH_END || offset as usize + bytes.len() > FLASH_END {
@ -57,7 +46,12 @@ impl<'d> Flash<'d> {
self.clear_all_err();
unsafe { family::blocking_write(offset, buf) }
unsafe {
family::unlock();
let res = family::blocking_write(offset, buf);
family::lock();
res
}
}
pub fn blocking_erase(&mut self, from: u32, to: u32) -> Result<(), Error> {
@ -72,7 +66,12 @@ impl<'d> Flash<'d> {
self.clear_all_err();
unsafe { family::blocking_erase(from, to) }
unsafe {
family::unlock();
let res = family::blocking_erase(from, to);
family::lock();
res
}
}
fn clear_all_err(&mut self) {
@ -82,7 +81,7 @@ impl<'d> Flash<'d> {
impl Drop for Flash<'_> {
fn drop(&mut self) {
self.lock();
unsafe { family::lock() };
}
}

View File

@ -160,6 +160,30 @@ impl<'d, T: BasicInstance, RxDma> UartRx<'d, T, RxDma> {
Ok(())
}
pub fn nb_read(&mut self) -> Result<u8, nb::Error<Error>> {
let r = T::regs();
unsafe {
let sr = sr(r).read();
if sr.pe() {
rdr(r).read_volatile();
Err(nb::Error::Other(Error::Parity))
} else if sr.fe() {
rdr(r).read_volatile();
Err(nb::Error::Other(Error::Framing))
} else if sr.ne() {
rdr(r).read_volatile();
Err(nb::Error::Other(Error::Noise))
} else if sr.ore() {
rdr(r).read_volatile();
Err(nb::Error::Other(Error::Overrun))
} else if sr.rxne() {
Ok(rdr(r).read_volatile())
} else {
Err(nb::Error::WouldBlock)
}
}
}
pub fn blocking_read(&mut self, buffer: &mut [u8]) -> Result<(), Error> {
unsafe {
let r = T::regs();
@ -263,6 +287,10 @@ impl<'d, T: BasicInstance, TxDma, RxDma> Uart<'d, T, TxDma, RxDma> {
self.rx.read(buffer).await
}
pub fn nb_read(&mut self) -> Result<u8, nb::Error<Error>> {
self.rx.nb_read()
}
pub fn blocking_read(&mut self, buffer: &mut [u8]) -> Result<(), Error> {
self.rx.blocking_read(buffer)
}
@ -281,27 +309,7 @@ mod eh02 {
impl<'d, T: BasicInstance, RxDma> embedded_hal_02::serial::Read<u8> for UartRx<'d, T, RxDma> {
type Error = Error;
fn read(&mut self) -> Result<u8, nb::Error<Self::Error>> {
let r = T::regs();
unsafe {
let sr = sr(r).read();
if sr.pe() {
rdr(r).read_volatile();
Err(nb::Error::Other(Error::Parity))
} else if sr.fe() {
rdr(r).read_volatile();
Err(nb::Error::Other(Error::Framing))
} else if sr.ne() {
rdr(r).read_volatile();
Err(nb::Error::Other(Error::Noise))
} else if sr.ore() {
rdr(r).read_volatile();
Err(nb::Error::Other(Error::Overrun))
} else if sr.rxne() {
Ok(rdr(r).read_volatile())
} else {
Err(nb::Error::WouldBlock)
}
}
self.nb_read()
}
}
@ -318,7 +326,7 @@ mod eh02 {
impl<'d, T: BasicInstance, TxDma, RxDma> embedded_hal_02::serial::Read<u8> for Uart<'d, T, TxDma, RxDma> {
type Error = Error;
fn read(&mut self) -> Result<u8, nb::Error<Self::Error>> {
embedded_hal_02::serial::Read::read(&mut self.rx)
self.nb_read()
}
}
@ -359,6 +367,58 @@ mod eh1 {
impl<'d, T: BasicInstance, RxDma> embedded_hal_1::serial::ErrorType for UartRx<'d, T, RxDma> {
type Error = Error;
}
impl<'d, T: BasicInstance, RxDma> embedded_hal_nb::serial::Read for UartRx<'d, T, RxDma> {
fn read(&mut self) -> nb::Result<u8, Self::Error> {
self.nb_read()
}
}
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)
}
fn flush(&mut self) -> nb::Result<(), Self::Error> {
self.blocking_flush().map_err(nb::Error::Other)
}
}
impl<'d, T: BasicInstance, TxDma, RxDma> embedded_hal_nb::serial::Read for Uart<'d, T, TxDma, RxDma> {
fn read(&mut self) -> Result<u8, nb::Error<Self::Error>> {
self.nb_read()
}
}
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)
}
fn flush(&mut self) -> nb::Result<(), Self::Error> {
self.blocking_flush().map_err(nb::Error::Other)
}
}
}
#[cfg(all(