Skip to content

Commit

Permalink
Merge pull request #18 from braun-embedded/adc
Browse files Browse the repository at this point in the history
Make ADC work on STM32L0x2, some fixes
  • Loading branch information
arkorobotics authored Jul 19, 2019
2 parents af1761d + 518f3b8 commit 12aed40
Show file tree
Hide file tree
Showing 6 changed files with 242 additions and 39 deletions.
43 changes: 37 additions & 6 deletions .travis.yml
Original file line number Diff line number Diff line change
@@ -1,18 +1,49 @@
language: rust
cache: cargo
rust:
- stable
- nightly
cache: cargo
env:
- MCU=stm32l0x1
- MCU=stm32l0x2
# STM32L062 is not being run, as it's currently identical to STM32L082
- MCU=stm32l082
- MCU=stm32l0x1
- MCU=stm32l0x2
matrix:
allow_failures:
- rust: nightly
fast_finish: true
# Most of these configurations are commented out, as running them takes far
# too long. I've still left them in, to document which combinations are
# supported.
#
# It probably makes sense to uncomment them selectively, from time to time, to
# test any changes to the affected code.
include:
# STM32L052
# - env: MCU=stm32l052 PACKAGE=lqfp32
# - env: MCU=stm32l052 PACKAGE=lqfp48
# - env: MCU=stm32l052 PACKAGE=lqfp64
# - env: MCU=stm32l052 PACKAGE=tfbga64
# - env: MCU=stm32l052 PACKAGE=ufqfpn32
# - env: MCU=stm32l052 PACKAGE=ufqfpn48
# - env: MCU=stm32l052 PACKAGE=wlcsp36
# STM32L062
# - env: MCU=stm32l062 PACKAGE=lqfp32
# - env: MCU=stm32l062 PACKAGE=ufqfpn32
# - env: MCU=stm32l062 PACKAGE=wlcsp36
# STM32L072
- env: MCU=stm32l072 PACKAGE=lqfp32
# - env: MCU=stm32l072 PACKAGE=lqfp48
# - env: MCU=stm32l072 PACKAGE=lqfp64
# - env: MCU=stm32l072 PACKAGE=lqfp100
# - env: MCU=stm32l072 PACKAGE=tfbga64
# - env: MCU=stm32l072 PACKAGE=ufbga64
# - env: MCU=stm32l072 PACKAGE=ufbg100
# - env: MCU=stm32l072 PACKAGE=ufqfpn32
# - env: MCU=stm32l072 PACKAGE=wlcsp49
# STM32L082
- env: MCU=stm32l082 PACKAGE=lqfp32
# - env: MCU=stm32l082 PACKAGE=ufqfpn32
# - env: MCU=stm32l082 PACKAGE=wlcsp49
before_script:
- rustup target add thumbv6m-none-eabi
script:
- RUSTFLAGS="-D warnings" cargo build --release --examples --features rt,$MCU
- RUSTFLAGS="-D warnings" cargo build --release --examples --features="rt $MCU $PACKAGE"
16 changes: 16 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -45,11 +45,27 @@ panic-semihosting = "0.5.1"


[features]
# Miscellaneaous features
rt = ["stm32l0/rt"]
# MCUs
stm32l0x1 = ["stm32l0/stm32l0x1"]
stm32l0x2 = ["stm32l0/stm32l0x2"]
stm32l052 = ["stm32l0x2"]
stm32l062 = ["stm32l0x2"]
stm32l072 = ["stm32l0x2"]
stm32l082 = ["stm32l0x2"]
# Chip packages
lqfp32 = []
lqfp48 = []
lqfp64 = []
lqfp100 = []
tfbga64 = []
ufbga64 = []
ufbg100 = []
ufqfpn32 = []
ufqfpn48 = []
wlcsp36 = []
wlcsp49 = []


[profile.dev]
Expand Down
43 changes: 43 additions & 0 deletions examples/adc.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
#![deny(unsafe_code)]
#![no_main]
#![no_std]


extern crate panic_halt;


use cortex_m_rt::entry;
use stm32l0xx_hal::{
prelude::*,
pac,
rcc::Config,
};


