Merge pull request #367 from embassy-rs/metapac-cleanup

stm32-metapac cleanups
This commit is contained in:
Dario Nieuwenhuis 2021-08-20 00:05:08 +02:00 committed by GitHub
commit 8e5f1f4b5e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
59 changed files with 507 additions and 917 deletions

1
.gitignore vendored
View File

@ -2,3 +2,4 @@ target
Cargo.lock
third_party
/Cargo.toml
stm32-metapac-gen/out/

View File

@ -1,6 +1,6 @@
use std::env;
use std::fs;
use std::path::PathBuf;
use std::process::Command;
fn main() {
let chip_name = env::vars_os()
@ -11,17 +11,72 @@ fn main() {
.unwrap()
.to_ascii_lowercase();
struct Peripheral {
kind: String,
name: String,
}
let mut peripherals: Vec<Peripheral> = Vec::new();
stm32_metapac::peripherals!(
($kind:ident, $name:ident) => {
peripherals.push(Peripheral{
kind: stringify!($kind).to_string(),
name: stringify!($name).to_string(),
});
};
);
let mut singletons: Vec<String> = Vec::new();
for p in peripherals {
match p.kind.as_str() {
// Generate singletons per pin, not per port
"gpio" => {
println!("{}", p.name);
let port_letter = p.name.strip_prefix("GPIO").unwrap();
for pin_num in 0..16 {
singletons.push(format!("P{}{}", port_letter, pin_num));
}
}
// No singleton for these, the HAL handles them specially.
"exti" => {}
// We *shouldn't* have singletons for these, but the HAL currently requires
// singletons, for using with RccPeripheral to enable/disable clocks to them.
//"rcc" => {}
//"dbgmcu" => {}
//"syscfg" => {}
//"dma" => {}
//"bdma" => {}
//"dmamux" => {}
// For other peripherals, one singleton per peri
_ => singletons.push(p.name.clone()),
}
}
// One singleton per EXTI line
for pin_num in 0..16 {
singletons.push(format!("EXTI{}", pin_num));
}
// One singleton per DMA channel
stm32_metapac::dma_channels! {
($channel_peri:ident, $dma_peri:ident, $version:ident, $channel_num:expr, $ignore:tt) => {
singletons.push(stringify!($channel_peri).to_string());
};
}
let out_dir = &PathBuf::from(env::var_os("OUT_DIR").unwrap());
let out_file = out_dir.join("generated.rs").to_string_lossy().to_string();
let exit_code = Command::new("python3")
.args(&["gen.py", &chip_name, &out_file])
.status()
.expect("failed to execute gen.py");
if !exit_code.success() {
panic!("gen.py exited with {:?}", exit_code)
}
fs::write(
out_file,
format!(
"embassy_hal_common::peripherals!({});",
singletons.join(",")
),
)
.unwrap();
stm32_metapac::peripheral_versions!(
($peri:ident, $version:ident) => {

View File

@ -1,88 +0,0 @@
import sys
import yaml
import re
import os
import re
try:
from yaml import CSafeLoader as SafeLoader
except ImportError:
from yaml import SafeLoader
abspath = os.path.abspath(__file__)
dname = os.path.dirname(abspath)
os.chdir(dname)
data_path = '../stm32-data/data'
try:
_, chip_name, output_file = sys.argv
except:
raise Exception("Usage: gen.py STM32F429ZI_CM0 path/to/generated.rs")
c = chip_name.split('_', 1)
chip_name = c[0].upper()
core_name = None
if len(c) > 1:
core_name = c[1].lower()
# ======= load chip
with open(f'{data_path}/chips/{chip_name}.yaml', 'r') as f:
chip = yaml.load(f, Loader=SafeLoader)
# ======= Generate!
with open(output_file, 'w') as f:
singletons = [] # USART1, PA5, EXTI8
exti_interrupts = [] # EXTI IRQs, EXTI0, EXTI4_15 etc.
pins = set() # set of all present pins. PA4, PA5...
# ========= peripherals
singletons.extend((f'EXTI{x}' for x in range(16)))
num_dmas = 0
core = chip['cores'][0]
if core_name != None:
for c in chip['cores']:
if core_name == c['name']:
core = c
for (name, peri) in core['peripherals'].items():
if 'block' not in peri:
continue
block = peri['block']
block_mod, block_name_unparsed = block.rsplit('/')
block_mod, block_version = block_mod.rsplit('_')
block_name = ''
for b in block_name_unparsed.split('_'):
block_name += b.capitalize()
custom_singletons = False
if block_mod == 'gpio':
custom_singletons = True
port = name[4:]
port_num = ord(port) - ord('A')
for pin_num in range(16):
pin = f'P{port}{pin_num}'
pins.add(pin)
singletons.append(pin)
# if block_mod == 'dma':
# custom_singletons = True
# for ch_num in range(8):
# channel = f'{name}_CH{ch_num}'
# singletons.append(channel)
if not custom_singletons:
singletons.append(name)
for (channel_id, defn) in core['dma_channels'].items():
singletons.append( channel_id )
f.write(f"embassy_hal_common::peripherals!({','.join(singletons)});")

270
embassy-stm32/src/exti.rs Normal file
View File

@ -0,0 +1,270 @@
use core::convert::Infallible;
use core::future::Future;
use core::marker::PhantomData;
use core::pin::Pin;
use core::task::{Context, Poll};
use embassy::traits::gpio::{WaitForAnyEdge, WaitForFallingEdge, WaitForRisingEdge};
use embassy::util::{AtomicWaker, Unborrow};
use embassy_hal_common::unsafe_impl_unborrow;
use embedded_hal::digital::v2::InputPin;
use crate::gpio::{AnyPin, Input, Pin as GpioPin};
use crate::interrupt;
use crate::pac;
use crate::pac::{EXTI, SYSCFG};
use crate::peripherals;
const EXTI_COUNT: usize = 16;
const NEW_AW: AtomicWaker = AtomicWaker::new();
static EXTI_WAKERS: [AtomicWaker; EXTI_COUNT] = [NEW_AW; EXTI_COUNT];
#[cfg(exti_w)]
fn cpu_regs() -> pac::exti::Cpu {
EXTI.cpu(crate::pac::CORE_INDEX)
}
#[cfg(not(exti_w))]
fn cpu_regs() -> pac::exti::Exti {
EXTI
}
pub unsafe fn on_irq() {
let bits = EXTI.pr(0).read();
// Mask all the channels that fired.
cpu_regs().imr(0).modify(|w| w.0 &= !bits.0);
// Wake the tasks
for pin in BitIter(bits.0) {
EXTI_WAKERS[pin as usize].wake();
}
// Clear pending
EXTI.pr(0).write_value(bits);
}
struct BitIter(u32);
impl Iterator for BitIter {
type Item = u32;
fn next(&mut self) -> Option<Self::Item> {
match self.0.trailing_zeros() {
32 => None,
b => {
self.0 &= !(1 << b);
Some(b)
}
}
}
}
/// EXTI input driver
pub struct ExtiInput<'d, T: GpioPin> {
pin: Input<'d, T>,
}
impl<'d, T: GpioPin> Unpin for ExtiInput<'d, T> {}
impl<'d, T: GpioPin> ExtiInput<'d, T> {
pub fn new(pin: Input<'d, T>, _ch: impl Unborrow<Target = T::ExtiChannel> + 'd) -> Self {
Self { pin }
}
}
impl<'d, T: GpioPin> InputPin for ExtiInput<'d, T> {
type Error = Infallible;
fn is_high(&self) -> Result<bool, Self::Error> {
self.pin.is_high()
}
fn is_low(&self) -> Result<bool, Self::Error> {
self.pin.is_low()
}
}
impl<'d, T: GpioPin> WaitForRisingEdge for ExtiInput<'d, T> {
type Future<'a> = ExtiInputFuture<'a>;
fn wait_for_rising_edge<'a>(&'a mut self) -> Self::Future<'a> {
ExtiInputFuture::new(self.pin.pin.pin(), self.pin.pin.port(), true, false)
}
}
impl<'d, T: GpioPin> WaitForFallingEdge for ExtiInput<'d, T> {
type Future<'a> = ExtiInputFuture<'a>;
fn wait_for_falling_edge<'a>(&'a mut self) -> Self::Future<'a> {
ExtiInputFuture::new(self.pin.pin.pin(), self.pin.pin.port(), false, true)
}
}
impl<'d, T: GpioPin> WaitForAnyEdge for ExtiInput<'d, T> {
type Future<'a> = ExtiInputFuture<'a>;
fn wait_for_any_edge<'a>(&'a mut self) -> Self::Future<'a> {
ExtiInputFuture::new(self.pin.pin.pin(), self.pin.pin.port(), true, true)
}
}
pub struct ExtiInputFuture<'a> {
pin: u8,
phantom: PhantomData<&'a mut AnyPin>,
}
impl<'a> ExtiInputFuture<'a> {
fn new(pin: u8, port: u8, rising: bool, falling: bool) -> Self {
cortex_m::interrupt::free(|_| unsafe {
let pin = pin as usize;
SYSCFG.exticr(pin / 4).modify(|w| w.set_exti(pin % 4, port));
EXTI.rtsr(0).modify(|w| w.set_line(pin, rising));
EXTI.ftsr(0).modify(|w| w.set_line(pin, falling));
EXTI.pr(0).write(|w| w.set_line(pin, true)); // clear pending bit
cpu_regs().imr(0).modify(|w| w.set_line(pin, true));
});
Self {
pin,
phantom: PhantomData,
}
}
}
impl<'a> Drop for ExtiInputFuture<'a> {
fn drop(&mut self) {
cortex_m::interrupt::free(|_| unsafe {
let pin = self.pin as _;
cpu_regs().imr(0).modify(|w| w.set_line(pin, false));
});
}
}
impl<'a> Future for ExtiInputFuture<'a> {
type Output = ();
fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
EXTI_WAKERS[self.pin as usize].register(cx.waker());
let imr = unsafe { cpu_regs().imr(0).read() };
if !imr.line(self.pin as _) {
Poll::Ready(())
} else {
Poll::Pending
}
}
}
macro_rules! foreach_exti_irq {
($action:ident) => {
crate::pac::interrupts!(
(EXTI0) => { $action!(EXTI0); };
(EXTI1) => { $action!(EXTI1); };
(EXTI2) => { $action!(EXTI2); };
(EXTI3) => { $action!(EXTI3); };
(EXTI4) => { $action!(EXTI4); };
(EXTI5) => { $action!(EXTI5); };
(EXTI6) => { $action!(EXTI6); };
(EXTI7) => { $action!(EXTI7); };
(EXTI8) => { $action!(EXTI8); };
(EXTI9) => { $action!(EXTI9); };
(EXTI10) => { $action!(EXTI10); };
(EXTI11) => { $action!(EXTI11); };
(EXTI12) => { $action!(EXTI12); };
(EXTI13) => { $action!(EXTI13); };
(EXTI14) => { $action!(EXTI14); };
(EXTI15) => { $action!(EXTI15); };
// plus the weird ones
(EXTI0_1) => { $action!( EXTI0_1 ); };
(EXTI15_10) => { $action!(EXTI15_10); };
(EXTI15_4) => { $action!(EXTI15_4); };
(EXTI1_0) => { $action!(EXTI1_0); };
(EXTI2_3) => { $action!(EXTI2_3); };
(EXTI2_TSC) => { $action!(EXTI2_TSC); };
(EXTI3_2) => { $action!(EXTI3_2); };
(EXTI4_15) => { $action!(EXTI4_15); };
(EXTI9_5) => { $action!(EXTI9_5); };
);
};
}
macro_rules! impl_irq {
($e:ident) => {
#[interrupt]
unsafe fn $e() {
on_irq()
}
};
}
foreach_exti_irq!(impl_irq);
pub(crate) mod sealed {
pub trait Channel {}
}
pub trait Channel: sealed::Channel + Sized {
fn number(&self) -> usize;
fn degrade(self) -> AnyChannel {
AnyChannel {
number: self.number() as u8,
}
}
}
pub struct AnyChannel {
number: u8,
}
unsafe_impl_unborrow!(AnyChannel);
impl sealed::Channel for AnyChannel {}
impl Channel for AnyChannel {
fn number(&self) -> usize {
self.number as usize
}
}
macro_rules! impl_exti {
($type:ident, $number:expr) => {
impl sealed::Channel for peripherals::$type {}
impl Channel for peripherals::$type {
fn number(&self) -> usize {
$number as usize
}
}
};
}
impl_exti!(EXTI0, 0);
impl_exti!(EXTI1, 1);
impl_exti!(EXTI2, 2);
impl_exti!(EXTI3, 3);
impl_exti!(EXTI4, 4);
impl_exti!(EXTI5, 5);
impl_exti!(EXTI6, 6);
impl_exti!(EXTI7, 7);
impl_exti!(EXTI8, 8);
impl_exti!(EXTI9, 9);
impl_exti!(EXTI10, 10);
impl_exti!(EXTI11, 11);
impl_exti!(EXTI12, 12);
impl_exti!(EXTI13, 13);
impl_exti!(EXTI14, 14);
impl_exti!(EXTI15, 15);
macro_rules! enable_irq {
($e:ident) => {
crate::interrupt::$e::steal().enable();
};
}
/// safety: must be called only once
pub(crate) unsafe fn init() {
use embassy::interrupt::Interrupt;
use embassy::interrupt::InterruptExt;
foreach_exti_irq!(enable_irq);
#[cfg(not(any(rcc_wb, rcc_wl5)))]
<crate::peripherals::SYSCFG as crate::rcc::sealed::RccPeripheral>::enable();
}

