Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 5 additions & 5 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ authors = ["Vitaly Domnikov <[email protected]>"]
categories = ["embedded", "hardware-support", "no-std"]
description = "Peripheral access API for STM32G0 series microcontrollers"
documentation = "https://docs.rs/stm32g0xx-hal"
edition = "2018"
edition = "2021"
keywords = ["arm", "cortex-m", "stm32g0xx", "hal"]
license = "MIT/Apache-2.0"
name = "stm32g0xx-hal"
Expand All @@ -18,14 +18,16 @@ default-target = "thumbv6m-none-eabi"
[dependencies]
cortex-m = { version = "0.7.7", features = ["critical-section-single-core"] }
nb = "1.1.0"
defmt = { version = "0.3.10", optional = true }
fugit = "0.3.7"
embedded-hal = "1.0.0"
bare-metal = "1.0.0"

portable-atomic = { version = "1.10.0", features = ["critical-section"] }

[dependencies.stm32g0]
package = "stm32g0-staging"
version = "0.16.0"
features = ["atomics"]

[dependencies.void]
default-features = false
Expand All @@ -34,19 +36,17 @@ version = "1.0.2"
[dev-dependencies]
cortex-m-rt = "0.7.5"
cortex-m-semihosting = "0.5.0"
defmt = "0.3.8"
defmt-rtt = "0.4.0"
panic-halt = "1.0.0"
panic-semihosting = "0.6.0"
portable-atomic = {version = "1.7.0", features = ["critical-section"]}
rtic = { version = "2.1.1", features = ["thumbv6-backend"] }
panic-probe = "0.3.2"

[features]
default = ["i2c-blocking"]
device-selected = []
rt = ["stm32g0/rt"]
defmt = ["embedded-hal/defmt-03"]
defmt = ["dep:defmt", "embedded-hal/defmt-03", "stm32g0/defmt"]
stm32g030 = ["stm32g0/stm32g030", "stm32g0x0", "device-selected"]
stm32g070 = ["stm32g0/stm32g070", "stm32g0x0", "device-selected"]
stm32g031 = ["stm32g0/stm32g031", "stm32g0x1", "device-selected"]
Expand Down
24 changes: 16 additions & 8 deletions src/analog/adc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,8 @@ pub trait Channel<ADC> {
}

/// ADC Result Alignment
#[derive(Eq, PartialEq)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub enum Align {
/// Right aligned results (least significant bits)
///
Expand All @@ -29,7 +30,8 @@ pub enum Align {
}

/// ADC Sampling Precision
#[derive(Copy, Clone, PartialEq, Eq)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub enum Precision {
/// 12 bit precision
B_12 = 0b00,
Expand All @@ -42,7 +44,8 @@ pub enum Precision {
}

/// ADC Sampling time
#[derive(Copy, Clone, PartialEq, Eq)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub enum SampleTime {
T_2 = 0b000,
T_4 = 0b001,
Expand All @@ -55,7 +58,8 @@ pub enum SampleTime {
}

// ADC Oversampling ratio
#[derive(Copy, Clone, PartialEq, Eq)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub enum OversamplingRatio {
X_2 = 0b000,
X_4 = 0b001,
Expand All @@ -67,20 +71,23 @@ pub enum OversamplingRatio {
X_256 = 0b111,
}

#[derive(Clone, Copy, PartialEq, Eq, Debug)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub enum ClockSource {
Pclk(PclkDiv),
Async(AsyncClockDiv),
}

#[derive(Clone, Copy, PartialEq, Eq, Debug)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub enum PclkDiv {
PclkD1 = 3,
PclkD2 = 1,
PclkD4 = 2,
}

#[derive(Clone, Copy, PartialEq, Eq, Debug)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub enum AsyncClockDiv {
AsyncD1 = 0,
AsyncD2 = 1,
Expand All @@ -94,7 +101,8 @@ pub enum AsyncClockDiv {
}

/// ADC injected trigger source selection
#[derive(Copy, Clone, PartialEq, Eq)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub enum InjTrigSource {
TRG_0 = 0b000, // TIM1_TRGO2
TRG_1 = 0b001, // TIM1_CC4
Expand Down
9 changes: 6 additions & 3 deletions src/analog/comparator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -94,15 +94,17 @@ impl Config {
}
}

#[derive(Copy, Clone, Eq, PartialEq)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub enum Hysteresis {
None = 0b00,
Low = 0b01,
Medium = 0b10,
High = 0b11,
}

#[derive(Copy, Clone, Eq, PartialEq)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub enum PowerMode {
HighSpeed = 0b00,
MediumSpeed = 0b01,
Expand Down Expand Up @@ -183,7 +185,8 @@ negative_input_pin!(COMP2, PB3<Analog>, 0b0110);
negative_input_pin!(COMP2, PB7<Analog>, 0b0111);
negative_input_pin!(COMP2, PA2<Analog>, 0b1000);

#[derive(Copy, Clone, Eq, PartialEq)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub enum RefintInput {
/// VRefint * 1/4
VRefintM14 = 0b0000,
Expand Down
4 changes: 4 additions & 0 deletions src/crc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,8 @@ impl CrcExt for CRC {
}

