Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fast forwarding #1

Merged
merged 11 commits into from
Dec 3, 2019
7 changes: 6 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,16 +9,18 @@ and this project adheres to [Semantic Versioning](http://semver.org/).

### Added

- Added `Mode` marker trait for `gpio` pins that correspondent to pin mode.
- RCC `Bus` trait + private `Enable` and `Reset` traits
- Added `micros_since` and `reset` methods to timer
- Added `select_frequency` method to RTC
- Unidirectional DMA support for SPI (TX only)
- Added USB driver for `stm32f102` and `stm32f103` devices

- Added all timers for all variants as described by CubeMX. Commented out {TIM9, TIM10} for XL and {TIM12, TIM13, TIM14} for XL and F100-HIGH due to missing fields for those devices in stm32-rs.
- ADC measurement now can be run by timer

### Breaking changes

- Implement more pin combinations for PWM configuration, added PWM for TIM1 (API for custom PWM pins was removed as it's no more needed)
- Bump `stm32f1` dependency (`0.9.0`)
- `void::Void` replaced with `Infallible` where it is possible
- Change timer/pwm init API
Expand All @@ -27,6 +29,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
- Starting the timer does not generate interrupt requests anymore
- Make MAPR::mapr() private
- i2c mode now takes Hertz instead of a generic u32
- Timers that were previously incorrectly available without medium/high/xl density features may now be missing

### Fixed

Expand All @@ -35,6 +38,8 @@ and this project adheres to [Semantic Versioning](http://semver.org/).

### Changed

- Pins can be passed in any order to SPI constructor,
`NoSck`, `NoMiso` and `NoMosi` can be also passed instead of real pin
- DMA traits now require AsSlice instead of AsRef
- GPIO `downgrade` function now returns a `Pxx` instead of a type specific to a
GPIO port
Expand Down
19 changes: 1 addition & 18 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ cortex-m = "0.6.0"
nb = "0.1.2"
cortex-m-rt = "0.6.8"
stm32f1 = "0.9.0"
as-slice = "0.2"
as-slice = "0.1"

[dependencies.void]
default-features = false
Expand All @@ -48,7 +48,6 @@ panic-semihosting = "0.5.2"
panic-itm = "0.4.1"
cortex-m-rtfm = "0.4.3"
cortex-m-semihosting = "0.3.3"
enc28j60 = "0.2.1"
heapless = "0.4.3"
m = "0.1.1"
mfrc522 = "0.2.0"
Expand All @@ -72,26 +71,10 @@ version = "0.4.0"
default-features = false
version = "1.5.2"

#[dev-dependencies.jnet]
#git = "https://github.com/japaric/jnet"
#rev = "df96b408049ca952ad7844d6552e87cf8fc18d2a"

#[dev-dependencies.motor-driver]
#git = "https://github.com/japaric/motor-driver"
#rev = "00c8b15223643090d69f1acfb8b7a7a43a440417"

#[dev-dependencies.mpu9250]
#git = "https://github.com/japaric/mpu9250"
#rev = "8f9ecad690093cb71c41301ca5e5705706150610"

[dev-dependencies.serde]
default-features = false
version = "1.0.90"

#[dev-dependencies.serde-json-core]
#git = "https://github.com/japaric/serde-json-core"
#rev = "6f12b77c1ffeae167989fe06e0d8b15978bd6d18"

[features]
device-selected = []
doc = []
Expand Down
11 changes: 10 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,19 @@

This crate supports multiple microcontrollers in the
stm32f1 family. Which specific microcontroller you want to build for has to be
specified with a feature, for example `stm32f103`.
specified with a feature, for example `stm32f103`.

If no microcontroller is specified, the crate will not compile.

You may also need to specify the density of the device with `medium`, `high` or `xl`
to enable certain peripherals. Generally the density can be determined by the 2nd character
after the number in the device name (i.e. For STM32F103C6U, the 6 indicates a low-density
device) but check the datasheet or CubeMX to be sure.
* 4, 6 => low density, no feature required
* 8, B => `medium` feature
* C, D, E => `high` feature
* F, G => `xl` feature

### Supported Microcontrollers

* `stm32f100`
Expand Down
30 changes: 16 additions & 14 deletions examples/pwm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ use cortex_m::asm;
use stm32f1xx_hal::{
prelude::*,
pac,
timer::Timer,
timer::{Tim2NoRemap, Timer},
};
use cortex_m_rt::entry;

Expand All @@ -25,30 +25,32 @@ fn main() -> ! {

let mut afio = p.AFIO.constrain(&mut rcc.apb2);

// let mut gpioa = p.GPIOA.split(&mut rcc.apb2);
let mut gpiob = p.GPIOB.split(&mut rcc.apb2);
let mut gpioa = p.GPIOA.split(&mut rcc.apb2);
// let mut gpiob = p.GPIOB.split(&mut rcc.apb2);

// TIM2
// let c1 = gpioa.pa0.into_alternate_push_pull(&mut gpioa.crl);
// let c2 = gpioa.pa1.into_alternate_push_pull(&mut gpioa.crl);
// let c3 = gpioa.pa2.into_alternate_push_pull(&mut gpioa.crl);
let c1 = gpioa.pa0.into_alternate_push_pull(&mut gpioa.crl);
let c2 = gpioa.pa1.into_alternate_push_pull(&mut gpioa.crl);
let c3 = gpioa.pa2.into_alternate_push_pull(&mut gpioa.crl);
// If you don't want to use all channels, just leave some out
// let c4 = gpioa.pa3.into_alternate_push_pull(&mut gpioa.crl);
let pins = (c1, c2, c3);

// TIM3
// let c1 = gpioa.pa6.into_alternate_push_pull(&mut gpioa.crl);
// let c2 = gpioa.pa7.into_alternate_push_pull(&mut gpioa.crl);
// let c3 = gpiob.pb0.into_alternate_push_pull(&mut gpiob.crl);
// let c4 = gpiob.pb1.into_alternate_push_pull(&mut gpiob.crl);

// TIM4
let c1 = gpiob.pb6.into_alternate_push_pull(&mut gpiob.crl);
let c2 = gpiob.pb7.into_alternate_push_pull(&mut gpiob.crl);
let c3 = gpiob.pb8.into_alternate_push_pull(&mut gpiob.crh);
let c4 = gpiob.pb9.into_alternate_push_pull(&mut gpiob.crh);
// TIM4 (Only available with the "medium" density feature)
// let c1 = gpiob.pb6.into_alternate_push_pull(&mut gpiob.crl);
// let c2 = gpiob.pb7.into_alternate_push_pull(&mut gpiob.crl);
// let c3 = gpiob.pb8.into_alternate_push_pull(&mut gpiob.crh);
// let c4 = gpiob.pb9.into_alternate_push_pull(&mut gpiob.crh);

let mut pwm = Timer::tim4(p.TIM4, &clocks, &mut rcc.apb1)
.pwm((c1, c2, c3, c4), &mut afio.mapr, 1.khz())
.3;
let mut pwm = Timer::tim2(p.TIM2, &clocks, &mut rcc.apb1)
.pwm::<Tim2NoRemap, _, _, _>(pins, &mut afio.mapr, 1.khz())
.2;

let max = pwm.get_max_duty();

Expand Down
33 changes: 2 additions & 31 deletions examples/pwm_custom.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,38 +8,13 @@ use panic_halt as _;

use cortex_m::asm;
use stm32f1xx_hal::{
gpio::gpiob::{PB4, PB5},
gpio::{Alternate, PushPull},
pac::{self,TIM3},
pac,
prelude::*,
pwm::{Pins, Pwm, C1, C2},
timer::Timer,
};

use cortex_m_rt::entry;

// Using PB5 channel for TIM3 PWM output
// struct MyChannels(PB5<Alternate<PushPull>>);
// impl Pins<TIM3> for MyChannels {
// const REMAP: u8 = 0b10;
// const C1: bool = false;
// const C2: bool = true;
// const C3: bool = false;
// const C4: bool = false;
// type Channels = Pwm<TIM3, C2>;
// }

// Using PB4 and PB5 channels for TIM3 PWM output
struct MyChannels(PB4<Alternate<PushPull>>, PB5<Alternate<PushPull>>);
impl Pins<TIM3> for MyChannels {
const REMAP: u8 = 0b10;
const C1: bool = true;
const C2: bool = true;
const C3: bool = false;
const C4: bool = false;
type Channels = (Pwm<TIM3, C1>, Pwm<TIM3, C2>);
}

#[entry]
fn main() -> ! {
let p = pac::Peripherals::take().unwrap();
Expand All @@ -59,11 +34,7 @@ fn main() -> ! {
let p1 = gpiob.pb5.into_alternate_push_pull(&mut gpiob.crl);

let mut pwm = Timer::tim3(p.TIM3, &clocks, &mut rcc.apb1)
.pwm(
MyChannels(p0, p1),
&mut afio.mapr,
1.khz(),
);
.pwm((p0, p1), &mut afio.mapr, 1.khz());

let max = pwm.0.get_max_duty();

Expand Down
17 changes: 13 additions & 4 deletions src/adc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,13 @@ use core::sync::atomic::{self, Ordering};
use cortex_m::asm::delay;

use crate::stm32::ADC1;
#[cfg(any(
#[cfg(feature = "stm32f103")]
use crate::stm32::ADC2;
#[cfg(all(
feature = "stm32f103",
feature = "high",
))]
use crate::stm32::ADC2;
use crate::stm32::ADC3;

/// Continuous mode
pub struct Continuous;
Expand Down Expand Up @@ -484,11 +487,17 @@ adc_hal! {
ADC1: (adc1),
}

#[cfg(any(
#[cfg(feature = "stm32f103")]
adc_hal! {
ADC2: (adc2),
}

#[cfg(all(
feature = "stm32f103",
feature = "high",
))]
adc_hal! {
ADC2: (adc2),
ADC3: (adc3),
}

