Skip to content

Commit cf9c8ea

Browse files
committed
Translate PWM for TIM2 from stm32f1xx-hal
1 parent 0796139 commit cf9c8ea

File tree

6 files changed

+445
-1
lines changed

6 files changed

+445
-1
lines changed

examples/pwm.rs

Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
//! Testing PWM output
2+
3+
#![deny(unsafe_code)]
4+
#![deny(warnings)]
5+
#![no_main]
6+
#![no_std]
7+
8+
extern crate panic_halt;
9+
10+
// use cortex_m::asm;
11+
use stm32l4xx_hal::{
12+
prelude::*,
13+
stm32,
14+
delay,
15+
};
16+
use cortex_m_rt::entry;
17+
18+
#[entry]
19+
fn main() -> ! {
20+
let c = cortex_m::Peripherals::take().unwrap();
21+
let p = stm32::Peripherals::take().unwrap();
22+
23+
let mut flash = p.FLASH.constrain();
24+
let mut rcc = p.RCC.constrain();
25+
26+
let clocks = rcc.cfgr.freeze(&mut flash.acr);
27+
28+
let mut gpioa = p.GPIOA.split(&mut rcc.ahb2);
29+
30+
// TIM2
31+
let c1 = gpioa.pa0
32+
.into_push_pull_output(&mut gpioa.moder, &mut gpioa.otyper)
33+
.into_af1(&mut gpioa.moder, &mut gpioa.afrl);
34+
let c2 = gpioa.pa1
35+
.into_push_pull_output(&mut gpioa.moder, &mut gpioa.otyper)
36+
.into_af1(&mut gpioa.moder, &mut gpioa.afrl);
37+
let c3 = gpioa.pa2
38+
.into_push_pull_output(&mut gpioa.moder, &mut gpioa.otyper)
39+
.into_af1(&mut gpioa.moder, &mut gpioa.afrl);
40+
let c4 = gpioa.pa3
41+
.into_push_pull_output(&mut gpioa.moder, &mut gpioa.otyper)
42+
.into_af1(&mut gpioa.moder, &mut gpioa.afrl);
43+
44+
let mut pwm = p
45+
.TIM2
46+
.pwm(
47+
(c1, c2, c3, c4),
48+
1.khz(),
49+
clocks,
50+
&mut rcc.apb1r1,
51+
)
52+
.3;
53+
54+
let max = pwm.get_max_duty();
55+
56+
pwm.enable();
57+
58+
let mut timer = delay::Delay::new(c.SYST, clocks);
59+
let second: u32 = 100;
60+
61+
loop {
62+
pwm.set_duty(max);
63+
timer.delay_ms(second);
64+
// asm::bkpt();
65+
66+
pwm.set_duty(max/11*10);
67+
timer.delay_ms(second);
68+
// asm::bkpt();
69+
70+
pwm.set_duty(3*max/4);
71+
timer.delay_ms(second);
72+
// asm::bkpt();
73+
74+
pwm.set_duty(max/2);
75+
timer.delay_ms(second);
76+
// asm::bkpt();
77+
78+
pwm.set_duty(max/4);
79+
timer.delay_ms(second);
80+
// asm::bkpt();
81+
82+
}
83+
}

src/bb.rs

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
//! Bit banding
2+
3+
// seems this is not a HAL trait (yet?)
4+
// TODO: why is it used
5+
//
6+
// "The processor memory map includes two bit-band regions.
7+
// These occupy the lowest 1MB of the SRAM and Peripheral memory regions respectively.
8+
// These bit-band regions map each word in an alias region of memory to a bit
9+
// in a bit-band region of memory."
10+
//
11+
// This module only handles peripheral, not SRAM bit-banding
12+
13+
use core::ptr;
14+
15+
pub fn clear<T>(register: *const T, bit: u8) {
16+
write(register, bit, false);
17+
}
18+
19+
pub fn set<T>(register: *const T, bit: u8) {
20+
write(register, bit, true);
21+
}
22+
23+
pub fn write<T>(register: *const T, bit: u8, set: bool) {
24+
let addr = register as usize;
25+
26+
// Peripheral memory starts at 0x4000_0000, the first megabyte is aliased.
27+
//
28+
// Bit-band region is first megabyte
29+
assert!(addr >= 0x4000_0000 && addr <= 0x4010_0000);
30+
assert!(bit < 32);
31+
32+
let bit = bit as usize;
33+
// bit_word_addr = bit_band_base + (byte_offset x 32) + (bit_number × 4)
34+
let bb_addr = (0x4200_0000 + (addr - 0x4000_0000) * 32) + 4 * bit;
35+
unsafe { ptr::write_volatile(bb_addr as *mut u32, if set { 1 } else { 0 }) }
36+
}

src/gpio.rs

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -111,7 +111,9 @@ macro_rules! gpio {
111111

112112
use crate::rcc::AHB2;
113113
use super::{
114-
Alternate, AF4, AF5, AF6, AF7, AF8, AF9, Floating, GpioExt, Input, OpenDrain, Output,
114+
Alternate,
115+
AF1, AF4, AF5, AF6, AF7, AF8, AF9,
116+
Floating, GpioExt, Input, OpenDrain, Output,
115117
PullDown, PullUp, PushPull, State,
116118
};
117119

@@ -236,6 +238,29 @@ macro_rules! gpio {
236238
}
237239

238240
impl<MODE> $PXi<MODE> {
241+
/// Configures the pin to serve as alternate function 1 (AF1)
242+
pub fn into_af1(
243+
self,
244+
moder: &mut MODER,
245+
afr: &mut $AFR,
246+
) -> $PXi<Alternate<AF1, MODE>> {
247+
let offset = 2 * $i;
248+
249+
// alternate function mode
250+
let mode = 0b10;
251+
moder.moder().modify(|r, w| unsafe {
252+
w.bits((r.bits() & !(0b11 << offset)) | (mode << offset))
253+
});
254+
255+
let af = 1;
256+
let offset = 4 * ($i % 8);
257+
afr.afr().modify(|r, w| unsafe {
258+
w.bits((r.bits() & !(0b1111 << offset)) | (af << offset))
259+
});
260+
261+
$PXi { _mode: PhantomData }
262+
}
263+
239264
/// Configures the pin to serve as alternate function 4 (AF4)
240265
pub fn into_af4(
241266
self,

src/lib.rs

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -165,3 +165,19 @@ pub mod timer;
165165
feature = "stm32l4x6"
166166
))]
167167
pub mod tsc;
168+
#[cfg(any(
169+
feature = "stm32l4x1",
170+
feature = "stm32l4x2",
171+
feature = "stm32l4x3",
172+
feature = "stm32l4x5",
173+
feature = "stm32l4x6"
174+
))]
175+
pub mod bb;
176+
#[cfg(any(
177+
feature = "stm32l4x1",
178+
feature = "stm32l4x2",
179+
feature = "stm32l4x3",
180+
feature = "stm32l4x5",
181+
feature = "stm32l4x6"
182+
))]
183+
pub mod pwm;

src/prelude.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,3 +10,4 @@ pub use crate::datetime::U32Ext as _stm32l4_hal_datetime_U32Ext;
1010
pub use crate::dma::DmaExt as _stm32l4_hal_DmaExt;
1111
pub use crate::pwr::PwrExt as _stm32l4_hal_PwrExt;
1212
pub use crate::rng::RngExt as _stm32l4_hal_RngExt;
13+
pub use crate::pwm::PwmExt as _stm32l4_hal_PwmExt;

0 commit comments

Comments
 (0)