#[entry]
fn main() -> ! {
let dp = pac::Peripherals::take().unwrap();

let mut rcc = dp.RCC.freeze(Config::hsi16());
let mut adc = dp.ADC.constrain(&mut rcc);
let gpioa = dp.GPIOA.split(&mut rcc);
let gpiob = dp.GPIOB.split(&mut rcc);

let mut a0 = gpioa.pa0.into_analog();

let mut blue = gpiob.pb6.into_push_pull_output();
let mut red = gpiob.pb7.into_push_pull_output();

loop {
let val: u16 = adc.read(&mut a0).unwrap();

if val > 2000 {
blue.set_high().unwrap();
red.set_low().unwrap();
}
else {
red.set_high().unwrap();
blue.set_low().unwrap();
}
}
}
177 changes: 146 additions & 31 deletions src/adc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,14 +36,29 @@ pub enum Precision {
/// ADC Sampling time
#[derive(Copy, Clone, PartialEq)]
pub enum SampleTime {
T_2 = 0b000,
T_4 = 0b001,
T_8 = 0b010,
T_12 = 0b011,
T_20 = 0b100,
T_40 = 0b101,
T_80 = 0b110,
T_160 = 0b111,
/// 1.5 ADC clock cycles
T_1_5 = 0b000,

/// 3.5 ADC clock cycles
T_3_5 = 0b001,

/// 7.5 ADC clock cycles
T_7_5 = 0b010,

/// 12.5 ADC clock cycles
T_12_5 = 0b011,

/// 19.5 ADC clock cycles
T_19_5 = 0b100,

/// 39.5 ADC clock cycles
T_39_5 = 0b101,

/// 79.5 ADC clock cycles
T_79_5 = 0b110,

/// 160.5 ADC clock cycles
T_160_5 = 0b111,
}

/// Analog to Digital converter interface
Expand All @@ -62,7 +77,7 @@ impl Adc {

Self {
rb: adc,
sample_time: SampleTime::T_2,
sample_time: SampleTime::T_1_5,
align: Align::Right,
precision: Precision::B_12,
}
Expand Down Expand Up @@ -95,6 +110,22 @@ impl Adc {
while self.rb.cr.read().aden().bit_is_set() {}
}

#[cfg(feature = "stm32l0x1")]
fn write_smpr(&mut self) {
self.rb
.smpr
.modify(|_, w| w.smp().bits(self.sample_time as u8));
}

#[cfg(feature = "stm32l0x2")]
fn write_smpr(&mut self) {
self.rb
.smpr
// Safe, because `self.sample_time` is of type `SampleTime`, which
// defines only valid values.
.modify(|_, w| unsafe { w.smpr().bits(self.sample_time as u8) });
}

pub fn release(self) -> ADC {
self.rb
}
Expand All @@ -120,31 +151,24 @@ where
fn read(&mut self, _pin: &mut PIN) -> nb::Result<WORD, Self::Error> {
self.power_up();
self.rb.cfgr1.modify(|_, w| {
w.res()
.bits(self.precision as u8)
.align()
.bit(self.align == Align::Left)
// Safe, as `self.precision` is of type `Precision`, which defines
// only valid values.
//
// The `bits` method is not unsafe on STM32L0x1, so we need to
// suppress the warning there.
#[cfg_attr(feature = "stm32l0x1", allow(unused_unsafe))]
let w = unsafe { w.res().bits(self.precision as u8) };
w
.align().bit(self.align == Align::Left)
});

self.rb
.smpr
.modify(|_, w| w.smp().bits(self.sample_time as u8));
self.write_smpr();

match PIN::channel() {
0 => self.rb.chselr.modify(|_, w| w.chsel0().set_bit()),
1 => self.rb.chselr.modify(|_, w| w.chsel1().set_bit()),
2 => self.rb.chselr.modify(|_, w| w.chsel2().set_bit()),
3 => self.rb.chselr.modify(|_, w| w.chsel3().set_bit()),
4 => self.rb.chselr.modify(|_, w| w.chsel4().set_bit()),
5 => self.rb.chselr.modify(|_, w| w.chsel5().set_bit()),
6 => self.rb.chselr.modify(|_, w| w.chsel6().set_bit()),
7 => self.rb.chselr.modify(|_, w| w.chsel7().set_bit()),
8 => self.rb.chselr.modify(|_, w| w.chsel8().set_bit()),
9 => self.rb.chselr.modify(|_, w| w.chsel9().set_bit()),
17 => self.rb.chselr.modify(|_, w| w.chsel17().set_bit()),
18 => self.rb.chselr.modify(|_, w| w.chsel18().set_bit()),
_ => unreachable!(),
}
self.rb.chselr.write(|w|
// Safe, as long as there are no `Channel` implementations that
// define invalid values.
unsafe { w.bits(0b1 << PIN::channel()) }
);

self.rb.isr.modify(|_, w| w.eos().set_bit());
self.rb.cr.modify(|_, w| w.adstart().set_bit());
Expand Down Expand Up @@ -221,3 +245,94 @@ adc_pins! {
Channel8: (gpiob::PB0<Analog>, 8u8),
Channel9: (gpiob::PB1<Analog>, 9u8),
}

#[cfg(
all(
feature = "stm32l052",
any(
feature = "lqfp64",
feature = "tfbga64",
),
)
)]
adc_pins! {
Channel10: (gpioc::PC0<Analog>, 10u8),
Channel11: (gpioc::PC1<Analog>, 11u8),
Channel12: (gpioc::PC2<Analog>, 12u8),
}

#[cfg(
all(
feature = "stm32l072",
any(
feature = "lqfp64",
feature = "lqfp100",
feature = "tfbga64",
feature = "ufbga64",
feature = "ufbg100",
feature = "wlcsp49",
),
)
)]
adc_pins! {
Channel10: (gpioc::PC0<Analog>, 10u8),
Channel11: (gpioc::PC1<Analog>, 11u8),
Channel12: (gpioc::PC2<Analog>, 12u8),
}

#[cfg(all(feature = "stm32l082", feature = "wlcsp49"))]
adc_pins! {
Channel10: (gpioc::PC0<Analog>, 10u8),
Channel11: (gpioc::PC1<Analog>, 11u8),
Channel12: (gpioc::PC2<Analog>, 12u8),
}

#[cfg(all(feature = "stm32l052", feature = "lqfp64"))]
adc_pins! {
Channel13: (gpioc::PC3<Analog>, 13u8),
}

#[cfg(
all(
feature = "stm32l072",
any(
feature = "lqfp64",
feature = "lqfp100",
feature = "ufbg100",
),
)
)]
adc_pins! {
Channel13: (gpioc::PC3<Analog>, 13u8),
}

#[cfg(
all(
feature = "stm32l052",
any(
feature = "lqfp64",
feature = "tfbga64",
),
)
)]
adc_pins! {
Channel14: (gpioc::PC4<Analog>, 14u8),
Channel15: (gpioc::PC5<Analog>, 15u8),
}

#[cfg(
all(
feature = "stm32l072",
any(
feature = "lqfp64",
feature = "lqfp100",
feature = "tfbga64",
feature = "ufbga64",
feature = "ufbg100",
),
)
)]
adc_pins! {
Channel14: (gpioc::PC4<Analog>, 14u8),
Channel15: (gpioc::PC5<Analog>, 15u8),
}
1 change: 0 additions & 1 deletion src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@ pub use crate::pac as stm32;

mod bb;

#[cfg(feature = "stm32l0x1")]
pub mod adc;
#[cfg(any(feature = "stm32l062", feature = "stm32l082"))]
pub mod aes;
Expand Down
1 change: 0 additions & 1 deletion src/prelude.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ pub use crate::hal::adc::OneShot as _hal_adc_OneShot;
pub use crate::hal::watchdog::Watchdog as _hal_watchdog_Watchdog;
pub use crate::hal::watchdog::WatchdogEnable as _hal_watchdog_WatchdogEnable;

#[cfg(feature = "stm32l0x1")]
pub use crate::adc::AdcExt as _stm32l0xx_hal_analog_AdcExt;
pub use crate::delay::DelayExt as _stm32l0xx_hal_delay_DelayExt;
pub use crate::exti::ExtiExt as _stm32l0xx_hal_exti_ExtiExt;
Expand Down

0 comments on commit 12aed40

Please sign in to comment.