pub struct AdcPayload<PINS, MODE> {
Expand Down
11 changes: 10 additions & 1 deletion src/gpio.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,10 @@ pub trait GpioExt {
fn split(self, apb2: &mut APB2) -> Self::Parts;
}


/// Marker trait for pin mode detection.
pub trait Mode<MODE> {}

/// Marker trait for active states.
pub trait Active {}

Expand Down Expand Up @@ -95,7 +99,8 @@ macro_rules! gpio {
State,
Active,
Debugger,
Pxx
Pxx,
Mode,
};

/// GPIO parts
Expand Down Expand Up @@ -216,13 +221,17 @@ macro_rules! gpio {
pub type $PXx<MODE> = Pxx<MODE>;


impl<MODE> Mode<MODE> for Generic<MODE> {}


$(
/// Pin
pub struct $PXi<MODE> {
_mode: PhantomData<MODE>,
}

impl<MODE> Mode<MODE> for $PXi<MODE> {}

impl $PXi<Debugger> {
/// Put the pin in an active state. The caller
/// must enforce that the pin is really in this
Expand Down
56 changes: 38 additions & 18 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,30 @@
//! - stm32f103
//! - stm32f100
//!
//! ```toml
//! [dependencies.stm32f1xx-hal]
//! version = "0.2.1"
//! features = ["stm32f103", "rt"]
//! ```
//! ## Usage
//!
//! This crate supports multiple microcontrollers in the
//! stm32f1 family. Which specific microcontroller you want to build for has to be
//! specified with a feature, for example `stm32f103`.
//!
//! If no microcontroller is specified, the crate will not compile.
//!
//! The currently supported variants are
//!
//! - `stm32f100`
//! - `stm32f101`
//! - `stm32f103`
//!
//! You may also need to specify the density of the device with `medium`, `high` or `xl`
//! to enable certain peripherals. Generally the density can be determined by the 2nd character
//! after the number in the device name (i.e. For STM32F103C6U, the 6 indicates a low-density
//! device) but check the datasheet or CubeMX to be sure.
//! * 4, 6 => low density, no feature required
//! * 8, B => `medium` feature
//! * C, D, E => `high` feature
//! * F, G => `xl` feature
//!
//!
//!
//! [cortex-m-quickstart]: https://docs.rs/cortex-m-quickstart/0.3.1
//!
Expand All @@ -36,7 +55,7 @@
//! #![no_std]
//! #![no_main]
//!
//! extern crate panic_halt;
//! use panic_halt as _;
//!
//! use nb::block;
//!
Expand All @@ -46,6 +65,7 @@
//! timer::Timer,
//! };
//! use cortex_m_rt::entry;
//! use embedded_hal::digital::v2::OutputPin;
//!
//! #[entry]
//! fn main() -> ! {
Expand All @@ -54,25 +74,23 @@
//! // Get access to the device specific peripherals from the peripheral access crate
//! let dp = pac::Peripherals::take().unwrap();
//!
//! // Take ownership over the raw flash and rcc devices and convert them
//! // into the corresponding HAL structs
//! // Take ownership over the raw flash and rcc devices and convert them into the corresponding
//! // HAL structs
//! let mut flash = dp.FLASH.constrain();
//! let mut rcc = dp.RCC.constrain();
//!
//! // Freeze the configuration of all the clocks in the system and store
//! // the frozen frequencies in `clocks`
//! // Freeze the configuration of all the clocks in the system and store the frozen frequencies in
//! // `clocks`
//! let clocks = rcc.cfgr.freeze(&mut flash.acr);
//!
//! // Acquire the GPIOC peripheral
//! let mut gpioc = dp.GPIOC.split(&mut rcc.apb2);
//!
//! // Configure gpio C pin 13 as a push-pull output. The `crh` register is
//! // passed to the function in order to configure the port. For pins 0-7,
//! // crl should be passed instead.
//! // Configure gpio C pin 13 as a push-pull output. The `crh` register is passed to the function
//! // in order to configure the port. For pins 0-7, crl should be passed instead.
//! let mut led = gpioc.pc13.into_push_pull_output(&mut gpioc.crh);
//! // Configure the syst timer to trigger an update every second
//! let mut timer = Timer::syst(cp.SYST, clocks)
//! .start_count_down(1.hz());
//! let mut timer = Timer::syst(cp.SYST, &clocks).start_count_down(1.hz());
//!
//! // Wait for the timer to trigger an update and change the state of the LED
//! loop {
Expand All @@ -99,9 +117,11 @@
compile_error!("Target not found. A `--feature <target-name>` is required.");

// If any two or more targets are specified, print error message.
#[cfg(all(feature = "stm32f100", feature = "stm32f101"))]
#[cfg(all(feature = "stm32f100", feature = "stm32f103"))]
#[cfg(all(feature = "stm32f101", feature = "stm32f103"))]
#[cfg(any(
all(feature = "stm32f100", feature = "stm32f101"),
all(feature = "stm32f100", feature = "stm32f103"),
all(feature = "stm32f101", feature = "stm32f103"),
))]
compile_error!("Multiple targets specified. Only a single `--feature <target-name>` can be specified.");

#[cfg(feature = "device-selected")]
Expand Down
Loading