View File

@ -1,116 +0,0 @@
#![macro_use]
macro_rules! foreach_exti_irq {
($action:ident) => {
crate::pac::interrupts!(
(EXTI0) => { $action!(EXTI0); };
(EXTI1) => { $action!(EXTI1); };
(EXTI2) => { $action!(EXTI2); };
(EXTI3) => { $action!(EXTI3); };
(EXTI4) => { $action!(EXTI4); };
(EXTI5) => { $action!(EXTI5); };
(EXTI6) => { $action!(EXTI6); };
(EXTI7) => { $action!(EXTI7); };
(EXTI8) => { $action!(EXTI8); };
(EXTI9) => { $action!(EXTI9); };
(EXTI10) => { $action!(EXTI10); };
(EXTI11) => { $action!(EXTI11); };
(EXTI12) => { $action!(EXTI12); };
(EXTI13) => { $action!(EXTI13); };
(EXTI14) => { $action!(EXTI14); };
(EXTI15) => { $action!(EXTI15); };
// plus the weird ones
(EXTI0_1) => { $action!( EXTI0_1 ); };
(EXTI15_10) => { $action!(EXTI15_10); };
(EXTI15_4) => { $action!(EXTI15_4); };
(EXTI1_0) => { $action!(EXTI1_0); };
(EXTI2_3) => { $action!(EXTI2_3); };
(EXTI2_TSC) => { $action!(EXTI2_TSC); };
(EXTI3_2) => { $action!(EXTI3_2); };
(EXTI4_15) => { $action!(EXTI4_15); };
(EXTI9_5) => { $action!(EXTI9_5); };
);
};
}
#[cfg_attr(exti_v1, path = "v1.rs")]
#[cfg_attr(exti_h7, path = "v1.rs")]
#[cfg_attr(exti_wb55, path = "v2.rs")]
#[cfg_attr(exti_wl5x, path = "v2.rs")]
mod _version;
#[allow(unused)]
pub use _version::*;
use crate::peripherals;
use embassy_hal_common::unsafe_impl_unborrow;
pub(crate) mod sealed {
pub trait Channel {}
}
pub trait Channel: sealed::Channel + Sized {
fn number(&self) -> usize;
fn degrade(self) -> AnyChannel {
AnyChannel {
number: self.number() as u8,
}
}
}
pub struct AnyChannel {
number: u8,
}
unsafe_impl_unborrow!(AnyChannel);
impl sealed::Channel for AnyChannel {}
impl Channel for AnyChannel {
fn number(&self) -> usize {
self.number as usize
}
}
macro_rules! impl_exti {
($type:ident, $number:expr) => {
impl sealed::Channel for peripherals::$type {}
impl Channel for peripherals::$type {
fn number(&self) -> usize {
$number as usize
}
}
};
}
impl_exti!(EXTI0, 0);
impl_exti!(EXTI1, 1);
impl_exti!(EXTI2, 2);
impl_exti!(EXTI3, 3);
impl_exti!(EXTI4, 4);
impl_exti!(EXTI5, 5);
impl_exti!(EXTI6, 6);
impl_exti!(EXTI7, 7);
impl_exti!(EXTI8, 8);
impl_exti!(EXTI9, 9);
impl_exti!(EXTI10, 10);
impl_exti!(EXTI11, 11);
impl_exti!(EXTI12, 12);
impl_exti!(EXTI13, 13);
impl_exti!(EXTI14, 14);
impl_exti!(EXTI15, 15);
macro_rules! enable_irq {
($e:ident) => {
crate::interrupt::$e::steal().enable();
};
}
/// safety: must be called only once
pub(crate) unsafe fn init() {
use embassy::interrupt::Interrupt;
use embassy::interrupt::InterruptExt;
foreach_exti_irq!(enable_irq);
#[cfg(not(any(rcc_wb55, rcc_wl5x)))]
<crate::peripherals::SYSCFG as crate::rcc::sealed::RccPeripheral>::enable();
}

