Skip to content
Snippets Groups Projects
Commit 1c394e45 authored by Per Lindgren's avatar Per Lindgren
Browse files

pmw3389-sine, wip

parent 8d3a3660
No related branches found
No related tags found
No related merge requests found
......@@ -19,7 +19,7 @@
"runToMain": true,
"svdFile": "${workspaceRoot}/.vscode/STM32F401.svd",
"configFiles": [
"interface/stlink-v2-1.cfg",
"interface/stlink.cfg",
"target/stm32f4x.cfg"
],
"preRestartCommands": [
......@@ -44,6 +44,41 @@
"executable": "./target/thumbv7em-none-eabihf/debug/examples/${fileBasenameNoExtension}",
"cpu": "cortex-m4",
},
{
"type": "cortex-debug",
"request": "launch",
"name": "Cortex Debug 48Mhz",
"servertype": "openocd",
"cwd": "${workspaceRoot}",
"preLaunchTask": "cargo build --example",
"runToMain": true,
"svdFile": "${workspaceRoot}/.vscode/STM32F401.svd",
"configFiles": [
"interface/stlink.cfg",
"target/stm32f4x.cfg"
],
"preRestartCommands": [
"load",
],
"postLaunchCommands": [
"monitor arm semihosting enable"
],
"swoConfig": {
"enabled": true,
"cpuFrequency": 48000000,
"swoFrequency": 2000000,
"source": "probe",
"decoders": [
{
"type": "console",
"label": "ITM",
"port": 0
}
]
},
"executable": "./target/thumbv7em-none-eabihf/debug/examples/${fileBasenameNoExtension}",
"cpu": "cortex-m4",
},
{
"type": "cortex-debug",
"request": "launch",
......@@ -54,7 +89,7 @@
"runToMain": true,
"svdFile": "${workspaceRoot}/.vscode/STM32F401.svd",
"configFiles": [
"interface/stlink-v2-1.cfg",
"interface/stlink.cfg",
"target/stm32f4x.cfg"
],
"preRestartCommands": [
......@@ -78,6 +113,41 @@
},
"executable": "./target/thumbv7em-none-eabihf/release/examples/${fileBasenameNoExtension}",
"cpu": "cortex-m4",
},
{
"type": "cortex-debug",
"request": "launch",
"name": "Cortex Release 48Mhz",
"servertype": "openocd",
"cwd": "${workspaceRoot}",
"preLaunchTask": "cargo build --example --release",
"runToMain": true,
"svdFile": "${workspaceRoot}/.vscode/STM32F401.svd",
"configFiles": [
"interface/stlink.cfg",
"target/stm32f4x.cfg"
],
"preRestartCommands": [
"load",
],
"postLaunchCommands": [
"monitor arm semihosting enable"
],
"swoConfig": {
"enabled": true,
"cpuFrequency": 48000000,
"swoFrequency": 2000000,
"source": "probe",
"decoders": [
{
"type": "console",
"label": "ITM",
"port": 0
}
]
},
"executable": "./target/thumbv7em-none-eabihf/release/examples/${fileBasenameNoExtension}",
"cpu": "cortex-m4",
}
]
}
\ No newline at end of file
// itm_rtic_hello_48Mhz
//
// Use the vscode 48Mhz launch profiles
#![no_main]
#![no_std]
use cortex_m::iprintln;
use panic_halt as _;
use stm32f4xx_hal::prelude::*;
#[rtic::app(device = stm32f4xx_hal::stm32, peripherals = true)]
const APP: () = {
#[init]
fn init(ctx: init::Context) {
// Set up the system clock.
let rcc = ctx.device.RCC.constrain();
let _clocks = rcc.cfgr.sysclk(48.mhz()).require_pll48clk().freeze();
let mut p = ctx.core;
let stim = &mut p.ITM.stim[0];
for a in 0..=10 {
iprintln!(stim, "RTIC Hello, world!! {}", a);
}
}
};
//! examples/rtt-pwm-sine.rs
//! cargo run --examples rtt-pwm-sine --release
// #![deny(unsafe_code)]
// #![deny(warnings)]
#![no_main]
#![no_std]
// use core::f32::consts::PI;
use cortex_m::{asm, peripheral::DWT};
// use panic_halt as _;
use panic_rtt_target as _;
use rtic::cyccnt::{Instant, U32Ext as _};
use rtt_target::{rprint, rprintln, rtt_init_print};
use core::f32::consts::PI;
use micromath::F32Ext;
use stm32f4xx_hal::{bb, gpio::Speed, prelude::*, pwm, stm32};
include!(concat!(env!("OUT_DIR"), "/sin_abs_const.rs"));
#[rtic::app(device = stm32f4xx_hal::stm32, monotonic = rtic::cyccnt::CYCCNT, peripherals = true)]
const APP: () = {
struct Resources {
// late resources
TIM1: stm32::TIM1,
}
#[init(schedule = [pwm_out])]
fn init(mut cx: init::Context) -> init::LateResources {
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())
.sysclk(96.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 contrained into SysConf and used to set clocks
let rcc = unsafe { &(*stm32::RCC::ptr()) };
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 pre-load for the output channels then we
// might as well enable for the auto-reload too
tim1.cr1.modify(|_, w| w.arpe().set_bit());
let clk = clocks.pclk2().0 * if clocks.ppre2() == 1 { 1 } else { 2 };
// check that its actually 48_000_000
rprintln!("clk {}", clk);
// we want maximum performance, thus we set the prescaler to 0
let pre = 0;
rprintln!("pre {}", pre);
tim1.psc.write(|w| w.psc().bits(pre));
// we want 8 bits of resolution
// so our ARR = 2^8 - 1 = 256 - 1 = 255
let arr = 255;
rprintln!("arr {}", arr);
tim1.arr.write(|w| unsafe { w.bits(arr) });
// Trigger update event to load the registers
tim1.cr1.modify(|_, w| w.urs().set_bit());
tim1.egr.write(|w| w.ug().set_bit());
tim1.cr1.modify(|_, w| w.urs().clear_bit());
// Set main output enable of all Output Compare (OC) registers
tim1.bdtr.modify(|_, w| w.moe().set_bit());
// Set output enable for channels 1 and 2
tim1.ccer.write(|w| w.cc1e().set_bit().cc2e().set_bit());
// Setup the timer
tim1.cr1.write(|w| {
w.cms()
.bits(0b00) // edge aligned mode
.dir() // counter used as up-counter
.clear_bit()
.opm() // one pulse mode
.clear_bit()
.cen() // enable counter
.set_bit()
});
// Set main output enable of all Output Compare (OC) registers
tim1.bdtr.modify(|_, w| w.moe().set_bit());
// Set duty cycle of Channels
tim1.ccr1.write(|w| unsafe { w.ccr().bits(128) });
tim1.ccr2.write(|w| unsafe { w.ccr().bits(128) });
// Set preload for the CCx
tim1.cr2.write(|w| w.ccpc().set_bit());
// Enable update events
tim1.dier.write(|w| w.uie().enabled());
tim1.sr.modify(|_, w| w.uif().clear());
// Set divider to 4, (48_000_000/256)/4
// tim1.rcr.modify(|_, w| unsafe { w.rep().bits(4) });
while tim1.sr.read().uif().is_clear() {
rprint!("-");
}
rprintln!("here");
tim1.sr.modify(|_, w| w.uif().clear());
// pass on late resources
cx.schedule.pwm_out(cx.start + PERIOD.cycles()).ok();
init::LateResources { TIM1: tim1 }
}
#[idle]
fn idle(_cx: idle::Context) -> ! {
rprintln!("idle");
// panic!("panic");
loop {
continue;
}
}
#[task(resources = [TIM1], schedule = [pwm_out])]
fn pwm_out(cx: pwm_out::Context) {
static mut INDEX: u16 = 0;
static mut LEFT: u16 = 0;
static mut RIGHT: u16 = 0;
static mut FLOAT: u16 = 0;
let tim1 = cx.resources.TIM1;
tim1.ccr1.write(|w| unsafe { w.ccr().bits(*LEFT) });
// tim1.ccr2.write(|w| unsafe { w.ccr().bits(*RIGHT) });
tim1.ccr2.write(|w| unsafe { w.ccr().bits(*FLOAT) });
*INDEX = (*INDEX).wrapping_add(10_000);
let f: f32 = (*INDEX as f32 * 2.0 * PI) / 65536.0;
*FLOAT = (128.0 + f.sin() * 128.0) as u16;
cx.schedule.pwm_out(cx.scheduled + PERIOD.cycles()).ok();
*LEFT = SINE_BUF[*INDEX as usize] as u16;
*RIGHT = SINE_BUF[*INDEX as usize] as u16;
if cx.scheduled.elapsed() > 500.cycles() {
panic!("task overrun");
}
}
extern "C" {
fn EXTI0();
}
};
// We aim for a sampling rate of 48kHz, assuming that the input filter of the
// sound card used to sample the generated signal has an appropriate input filter
const PERIOD: u32 = 2000; // 96_000_000 / 48_000;
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment