Select Git revision
rtt-pwm-saw.rs
Forked from
Per Lindgren / e7020e_2021
Source project has a limited visibility.
rtt-pwm-saw.rs 4.83 KiB
//! examples/rtt-pwm-saw.rs
//! cargo run --examples rtt-pwm-saw
// #![deny(unsafe_code)]
#![deny(warnings)]
#![no_main]
#![no_std]
// use cortex_m::{asm, peripheral::DWT};
use panic_halt as _;
use rtt_target::{rprint, rprintln, rtt_init_print};
use stm32f4xx_hal::{bb, gpio::Speed, prelude::*, stm32};
#[rtic::app(device = stm32f4xx_hal::stm32, peripherals = true)]
const APP: () = {
#[init]
fn init(mut cx: init::Context) {
rtt_init_print!();
rprintln!("init");
let dp = cx.device;
// Initialize (enable) the monotonic timer (CYCCNT)
cx.core.DCB.enable_trace();
cx.core.DWT.enable_cycle_counter();
let rcc = dp.RCC.constrain();
// Set up the system clock. 48 MHz?
let clocks = rcc
.cfgr
// .use_hse(8.mhz())
.sysclk(48.mhz())
.pclk1(24.mhz())
.freeze();
let gpioa = dp.GPIOA.split();
// we set the pins to VeryHigh to get the sharpest waveform possible
// (rise and fall times should have similar characteristics)
let _channels = (
gpioa.pa8.into_alternate_af1().set_speed(Speed::VeryHigh),
gpioa.pa9.into_alternate_af1().set_speed(Speed::VeryHigh),
);
// Setup PWM RAW
let tim1 = dp.TIM1;
// Here we need unsafe as we are "stealing" the RCC peripheral
// (At this point it has been constrained into SysConf and used to set clocks.)
let rcc = unsafe { &(*stm32::RCC::ptr()) };
// unsafe {
// bb::set(&rcc.apb2enr, 0u8);
// bb::set(&rcc.apb2rstr, 0u8);
// bb::clear(&rcc.apb2rstr, 0u8);
// }
//
// For some reason bb:: hangs target in release mode,
// so I implemented it using modify instead
rcc.apb2enr.modify(|_, w| w.tim1en().set_bit());
rcc.apb2rstr.modify(|_, w| w.tim1rst().set_bit());
rcc.apb2rstr.modify(|_, w| w.tim1rst().clear_bit());
// Setup chanel 1 and 2 as pwm_mode1
tim1.ccmr1_output()
.modify(|_, w| w.oc1pe().set_bit().oc1m().pwm_mode1());
tim1.ccmr1_output()
.modify(|_, w| w.oc2pe().set_bit().oc2m().pwm_mode1());
// The reference manual is a bit ambiguous about when enabling this bit is really
// necessary, but since we MUST enable the preload for the output channels then we
// might as well enable for the auto-reload too