View File

@ -1,171 +0,0 @@
use core::convert::Infallible;
use core::future::Future;
use core::marker::PhantomData;
use core::pin::Pin;
use core::task::{Context, Poll};
use embassy::traits::gpio::{WaitForAnyEdge, WaitForFallingEdge, WaitForRisingEdge};
use embassy::util::{AtomicWaker, Unborrow};
use embedded_hal::digital::v2::InputPin;
use pac::exti::{regs, vals};
use crate::gpio::{AnyPin, Input, Pin as GpioPin};
use crate::pac;
use crate::pac::{EXTI, SYSCFG};
const EXTI_COUNT: usize = 16;
const NEW_AW: AtomicWaker = AtomicWaker::new();
static EXTI_WAKERS: [AtomicWaker; EXTI_COUNT] = [NEW_AW; EXTI_COUNT];
pub unsafe fn on_irq() {
let bits = EXTI.pr().read().0;
// Mask all the channels that fired.
EXTI.imr().modify(|w| w.0 &= !bits);
// Wake the tasks
for pin in BitIter(bits) {
EXTI_WAKERS[pin as usize].wake();
}
// Clear pending
EXTI.pr().write_value(regs::Pr(bits));
}
struct BitIter(u32);
impl Iterator for BitIter {
type Item = u32;
fn next(&mut self) -> Option<Self::Item> {
match self.0.trailing_zeros() {
32 => None,
b => {
self.0 &= !(1 << b);
Some(b)
}
}
}
}
/// EXTI input driver
pub struct ExtiInput<'d, T: GpioPin> {
pin: Input<'d, T>,
}
impl<'d, T: GpioPin> Unpin for ExtiInput<'d, T> {}
impl<'d, T: GpioPin> ExtiInput<'d, T> {
pub fn new(pin: Input<'d, T>, _ch: impl Unborrow<Target = T::ExtiChannel> + 'd) -> Self {
Self { pin }
}
}
impl<'d, T: GpioPin> InputPin for ExtiInput<'d, T> {
type Error = Infallible;
fn is_high(&self) -> Result<bool, Self::Error> {
self.pin.is_high()
}
fn is_low(&self) -> Result<bool, Self::Error> {
self.pin.is_low()
}
}
impl<'d, T: GpioPin> WaitForRisingEdge for ExtiInput<'d, T> {
type Future<'a> = ExtiInputFuture<'a>;
fn wait_for_rising_edge<'a>(&'a mut self) -> Self::Future<'a> {
ExtiInputFuture::new(
self.pin.pin.pin(),
self.pin.pin.port(),
vals::Tr::ENABLED,
vals::Tr::DISABLED,
)
}
}
impl<'d, T: GpioPin> WaitForFallingEdge for ExtiInput<'d, T> {
type Future<'a> = ExtiInputFuture<'a>;
fn wait_for_falling_edge<'a>(&'a mut self) -> Self::Future<'a> {
ExtiInputFuture::new(
self.pin.pin.pin(),
self.pin.pin.port(),
vals::Tr::DISABLED,
vals::Tr::ENABLED,
)
}
}
impl<'d, T: GpioPin> WaitForAnyEdge for ExtiInput<'d, T> {
type Future<'a> = ExtiInputFuture<'a>;
fn wait_for_any_edge<'a>(&'a mut self) -> Self::Future<'a> {
ExtiInputFuture::new(
self.pin.pin.pin(),
self.pin.pin.port(),
vals::Tr::ENABLED,
vals::Tr::ENABLED,
)
}
}
pub struct ExtiInputFuture<'a> {
pin: u8,
phantom: PhantomData<&'a mut AnyPin>,
}
impl<'a> ExtiInputFuture<'a> {
fn new(pin: u8, port: u8, rising: vals::Tr, falling: vals::Tr) -> Self {
cortex_m::interrupt::free(|_| unsafe {
let pin = pin as usize;
SYSCFG.exticr(pin / 4).modify(|w| w.set_exti(pin % 4, port));
EXTI.rtsr().modify(|w| w.set_tr(pin, rising));
EXTI.ftsr().modify(|w| w.set_tr(pin, falling));
EXTI.pr().write(|w| w.set_pr(pin, true)); // clear pending bit
EXTI.imr().modify(|w| w.set_mr(pin, vals::Mr::UNMASKED));
});
Self {
pin,
phantom: PhantomData,
}
}
}
impl<'a> Drop for ExtiInputFuture<'a> {
fn drop(&mut self) {
cortex_m::interrupt::free(|_| unsafe {
let pin = self.pin as _;
EXTI.imr().modify(|w| w.set_mr(pin, vals::Mr::MASKED));
});
}
}
impl<'a> Future for ExtiInputFuture<'a> {
type Output = ();
fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
EXTI_WAKERS[self.pin as usize].register(cx.waker());
if unsafe { EXTI.imr().read().mr(self.pin as _) == vals::Mr::MASKED } {
Poll::Ready(())
} else {
Poll::Pending
}
}
}
use crate::interrupt;
macro_rules! impl_irq {
($e:ident) => {
#[interrupt]
unsafe fn $e() {
on_irq()
}
};
}
foreach_exti_irq!(impl_irq);

View File

@ -1,184 +0,0 @@
use core::convert::Infallible;
use core::future::Future;
use core::marker::PhantomData;
use core::pin::Pin;
use core::task::{Context, Poll};
use embassy::traits::gpio::{WaitForAnyEdge, WaitForFallingEdge, WaitForRisingEdge};
use embassy::util::{AtomicWaker, Unborrow};
use embedded_hal::digital::v2::InputPin;
use pac::exti::{regs, vals};
use crate::gpio::{AnyPin, Input, Pin as GpioPin};
use crate::pac;
use crate::pac::CORE_INDEX;
use crate::pac::{EXTI, SYSCFG};
const EXTI_COUNT: usize = 16;
const NEW_AW: AtomicWaker = AtomicWaker::new();
static EXTI_WAKERS: [AtomicWaker; EXTI_COUNT] = [NEW_AW; EXTI_COUNT];
pub unsafe fn on_irq() {
let bits = EXTI.pr(0).read().0;
// Mask all the channels that fired.
EXTI.cpu(CORE_INDEX)
.imr(CORE_INDEX)
.modify(|w| w.0 &= !bits);
// Wake the tasks
for pin in BitIter(bits) {
EXTI_WAKERS[pin as usize].wake();
}
// Clear pending
EXTI.pr(0).write_value(regs::Pr(bits));
}
struct BitIter(u32);
impl Iterator for BitIter {
type Item = u32;
fn next(&mut self) -> Option<Self::Item> {
match self.0.trailing_zeros() {
32 => None,
b => {
self.0 &= !(1 << b);
Some(b)
}
}
}
}
/// EXTI input driver
pub struct ExtiInput<'d, T: GpioPin> {
pin: Input<'d, T>,
}
impl<'d, T: GpioPin> Unpin for ExtiInput<'d, T> {}
impl<'d, T: GpioPin> ExtiInput<'d, T> {
pub fn new(pin: Input<'d, T>, _ch: impl Unborrow<Target = T::ExtiChannel> + 'd) -> Self {
Self { pin }
}
}
impl<'d, T: GpioPin> InputPin for ExtiInput<'d, T> {
type Error = Infallible;
fn is_high(&self) -> Result<bool, Self::Error> {
self.pin.is_high()
}
fn is_low(&self) -> Result<bool, Self::Error> {
self.pin.is_low()
}
}
impl<'d, T: GpioPin> WaitForRisingEdge for ExtiInput<'d, T> {
type Future<'a> = ExtiInputFuture<'a>;
fn wait_for_rising_edge<'a>(&'a mut self) -> Self::Future<'a> {
ExtiInputFuture::new(
self.pin.pin.pin(),
self.pin.pin.port(),
vals::Rt::ENABLED,
vals::Ft::DISABLED,
)
}
}
impl<'d, T: GpioPin> WaitForFallingEdge for ExtiInput<'d, T> {
type Future<'a> = ExtiInputFuture<'a>;
fn wait_for_falling_edge<'a>(&'a mut self) -> Self::Future<'a> {
ExtiInputFuture::new(
self.pin.pin.pin(),
self.pin.pin.port(),
vals::Rt::DISABLED,
vals::Ft::ENABLED,
)
}
}
impl<'d, T: GpioPin> WaitForAnyEdge for ExtiInput<'d, T> {
type Future<'a> = ExtiInputFuture<'a>;
fn wait_for_any_edge<'a>(&'a mut self) -> Self::Future<'a> {
ExtiInputFuture::new(
self.pin.pin.pin(),
self.pin.pin.port(),
vals::Rt::ENABLED,
vals::Ft::ENABLED,
)
}
}
pub struct ExtiInputFuture<'a> {
pin: u8,
phantom: PhantomData<&'a mut AnyPin>,
}
impl<'a> ExtiInputFuture<'a> {
fn new(pin: u8, port: u8, rising: vals::Rt, falling: vals::Ft) -> Self {
cortex_m::interrupt::free(|_| unsafe {
let pin = pin as usize;
SYSCFG.exticr(pin / 4).modify(|w| w.set_exti(pin % 4, port));
EXTI.rtsr(CORE_INDEX).modify(|w| w.set_rt(pin, rising));
EXTI.ftsr(CORE_INDEX).modify(|w| w.set_ft(pin, falling));
EXTI.pr(CORE_INDEX).write(|w| w.set_pif(pin, true)); // clear pending bit
EXTI.cpu(CORE_INDEX)
.imr(CORE_INDEX)
.modify(|w| w.set_im(pin, vals::Mr::UNMASKED));
});
Self {
pin,
phantom: PhantomData,
}
}
}
impl<'a> Drop for ExtiInputFuture<'a> {
fn drop(&mut self) {
cortex_m::interrupt::free(|_| unsafe {
let pin = self.pin as _;
EXTI.cpu(CORE_INDEX)
.imr(CORE_INDEX)
.modify(|w| w.set_im(pin, vals::Mr::MASKED));
});
}
}
impl<'a> Future for ExtiInputFuture<'a> {
type Output = ();
fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
EXTI_WAKERS[self.pin as usize].register(cx.waker());
if unsafe {
EXTI.cpu(CORE_INDEX)
.imr(CORE_INDEX)
.read()
.im(self.pin as _)
== vals::Mr::MASKED
} {
Poll::Ready(())
} else {
Poll::Pending
}
}
}
use crate::interrupt;
macro_rules! impl_irq {
($e:ident) => {
#[interrupt]
unsafe fn $e() {
on_irq()
}
};
}
foreach_exti_irq!(impl_irq);