/// Polynomial settings.
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub enum Polynomial {
/// 7-bit polynomial, only the lowest 7 bits are valid
L7(u8),
Expand All @@ -56,6 +58,8 @@ pub enum Polynomial {
}

/// Bit reversal settings.
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub enum BitReversal {
/// Reverse bits by byte
ByByte,
Expand Down
133 changes: 67 additions & 66 deletions src/dma.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
//! Direct Memory Access Engine

// TODO: add DMA2 for B1, C1
use crate::dmamux::DmaMuxIndex;
use crate::rcc::Rcc;
use crate::stm32::DMAMUX;
use crate::dmamux::{self, DmaMuxExt, DmaMuxIndex};
use crate::rcc::{Enable, Rcc, Reset};
use crate::stm32::{self, DMA1, DMAMUX};

/// Extension trait to split a DMA peripheral into independent channels
pub trait DmaExt {
Expand All @@ -18,6 +18,8 @@ pub trait DmaExt {
}

/// Channel priority level
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub enum Priority {
/// Low
Low = 0b00,
Expand All @@ -41,6 +43,8 @@ impl From<Priority> for u8 {
}

/// DMA transfer direction
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub enum Direction {
/// From memory to peripheral
FromMemory,
Expand All @@ -57,8 +61,9 @@ impl From<Direction> for bool {
}
}

#[doc = "Peripheral size"]
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
/// Peripheral size
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
#[repr(u8)]
pub enum WordSize {
#[doc = "0: 8-bit size"]
Expand All @@ -76,6 +81,8 @@ impl From<WordSize> for u8 {
}

/// DMA events
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub enum Event {
/// First half of a transfer is done
HalfTransfer,
Expand Down Expand Up @@ -243,6 +250,57 @@ pub trait Channel: private::Channel {
}
}

/// Singleton that represents a DMA channel
pub struct C<const N: u8> {
mux: dmamux::Channel<N>,
}

impl<const N: u8> private::Channel for C<N> {
fn ch(&self) -> &stm32::dma1::CH {
// NOTE(unsafe) $Ci grants exclusive access to this register
unsafe { (*DMA1::ptr()).ch(N as usize) }
}
}

impl<const N: u8> C<N> {
pub fn mux(&mut self) -> &mut dyn dmamux::DmaMuxChannel {
&mut self.mux
}
}

impl<const N: u8> Channel for C<N> {
fn select_peripheral(&mut self, index: DmaMuxIndex) {
self.mux().select_peripheral(index);
}

fn event_occurred(&self, event: Event) -> bool {
use Event::*;

// NOTE(unsafe) atomic read
let flags = unsafe { (*DMA1::ptr()).isr().read() };
match event {
HalfTransfer => flags.htif(N).bit_is_set(),
TransferComplete => flags.tcif(N).bit_is_set(),
TransferError => flags.teif(N).bit_is_set(),
Any => flags.gif(N).bit_is_set(),
}
}

fn clear_event(&mut self, event: Event) {
use Event::*;

// NOTE(unsafe) atomic write to a stateless register
unsafe {
let _ = &(*DMA1::ptr()).ifcr().write(|w| match event {
HalfTransfer => w.chtif(N).set_bit(),
TransferComplete => w.ctcif(N).set_bit(),
TransferError => w.cteif(N).set_bit(),
Any => w.cgif(N).set_bit(),
});
}
}
}

macro_rules! dma {
(
channels: {
Expand All @@ -251,11 +309,6 @@ macro_rules! dma {
)+
},
) => {
use crate::dmamux;
use crate::rcc::{Enable, Reset};
use crate::stm32::{self, DMA1 as DMA};
use crate::dmamux::DmaMuxExt;

/// DMA channels
pub struct Channels {
$( pub $chi: $Ci, )+
Expand All @@ -269,60 +322,8 @@ macro_rules! dma {
}
}


$(
/// Singleton that represents a DMA channel
pub struct $Ci {
mux: dmamux::Channel<$i>,
}

impl private::Channel for $Ci {
fn ch(&self) -> &stm32::dma1::CH {
// NOTE(unsafe) $Ci grants exclusive access to this register
unsafe { &(*DMA::ptr()).ch($i) }
}
}

impl $Ci {
pub fn mux(&mut self) -> &mut dyn dmamux::DmaMuxChannel {
&mut self.mux
}
}

impl Channel for $Ci {

fn select_peripheral(&mut self, index: DmaMuxIndex) {
self.mux().select_peripheral(index);
}

fn event_occurred(&self, event: Event) -> bool {
use Event::*;

// NOTE(unsafe) atomic read
let flags = unsafe { (*DMA::ptr()).isr().read() };
match event {
HalfTransfer => flags.htif($i).bit_is_set(),
TransferComplete => flags.tcif($i).bit_is_set(),
TransferError => flags.teif($i).bit_is_set(),
Any => flags.gif($i).bit_is_set(),
}
}

fn clear_event(&mut self, event: Event) {
use Event::*;

// NOTE(unsafe) atomic write to a stateless register
unsafe {
let _ = &(*DMA::ptr()).ifcr().write(|w| match event {
HalfTransfer => w.chtif($i).set_bit(),
TransferComplete => w.ctcif($i).set_bit(),
TransferError => w.cteif($i).set_bit(),
Any => w.cgif($i).set_bit(),
});
}
}

}
pub type $Ci = C<$i>;
)+
}
}
Expand Down Expand Up @@ -357,19 +358,19 @@ dma!(
},
);

impl DmaExt for DMA {
impl DmaExt for DMA1 {
type Channels = Channels;

fn reset(self, rcc: &mut Rcc) -> Self {
// reset DMA
<DMA as Reset>::reset(rcc);
<DMA1 as Reset>::reset(rcc);
self
}

fn split(self, rcc: &mut Rcc, dmamux: DMAMUX) -> Self::Channels {
let muxchannels = dmamux.split();
// enable DMA clock
DMA::enable(rcc);
DMA1::enable(rcc);

let mut channels = Channels {
ch1: C1 {
Expand Down
Loading
Loading