View File

@ -68,12 +68,14 @@ pub use generated::{peripherals, Peripherals};
#[non_exhaustive]
pub struct Config {
pub rcc: rcc::Config,
pub enable_debug_during_sleep: bool,
}
impl Default for Config {
fn default() -> Self {
Self {
rcc: Default::default(),
enable_debug_during_sleep: true,
}
}
}
@ -83,6 +85,10 @@ pub fn init(config: Config) -> Peripherals {
let p = Peripherals::take();
unsafe {
if config.enable_debug_during_sleep {
dbgmcu::Dbgmcu::enable_all();
}
gpio::init();
dma::init();
#[cfg(exti)]

View File

@ -2,7 +2,6 @@ use core::marker::PhantomData;
use embassy::util::Unborrow;
use crate::dbgmcu::Dbgmcu;
use crate::pac::{FLASH, RCC};
use crate::peripherals;
use crate::time::Hertz;
@ -27,7 +26,6 @@ pub struct Config {
pub sys_ck: Option<Hertz>,
pub hclk: Option<Hertz>,
pub pclk: Option<Hertz>,
pub enable_debug_wfe: bool,
}
pub struct Rcc<'d> {
@ -190,12 +188,6 @@ impl<'d> Rcc<'d> {
}
})
}
if self.config.enable_debug_wfe {
RCC.ahbenr().modify(|w| w.set_dmaen(true));
critical_section::with(|_| Dbgmcu::enable_all());
}
}
Clocks {
@ -210,18 +202,6 @@ impl<'d> Rcc<'d> {
}
pub unsafe fn init(config: Config) {
RCC.ahbenr().modify(|w| {
w.set_iopaen(true);
w.set_iopben(true);
w.set_iopcen(true);
w.set_iopden(true);
#[cfg(rcc_f0)]
w.set_iopeen(true);
w.set_iopfen(true);
});
let rcc = Rcc::new(<peripherals::RCC as embassy::util::Steal>::steal(), config);
let clocks = rcc.freeze();
set_freqs(clocks);

View File

@ -21,7 +21,6 @@ pub struct Config {
pub hclk: Option<Hertz>,
pub pclk1: Option<Hertz>,
pub pclk2: Option<Hertz>,
pub enable_debug_wfe: bool,
}
/// RCC peripheral
@ -176,15 +175,6 @@ impl<'d> Rcc<'d> {
});
}
if self.config.enable_debug_wfe {
unsafe {
RCC.ahb1enr().modify(|w| w.set_dma1en(true));
critical_section::with(|_| {
crate::dbgmcu::Dbgmcu::enable_all();
});
}
}
Clocks {
sys: Hertz(sysclk),
apb1: Hertz(pclk1),

View File

@ -3,7 +3,7 @@ use core::marker::PhantomData;
use embassy::util::Unborrow;
use crate::pac::rcc::vals::Timpre;
use crate::pac::{DBGMCU, RCC, SYSCFG};
use crate::pac::{RCC, SYSCFG};
use crate::peripherals;
use crate::pwr::{Power, VoltageScale};
use crate::rcc::{set_freqs, Clocks};
@ -363,25 +363,6 @@ impl<'d> Rcc<'d> {
}
}
/// Enables debugging during WFI/WFE
///
/// Set `enable_dma1` to true if you do not have at least one bus master (other than the CPU)
/// enable during WFI/WFE
pub fn enable_debug_wfe(&mut self, _dbg: &mut peripherals::DBGMCU, enable_dma1: bool) {
// NOTE(unsafe) We have exclusive access to the RCC and DBGMCU
unsafe {
if enable_dma1 {
RCC.ahb1enr().modify(|w| w.set_dma1en(true));
}
DBGMCU.cr().modify(|w| {
w.set_dbgsleep_d1(true);
w.set_dbgstby_d1(true);
w.set_dbgstop_d1(true);
});
}
}
/// Setup traceclk
/// Returns a pll1_r_ck
fn traceclk_setup(&mut self, sys_use_pll1_p: bool) {

View File

@ -1,5 +1,4 @@
pub use super::types::*;
use crate::dbgmcu::Dbgmcu;
use crate::pac;
use crate::peripherals::{self, CRS, RCC, SYSCFG};
use crate::rcc::{get_freqs, set_freqs, Clocks};
@ -168,15 +167,6 @@ impl<'d> Rcc<'d> {
unsafe { get_freqs() }
}
pub fn enable_debug_wfe(&mut self, _dbg: &mut peripherals::DBGMCU, enable_dma: bool) {
// NOTE(unsafe) We have exclusive access to the RCC and DBGMCU
unsafe {
pac::RCC.ahbenr().modify(|w| w.set_dma1en(enable_dma));
Dbgmcu::enable_all();
}
}
pub fn enable_hsi48(&mut self, _syscfg: &mut SYSCFG, _crs: CRS) -> HSI48 {
let rcc = pac::RCC;
unsafe {
@ -387,16 +377,6 @@ impl RccExt for RCC {
pub struct HSI48(());
pub unsafe fn init(config: Config) {
let rcc = pac::RCC;
rcc.iopenr().write(|w| {
w.set_iopaen(true);
w.set_iopben(true);
w.set_iopcen(true);
w.set_iopden(true);
w.set_iopeen(true);
w.set_iophen(true);
});
let r = <peripherals::RCC as embassy::util::Steal>::steal();
let clocks = r.freeze(config);
set_freqs(clocks);

View File

@ -10,6 +10,8 @@ pub struct Clocks {
pub sys: Hertz,
pub apb1: Hertz,
pub apb2: Hertz,
#[cfg(rcc_wl5)]
pub apb3: Hertz,
pub apb1_tim: Hertz,
pub apb2_tim: Hertz,
@ -17,13 +19,13 @@ pub struct Clocks {
#[cfg(any(rcc_l0, rcc_f0, rcc_f0x0))]
pub ahb: Hertz,
#[cfg(any(rcc_l4, rcc_f4, rcc_h7, rcc_wb55, rcc_wl5x))]
#[cfg(any(rcc_l4, rcc_f4, rcc_h7, rcc_wb, rcc_wl5))]
pub ahb1: Hertz,
#[cfg(any(rcc_l4, rcc_f4, rcc_h7, rcc_wb55, rcc_wl5x))]
#[cfg(any(rcc_l4, rcc_f4, rcc_h7, rcc_wb, rcc_wl5))]
pub ahb2: Hertz,
#[cfg(any(rcc_l4, rcc_f4, rcc_h7, rcc_wb55, rcc_wl5x))]
#[cfg(any(rcc_l4, rcc_f4, rcc_h7, rcc_wb, rcc_wl5))]
pub ahb3: Hertz,
#[cfg(any(rcc_h7))]
@ -66,10 +68,10 @@ cfg_if::cfg_if! {
} else if #[cfg(rcc_f4)] {
mod f4;
pub use f4::*;
} else if #[cfg(rcc_wb55)] {
mod wb55;
pub use wb55::*;
} else if #[cfg(rcc_wl5x)] {
} else if #[cfg(rcc_wb)] {
mod wb;
pub use wb::*;
} else if #[cfg(rcc_wl5)] {
mod wl5x;
pub use wl5x::*;
} else if #[cfg(any(rcc_f0, rcc_f0x0))] {

View File

@ -190,6 +190,9 @@ impl RccExt for RCC {
}
};
// TODO: completely untested
let apb3_freq = ahb_freq;
Clocks {
sys: sys_clk.hz(),
ahb1: ahb_freq.hz(),
@ -197,6 +200,7 @@ impl RccExt for RCC {
ahb3: ahb_freq.hz(),
apb1: apb1_freq.hz(),
apb2: apb2_freq.hz(),
apb3: apb3_freq.hz(),
apb1_tim: apb1_tim_freq.hz(),
apb2_tim: apb2_tim_freq.hz(),
}

View File

@ -12,7 +12,7 @@ use embassy_stm32::Peripherals;
#[path = "../example_common.rs"]
mod example_common;
#[embassy::main(config = "example_common::config()")]
#[embassy::main]
async fn main(_spawner: Spawner, _p: Peripherals) -> ! {
loop {
Timer::after(Duration::from_secs(1)).await;

View File

@ -6,13 +6,6 @@ use panic_probe as _;
pub use defmt::*;
use core::sync::atomic::{AtomicUsize, Ordering};
use embassy_stm32::Config;
pub fn config() -> Config {
let mut config = Config::default();
config.rcc.enable_debug_wfe = true;
config
}
defmt::timestamp! {"{=u64}", {
static COUNT: AtomicUsize = AtomicUsize::new(0);

View File

@ -8,7 +8,6 @@
mod example_common;
use embassy::executor::Spawner;
use embassy::time::{Duration, Timer};
use embassy_stm32::dbgmcu::Dbgmcu;
use embassy_stm32::gpio::{Level, Output, Speed};
use embassy_stm32::Peripherals;
use embedded_hal::digital::v2::OutputPin;
@ -18,10 +17,6 @@ use example_common::*;
async fn main(_spawner: Spawner, p: Peripherals) {
info!("Hello World!");
unsafe {
Dbgmcu::enable_all();
}
let mut led = Output::new(p.PB7, Level::High, Speed::Low);
loop {

View File

@ -7,7 +7,6 @@
#[path = "../example_common.rs"]
mod example_common;
use cortex_m_rt::entry;
use embassy_stm32::dbgmcu::Dbgmcu;
use embassy_stm32::gpio::{Input, Level, Output, Pull, Speed};
use embedded_hal::digital::v2::{InputPin, OutputPin};
use example_common::*;
@ -16,10 +15,6 @@ use example_common::*;
fn main() -> ! {
info!("Hello World!");
unsafe {
Dbgmcu::enable_all();
}
let p = embassy_stm32::init(Default::default());
let button = Input::new(p.PC13, Pull::Down);

View File

@ -7,7 +7,6 @@
#[path = "../example_common.rs"]
mod example_common;
use embassy::executor::Spawner;
use embassy_stm32::dbgmcu::Dbgmcu;
use embassy_stm32::exti::ExtiInput;
use embassy_stm32::gpio::{Input, Pull};
use embassy_stm32::Peripherals;
@ -18,10 +17,6 @@ use example_common::*;
async fn main(_spawner: Spawner, p: Peripherals) {
info!("Hello World!");
unsafe {
Dbgmcu::enable_all();
}
let button = Input::new(p.PC13, Pull::Down);
let mut button = ExtiInput::new(button, p.EXTI13);

View File

@ -10,7 +10,6 @@ mod example_common;
use cortex_m_rt::entry;
use embassy_stm32::can::filter::Mask32;
use embassy_stm32::can::{Can, Frame, StandardId};
use embassy_stm32::dbgmcu::Dbgmcu;
use embassy_stm32::gpio::{Input, Pull};
use example_common::*;
@ -18,10 +17,6 @@ use example_common::*;
fn main() -> ! {
info!("Hello World!");
unsafe {
Dbgmcu::enable_all();
}
let mut p = embassy_stm32::init(Default::default());
// The next two lines are a workaround for testing without transceiver.

View File

@ -17,7 +17,6 @@ mod example_common;
fn config() -> Config {
let mut config = Config::default();
config.rcc.sys_ck = Some(Hertz(84_000_000));
config.rcc.enable_debug_wfe = true;
config
}

View File

@ -8,7 +8,6 @@
mod example_common;
use cortex_m_rt::entry;
use embassy_stm32::dbgmcu::Dbgmcu;
use embassy_stm32::dma::NoDma;
use embassy_stm32::gpio::{Level, Output, Speed};
use embassy_stm32::spi::{Config, Spi};
@ -21,10 +20,6 @@ use example_common::*;
fn main() -> ! {
info!("Hello World, dude!");
unsafe {
Dbgmcu::enable_all();
}
let p = embassy_stm32::init(Default::default());
let mut spi = Spi::new(

View File

@ -9,7 +9,6 @@ mod example_common;
use core::fmt::Write;
use core::str::from_utf8;
use embassy::executor::Spawner;
use embassy_stm32::dbgmcu::Dbgmcu;
use embassy_stm32::spi::{Config, Spi};
use embassy_stm32::time::Hertz;
use embassy_stm32::Peripherals;
@ -21,10 +20,6 @@ use heapless::String;
async fn main(_spawner: Spawner, p: Peripherals) {
info!("Hello World!");
unsafe {
Dbgmcu::enable_all();
}
let mut spi = Spi::new(
p.SPI1,
p.PB3,

View File

@ -7,7 +7,6 @@
#[path = "../example_common.rs"]
mod example_common;
use cortex_m_rt::entry;
use embassy_stm32::dbgmcu::Dbgmcu;
use embassy_stm32::dma::NoDma;
use embassy_stm32::usart::{Config, Uart};
use embedded_hal::blocking::serial::Write;
@ -17,10 +16,6 @@ use example_common::*;
fn main() -> ! {
info!("Hello World!");
unsafe {
Dbgmcu::enable_all();
}
let p = embassy_stm32::init(Default::default());
let config = Config::default();

View File

@ -8,7 +8,6 @@
mod example_common;
use core::fmt::Write;
use embassy::executor::Spawner;
use embassy_stm32::dbgmcu::Dbgmcu;
use embassy_stm32::dma::NoDma;
use embassy_stm32::usart::{Config, Uart};
use embassy_stm32::Peripherals;
@ -20,10 +19,6 @@ use heapless::String;
async fn main(_spawner: Spawner, p: Peripherals) {
info!("Hello World!");
unsafe {
Dbgmcu::enable_all();
}
let config = Config::default();
let mut usart = Uart::new(p.USART3, p.PD9, p.PD8, p.DMA1_CH3, NoDma, config);

View File

@ -8,7 +8,6 @@
mod example_common;
use embassy::executor::Spawner;
use embassy::time::{Duration, Timer};
use embassy_stm32::dbgmcu::Dbgmcu;
use embassy_stm32::gpio::{Level, Output, Speed};
use embassy_stm32::Peripherals;
use embedded_hal::digital::v2::OutputPin;
@ -18,8 +17,6 @@ use example_common::*;
async fn main(_spawner: Spawner, p: Peripherals) {
info!("Hello World!");
unsafe { Dbgmcu::enable_all() };
let mut led = Output::new(p.PB14, Level::High, Speed::Low);
loop {

View File

@ -7,7 +7,6 @@
#[path = "../example_common.rs"]
mod example_common;
use embassy::executor::Spawner;
use embassy_stm32::dbgmcu::Dbgmcu;
use embassy_stm32::exti::ExtiInput;
use embassy_stm32::gpio::{Input, Pull};
use embassy_stm32::Peripherals;
@ -18,10 +17,6 @@ use example_common::*;
async fn main(_spawner: Spawner, p: Peripherals) {
info!("Hello World!");
unsafe {
Dbgmcu::enable_all();
}
let button = Input::new(p.PC13, Pull::Down);
let mut button = ExtiInput::new(button, p.EXTI13);

View File

@ -19,10 +19,6 @@ fn main() -> ! {
let p = embassy_stm32::init(config());
unsafe {
Dbgmcu::enable_all();
}
let mut dac = Dac::new(p.DAC1, p.PA4, NoPin);
loop {
@ -33,7 +29,6 @@ fn main() -> ! {
}
}
use embassy_stm32::dbgmcu::Dbgmcu;
use micromath::F32Ext;
fn to_sine_wave(v: u8) -> u8 {

View File

@ -19,7 +19,6 @@ use embassy_macros::interrupt_take;
use embassy_net::{
Config as NetConfig, Ipv4Address, Ipv4Cidr, StackResources, StaticConfigurator, TcpSocket,
};
use embassy_stm32::dbgmcu::Dbgmcu;
use embassy_stm32::eth::lan8742a::LAN8742A;
use embassy_stm32::eth::{Ethernet, State};
use embassy_stm32::rng::Random;
@ -96,10 +95,6 @@ fn main() -> ! {
info!("Setup RCC...");
unsafe {
Dbgmcu::enable_all();
}
let p = embassy_stm32::init(config());
let rng = Random::new(p.RNG);

View File

@ -17,7 +17,6 @@ use example_common::*;
use core::str::from_utf8;
use cortex_m_rt::entry;
use embassy_stm32::dbgmcu::Dbgmcu;
use embassy_stm32::peripherals::SPI3;
use embassy_stm32::time::U32Ext;
use heapless::String;
@ -43,10 +42,6 @@ static EXECUTOR: Forever<Executor> = Forever::new();
fn main() -> ! {
info!("Hello World!");
unsafe {
Dbgmcu::enable_all();
}
let p = embassy_stm32::init(config());
let spi = spi::Spi::new(

View File

@ -16,7 +16,6 @@ use example_common::*;
use core::str::from_utf8;
use cortex_m_rt::entry;
use embassy_stm32::dbgmcu::Dbgmcu;
use embassy_stm32::peripherals::{DMA1_CH3, DMA1_CH4, SPI3};
use embassy_stm32::spi;
use heapless::String;
@ -39,10 +38,6 @@ static EXECUTOR: Forever<Executor> = Forever::new();
fn main() -> ! {
info!("Hello World!");
unsafe {
Dbgmcu::enable_all();
}
let p = embassy_stm32::init(config());
let spi = spi::Spi::new(

View File

@ -14,7 +14,6 @@ use embassy_stm32::usart::{Config, Uart};
use example_common::*;
use cortex_m_rt::entry;
use embassy_stm32::dbgmcu::Dbgmcu;
#[embassy::task]
async fn main_task() {
@ -39,10 +38,6 @@ static EXECUTOR: Forever<Executor> = Forever::new();
fn main() -> ! {
info!("Hello World!");
unsafe {
Dbgmcu::enable_all();
}
let executor = EXECUTOR.put(Executor::new());
executor.run(|spawner| {

View File

@ -9,7 +9,6 @@ mod example_common;
use core::fmt::Write;
use embassy::executor::Executor;
use embassy::util::Forever;
use embassy_stm32::dbgmcu::Dbgmcu;
use embassy_stm32::dma::NoDma;
use embassy_stm32::usart::{Config, Uart};
use embassy_traits::uart::Write as _Write;
@ -41,10 +40,6 @@ static EXECUTOR: Forever<Executor> = Forever::new();
fn main() -> ! {
info!("Hello World!");
unsafe {
Dbgmcu::enable_all();
}
let executor = EXECUTOR.put(Executor::new());
executor.run(|spawner| {

View File

@ -27,7 +27,7 @@ defmt = "0.2.0"
defmt-rtt = "0.2.0"
cortex-m = "0.7.1"
cortex-m-rt = "0.6.14"
cortex-m-rt = "0.7.0"
embedded-hal = { version = "0.2.4" }
panic-probe = { version = "0.2.0", features= ["print-defmt"] }
futures = { version = "0.3.8", default-features = false, features = ["async-await"] }

View File

@ -10,17 +10,14 @@ mod example_common;
use embassy::executor::Spawner;
use embassy::time::{Duration, Timer};
use embassy_stm32::gpio::{Level, Output, Speed};
use embassy_stm32::rcc::Rcc;
use embassy_stm32::Peripherals;
use embedded_hal::digital::v2::OutputPin;
use example_common::*;
#[embassy::main]
async fn main(_spawner: Spawner, mut p: Peripherals) {
async fn main(_spawner: Spawner, p: Peripherals) {
info!("Hello World!");
Rcc::new(p.RCC).enable_debug_wfe(&mut p.DBGMCU, true);
let mut led = Output::new(p.PB5, Level::High, Speed::Low);
loop {

View File

@ -6,22 +6,16 @@
#[path = "../example_common.rs"]
mod example_common;
use embassy_stm32::{
gpio::{Input, Level, Output, Pull, Speed},
rcc::*,
};
use embassy::executor::Spawner;
use embassy_stm32::gpio::{Input, Level, Output, Pull, Speed};
use embassy_stm32::Peripherals;
use embedded_hal::digital::v2::{InputPin, OutputPin};
use example_common::*;
use cortex_m_rt::entry;
#[entry]
fn main() -> ! {
#[embassy::main]
async fn main(_spawner: Spawner, p: Peripherals) {
info!("Hello World!");
let mut p = embassy_stm32::init(Default::default());
Rcc::new(p.RCC).enable_debug_wfe(&mut p.DBGMCU, true);
let button = Input::new(p.PB2, Pull::Up);
let mut led1 = Output::new(p.PA5, Level::High, Speed::Low);
let mut led2 = Output::new(p.PB5, Level::High, Speed::Low);

View File

@ -17,7 +17,6 @@ use example_common::*;
#[embassy::main]
async fn main(_spawner: Spawner, mut p: Peripherals) {
let mut rcc = rcc::Rcc::new(p.RCC);
rcc.enable_debug_wfe(&mut p.DBGMCU, true);
// Enables SYSCFG
let _ = rcc.enable_hsi48(&mut p.SYSCFG, p.CRS);

View File

@ -7,25 +7,21 @@
#[path = "../example_common.rs"]
mod example_common;
use embassy::executor::Spawner;
use embassy_stm32::gpio::{Level, Output, Speed};
use embedded_hal::digital::v2::OutputPin;
use example_common::*;
use cortex_m_rt::entry;
use embassy_stm32::dma::NoDma;
use embassy_stm32::rcc;
use embassy_stm32::spi::{Config, Spi};
use embassy_stm32::time::Hertz;
use embassy_stm32::Peripherals;
use embedded_hal::blocking::spi::Transfer;
#[entry]
fn main() -> ! {
#[embassy::main]
async fn main(_spawner: Spawner, p: Peripherals) {
info!("Hello World, folks!");
let mut p = embassy_stm32::init(Default::default());
let mut rcc = rcc::Rcc::new(p.RCC);
rcc.enable_debug_wfe(&mut p.DBGMCU, true);
let mut spi = Spi::new(
p.SPI1,
p.PB3,
@ -40,7 +36,7 @@ fn main() -> ! {
let mut cs = Output::new(p.PA15, Level::High, Speed::VeryHigh);
loop {
let mut buf = [0x0A; 4];
let mut buf = [0x0Au8; 4];
unwrap!(cs.set_low());
unwrap!(spi.transfer(&mut buf));
unwrap!(cs.set_high());

View File

@ -11,14 +11,11 @@ use example_common::*;
use embassy::executor::Spawner;
use embassy_stm32::usart::{Config, Uart};
use embassy_stm32::{rcc, Peripherals};
use embassy_stm32::Peripherals;
use embassy_traits::uart::{Read, Write};
#[embassy::main]
async fn main(_spawner: Spawner, mut p: Peripherals) {
let mut rcc = rcc::Rcc::new(p.RCC);
rcc.enable_debug_wfe(&mut p.DBGMCU, true);
async fn main(_spawner: Spawner, p: Peripherals) {
let mut usart = Uart::new(
p.USART1,
p.PB7,

View File

@ -15,13 +15,10 @@ use embassy::io::{AsyncBufReadExt, AsyncWriteExt};
use embassy_stm32::dma::NoDma;
use embassy_stm32::interrupt;
use embassy_stm32::usart::{BufferedUart, Config, State, Uart};
use embassy_stm32::{rcc, Peripherals};
use embassy_stm32::Peripherals;
#[embassy::main]
async fn main(_spawner: Spawner, mut p: Peripherals) {
let mut rcc = rcc::Rcc::new(p.RCC);
rcc.enable_debug_wfe(&mut p.DBGMCU, true);
async fn main(_spawner: Spawner, p: Peripherals) {
static mut TX_BUFFER: [u8; 8] = [0; 8];
static mut RX_BUFFER: [u8; 256] = [0; 256];

View File

@ -26,7 +26,7 @@ defmt = "0.2.0"
defmt-rtt = "0.2.0"
cortex-m = "0.7.1"
cortex-m-rt = "0.6.14"
cortex-m-rt = "0.7.0"
embedded-hal = { version = "0.2.4" }
panic-probe = { version = "0.2.0", features= ["print-defmt"] }
futures = { version = "0.3.8", default-features = false, features = ["async-await"] }

View File

@ -9,7 +9,6 @@ mod example_common;
use embassy::time::Delay;
use embassy_stm32::adc::{Adc, Resolution};
use embassy_stm32::dbgmcu::Dbgmcu;
use embassy_stm32::pac;
use example_common::*;
@ -18,8 +17,6 @@ fn main() -> ! {
info!("Hello World!");
unsafe {
Dbgmcu::enable_all();
pac::RCC.ccipr().modify(|w| {
w.set_adcsel(0b11);
});

View File

@ -8,7 +8,6 @@
mod example_common;
use embassy::executor::Spawner;
use embassy::time::{Duration, Timer};
use embassy_stm32::dbgmcu::Dbgmcu;
use embassy_stm32::gpio::{Level, Output, Speed};
use embassy_stm32::Peripherals;
use embedded_hal::digital::v2::OutputPin;
@ -18,10 +17,6 @@ use example_common::*;
async fn main(_spawner: Spawner, p: Peripherals) {
info!("Hello World!");
unsafe {
Dbgmcu::enable_all();
}
let mut led = Output::new(p.PB14, Level::High, Speed::Low);
loop {

View File

@ -6,7 +6,6 @@
#[path = "../example_common.rs"]
mod example_common;
use embassy_stm32::dbgmcu::Dbgmcu;
use embassy_stm32::gpio::{Input, Pull};
use embedded_hal::digital::v2::InputPin;
use example_common::*;
@ -15,10 +14,6 @@ use example_common::*;
fn main() -> ! {
info!("Hello World!");
unsafe {
Dbgmcu::enable_all();
}
let p = embassy_stm32::init(Default::default());
let button = Input::new(p.PC13, Pull::Up);

View File

@ -7,7 +7,6 @@
#[path = "../example_common.rs"]
mod example_common;
use embassy::executor::Spawner;
use embassy_stm32::dbgmcu::Dbgmcu;
use embassy_stm32::exti::ExtiInput;
use embassy_stm32::gpio::{Input, Pull};
use embassy_stm32::Peripherals;
@ -18,10 +17,6 @@ use example_common::*;
async fn main(_spawner: Spawner, p: Peripherals) {
info!("Hello World!");
unsafe {
Dbgmcu::enable_all();
}
let button = Input::new(p.PC13, Pull::Up);
let mut button = ExtiInput::new(button, p.EXTI13);

View File

@ -8,7 +8,6 @@
mod example_common;
use embassy_stm32::dac::{Channel, Dac, Value};
use embassy_stm32::dbgmcu::Dbgmcu;
use embassy_stm32::gpio::NoPin;
use embassy_stm32::pac;
use example_common::*;
@ -18,8 +17,6 @@ fn main() -> ! {
info!("Hello World!");
unsafe {
Dbgmcu::enable_all();
pac::RCC.apb1enr1().modify(|w| {
w.set_dac1en(true);
});

View File

@ -7,7 +7,6 @@
#[path = "../example_common.rs"]
mod example_common;
use embassy_stm32::dbgmcu::Dbgmcu;
use embassy_stm32::dma::NoDma;
use embassy_stm32::gpio::{Level, Output, Speed};
use embassy_stm32::spi::{Config, Spi};
@ -20,10 +19,6 @@ use example_common::*;
fn main() -> ! {
info!("Hello World!");
unsafe {
Dbgmcu::enable_all();
}
let p = embassy_stm32::init(Default::default());
let mut spi = Spi::new(

View File

@ -8,7 +8,6 @@
mod example_common;
use embassy::executor::Spawner;
use embassy_stm32::dbgmcu::Dbgmcu;
use embassy_stm32::gpio::{Input, Level, Output, Pull, Speed};
use embassy_stm32::spi::{Config, Spi};
use embassy_stm32::time::Hertz;
@ -21,10 +20,6 @@ use example_common::*;
async fn main(_spawner: Spawner, p: Peripherals) {
info!("Hello World!");
unsafe {
Dbgmcu::enable_all();
}
let mut spi = Spi::new(
p.SPI3,
p.PC10,

View File

@ -7,7 +7,6 @@
#[path = "../example_common.rs"]
mod example_common;
use embassy_stm32::dbgmcu::Dbgmcu;
use embassy_stm32::dma::NoDma;
use embassy_stm32::usart::{Config, Uart};
use embedded_hal::blocking::serial::Write;
@ -17,10 +16,6 @@ use example_common::*;
fn main() -> ! {
info!("Hello World!");
unsafe {
Dbgmcu::enable_all();
}
let p = embassy_stm32::init(Default::default());
let config = Config::default();

View File

@ -8,7 +8,6 @@
mod example_common;
use core::fmt::Write;
use embassy::executor::Spawner;
use embassy_stm32::dbgmcu::Dbgmcu;
use embassy_stm32::dma::NoDma;
use embassy_stm32::usart::{Config, Uart};
use embassy_stm32::Peripherals;
@ -20,10 +19,6 @@ use heapless::String;
async fn main(_spawner: Spawner, p: Peripherals) {
info!("Hello World!");
unsafe {
Dbgmcu::enable_all();
}
let config = Config::default();
let mut usart = Uart::new(p.UART4, p.PA1, p.PA0, p.DMA1_CH3, NoDma, config);

View File

@ -8,7 +8,6 @@
mod example_common;
use embassy::executor::Spawner;
use embassy::time::{Duration, Timer};
use embassy_stm32::dbgmcu::Dbgmcu;
use embassy_stm32::gpio::{Level, Output, Speed};
use embassy_stm32::Peripherals;
use embedded_hal::digital::v2::OutputPin;
@ -18,8 +17,6 @@ use example_common::*;
async fn main(_spawner: Spawner, p: Peripherals) {
info!("Hello World!");
unsafe { Dbgmcu::enable_all() };
let mut led = Output::new(p.PB0, Level::High, Speed::Low);
loop {

View File

@ -0,0 +1,31 @@
#![no_std]
#![no_main]
#![feature(trait_alias)]
#![feature(type_alias_impl_trait)]
#![allow(incomplete_features)]
#[path = "../example_common.rs"]
mod example_common;
use embassy::executor::Spawner;
use embassy_stm32::exti::ExtiInput;
use embassy_stm32::gpio::{Input, Pull};
use embassy_stm32::Peripherals;
use embassy_traits::gpio::{WaitForFallingEdge, WaitForRisingEdge};
use example_common::*;
#[embassy::main]
async fn main(_spawner: Spawner, p: Peripherals) {
info!("Hello World!");
let button = Input::new(p.PC4, Pull::Up);
let mut button = ExtiInput::new(button, p.EXTI4);
info!("Press the USER button...");
loop {
button.wait_for_falling_edge().await;
info!("Pressed!");
button.wait_for_rising_edge().await;
info!("Released!");
}
}

View File

@ -8,7 +8,6 @@
mod example_common;
use embassy::executor::Spawner;
use embassy::time::{Duration, Timer};
use embassy_stm32::dbgmcu::Dbgmcu;
use embassy_stm32::gpio::{Level, Output, Speed};
use embassy_stm32::Peripherals;
use embedded_hal::digital::v2::OutputPin;
@ -18,8 +17,6 @@ use example_common::*;
async fn main(_spawner: Spawner, p: Peripherals) {
info!("Hello World!");
unsafe { Dbgmcu::enable_all() };
let mut led = Output::new(p.PB15, Level::High, Speed::Low);
loop {

View File

@ -6,10 +6,7 @@
#[path = "../example_common.rs"]
mod example_common;
use embassy_stm32::{
dbgmcu::Dbgmcu,
gpio::{Input, Level, Output, Pull, Speed},
};
use embassy_stm32::gpio::{Input, Level, Output, Pull, Speed};
use embedded_hal::digital::v2::{InputPin, OutputPin};
use example_common::*;
@ -21,8 +18,6 @@ fn main() -> ! {
let p = embassy_stm32::init(Default::default());
unsafe { Dbgmcu::enable_all() };
let button = Input::new(p.PA0, Pull::Up);
let mut led1 = Output::new(p.PB15, Level::High, Speed::Low);
let mut led2 = Output::new(p.PB9, Level::High, Speed::Low);

View File

@ -7,7 +7,6 @@
#[path = "../example_common.rs"]
mod example_common;
use embassy::executor::Spawner;
use embassy_stm32::dbgmcu::Dbgmcu;
use embassy_stm32::exti::ExtiInput;
use embassy_stm32::gpio::{Input, Pull};
use embassy_stm32::Peripherals;
@ -18,8 +17,6 @@ use example_common::*;
async fn main(_spawner: Spawner, p: Peripherals) {
info!("Hello World!");
unsafe { Dbgmcu::enable_all() };
let button = Input::new(p.PA0, Pull::Up);
let mut button = ExtiInput::new(button, p.EXTI0);

@ -1 +1 @@
Subproject commit bfd4797d1278c3e0b4611bc79e12346dedbde7c9
Subproject commit 12be5f3da4ba38850d94ab865d2b920bd936300b

View File

@ -1,4 +1,5 @@
use chiptool::generate::CommonModule;
use chiptool::ir::IR;
use regex::Regex;
use serde::Deserialize;
use std::collections::{BTreeMap, HashMap, HashSet};
@ -116,11 +117,7 @@ impl BlockInfo {
}
}
fn find_reg_for_field<'c>(
rcc: &'c ir::IR,
reg_regex: &str,
field_name: &str,
) -> Option<(&'c str, &'c str)> {
fn find_reg<'c>(rcc: &'c ir::IR, reg_regex: &str, field_name: &str) -> Option<(&'c str, &'c str)> {
let reg_regex = Regex::new(reg_regex).unwrap();
for (name, fieldset) in &rcc.fieldsets {
@ -273,19 +270,18 @@ pub fn gen(options: Options) {
});
// Load RCC register for chip
let rcc = core.peripherals.iter().find_map(|(name, p)| {
if name == "RCC" {
p.block.as_ref().map(|block| {
let bi = BlockInfo::parse(block);
let rcc_reg_path = data_dir
.join("registers")
.join(&format!("{}_{}.yaml", bi.module, bi.version));
serde_yaml::from_reader(File::open(rcc_reg_path).unwrap()).unwrap()
})
} else {
None
}
});
let (_, rcc) = core
.peripherals
.iter()
.find(|(name, _)| name == &"RCC")
.expect("RCC peripheral missing");
let rcc_block = rcc.block.as_ref().expect("RCC peripheral has no block");
let bi = BlockInfo::parse(&rcc_block);
let rcc_reg_path = data_dir
.join("registers")
.join(&format!("{}_{}.yaml", bi.module, bi.version));
let rcc: IR = serde_yaml::from_reader(File::open(rcc_reg_path).unwrap()).unwrap();
let mut peripheral_versions: BTreeMap<String, String> = BTreeMap::new();
let mut pin_table: Vec<Vec<String>> = Vec::new();
@ -424,73 +420,71 @@ pub fn gen(options: Options) {
_ => {}
}
if let Some(rcc) = &rcc {
// Workaround for clock registers being split on some chip families. Assume fields are
// named after peripheral and look for first field matching and use that register.
let mut en = find_reg_for_field(&rcc, "^.+ENR\\d*$", &format!("{}EN", name));
let mut rst = find_reg_for_field(&rcc, "^.+RSTR\\d*$", &format!("{}RST", name));
// Workaround for clock registers being split on some chip families. Assume fields are
// named after peripheral and look for first field matching and use that register.
let mut en = find_reg(&rcc, "^.+ENR\\d*$", &format!("{}EN", name));
let mut rst = find_reg(&rcc, "^.+RSTR\\d*$", &format!("{}RST", name));
if en.is_none() && name.ends_with("1") {
en = find_reg_for_field(
&rcc,
"^.+ENR\\d*$",
&format!("{}EN", &name[..name.len() - 1]),
);
rst = find_reg_for_field(
&rcc,
"^.+RSTR\\d*$",
&format!("{}RST", &name[..name.len() - 1]),
);
if en.is_none() && name.ends_with("1") {
en = find_reg(
&rcc,
"^.+ENR\\d*$",
&format!("{}EN", &name[..name.len() - 1]),
);
rst = find_reg(
&rcc,
"^.+RSTR\\d*$",
&format!("{}RST", &name[..name.len() - 1]),
);
}
match (en, rst) {
(Some((enable_reg, enable_field)), reset_reg_field) => {
let clock = match &p.clock {
Some(clock) => clock.as_str(),
None => {
// No clock was specified, derive the clock name from the enable register name.
Regex::new("([A-Z]+\\d*).*")
.unwrap()
.captures(enable_reg)
.unwrap()
.get(1)
.unwrap()
.as_str()
}
};
let clock = if name.starts_with("TIM") {
format!("{}_tim", clock.to_ascii_lowercase())
} else {
clock.to_ascii_lowercase()
};
let mut row = Vec::with_capacity(6);
row.push(name.clone());
row.push(clock);
row.push(enable_reg.to_ascii_lowercase());
if let Some((reset_reg, reset_field)) = reset_reg_field {
row.push(reset_reg.to_ascii_lowercase());
row.push(format!("set_{}", enable_field.to_ascii_lowercase()));
row.push(format!("set_{}", reset_field.to_ascii_lowercase()));
} else {
row.push(format!("set_{}", enable_field.to_ascii_lowercase()));
}
if !name.starts_with("GPIO") {
peripheral_rcc_table.push(row);
} else {
gpio_rcc_table.push(row);
gpio_regs.insert(enable_reg.to_ascii_lowercase());
}
}
match (en, rst) {
(Some((enable_reg, enable_field)), reset_reg_field) => {
let clock = match &p.clock {
Some(clock) => clock.as_str(),
None => {
// No clock was specified, derive the clock name from the enable register name.
Regex::new("([A-Z]+\\d*).*")
.unwrap()
.captures(enable_reg)
.unwrap()
.get(1)
.unwrap()
.as_str()
}
};
let clock = if name.starts_with("TIM") {
format!("{}_tim", clock.to_ascii_lowercase())
} else {
clock.to_ascii_lowercase()
};
let mut row = Vec::with_capacity(6);
row.push(name.clone());
row.push(clock);
row.push(enable_reg.to_ascii_lowercase());
if let Some((reset_reg, reset_field)) = reset_reg_field {
row.push(reset_reg.to_ascii_lowercase());
row.push(format!("set_{}", enable_field.to_ascii_lowercase()));
row.push(format!("set_{}", reset_field.to_ascii_lowercase()));
} else {
row.push(format!("set_{}", enable_field.to_ascii_lowercase()));
}
if !name.starts_with("GPIO") {
peripheral_rcc_table.push(row);
} else {
gpio_rcc_table.push(row);
gpio_regs.insert(enable_reg.to_ascii_lowercase());
}
}
(None, Some(_)) => {
println!("Unable to find enable register for {}", name)
}
(None, None) => {
println!("Unable to find enable and reset register for {}", name)
}
(None, Some(_)) => {
println!("Unable to find enable register for {}", name)
}
(None, None) => {
println!("Unable to find enable and reset register for {}", name)
}
}
}
@ -502,6 +496,10 @@ pub fn gen(options: Options) {
gpio_rcc_table.push(vec![reg]);
}
// We should always find GPIO RCC regs. If not, it means something
// is broken and GPIO won't work because it's not enabled.
assert!(!gpio_rcc_table.is_empty());
for (id, channel_info) in &core.dma_channels {
let mut row = Vec::new();
let dma_peri = core.peripherals.get(&channel_info.dma).unwrap();

View File

@ -1,3 +1,4 @@
use std::env::args;
use std::path::PathBuf;
use stm32_metapac_gen::*;
@ -5,13 +6,24 @@ fn main() {
let out_dir = PathBuf::from("out");
let data_dir = PathBuf::from("../stm32-data/data");
let chips = std::fs::read_dir(data_dir.join("chips"))
.unwrap()
.filter_map(|res| res.unwrap().file_name().to_str().map(|s| s.to_string()))
.filter(|s| s.ends_with(".yaml"))
.filter(|s| !s.starts_with("STM32L1")) // cursed gpio stride
.map(|s| s.strip_suffix(".yaml").unwrap().to_string())
.collect();
let args: Vec<String> = args().collect();
let chips = match &args[..] {
[_, chip] => {
vec![chip.clone()]
}
[_] => {
std::fs::read_dir(data_dir.join("chips"))
.unwrap()
.filter_map(|res| res.unwrap().file_name().to_str().map(|s| s.to_string()))
.filter(|s| s.ends_with(".yaml"))
.filter(|s| !s.starts_with("STM32L1")) // cursed gpio stride
.filter(|s| !s.starts_with("STM32GBK")) // cursed weird STM32G4
.map(|s| s.strip_suffix(".yaml").unwrap().to_string())
.collect()
}
_ => panic!("usage: stm32-metapac-gen [chip?]"),
};
gen(Options {
out_dir,