From 21a87f0e8bcf0accbbeb3ac6729203f1cec304a2 Mon Sep 17 00:00:00 2001 From: Sebastian Date: Thu, 29 Dec 2022 13:52:18 +0100 Subject: [PATCH] Input side works but stutters --- .cargo/config.toml | 19 +++++ .gitignore | 14 ++++ Cargo.toml | 80 +++++++++++++++++++++ memory.x | 6 ++ src/main.rs | 169 +++++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 288 insertions(+) create mode 100644 .cargo/config.toml create mode 100644 .gitignore create mode 100644 Cargo.toml create mode 100644 memory.x create mode 100644 src/main.rs diff --git a/.cargo/config.toml b/.cargo/config.toml new file mode 100644 index 0000000..dae491b --- /dev/null +++ b/.cargo/config.toml @@ -0,0 +1,19 @@ +[target.'cfg(all(target_arch = "arm", target_os = "none"))'] +# TODO(2) replace `$CHIP` with your chip's name (see `probe-run --list-chips` output) +runner = "probe-run --chip STM32F103C8" +rustflags = [ + "-C", "linker=flip-link", + "-C", "link-arg=-Tlink.x", + "-C", "link-arg=-Tdefmt.x", + # This is needed if your flash or ram addresses are not aligned to 0x10000 in memory.x + # See https://github.com/rust-embedded/cortex-m-quickstart/pull/95 + "-C", "link-arg=--nmagic", +] + +[build] +target = "thumbv7m-none-eabi" # Cortex-M3 + + +[alias] +rb = "run --bin" +rrb = "run --release --bin" diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..3a0e903 --- /dev/null +++ b/.gitignore @@ -0,0 +1,14 @@ +**/*.rs.bk +.#* +.gdb_history +Cargo.lock +target/ + +# editor files +.vscode/* +!.vscode/*.md +!.vscode/*.svd +!.vscode/launch.json +!.vscode/tasks.json +!.vscode/extensions.json +!.vscode/settings.json \ No newline at end of file diff --git a/Cargo.toml b/Cargo.toml new file mode 100644 index 0000000..a0f0b8f --- /dev/null +++ b/Cargo.toml @@ -0,0 +1,80 @@ +[package] +authors = ["Sebastian "] +name = "stm32-usbd-audio" +edition = "2018" +version = "0.1.0" + +[dependencies] +cortex-m = { version = "0.7.6", features = ["critical-section-single-core"]} +cortex-m-rt = "0.7.2" +cortex-m-rtic = "1.1.3" +defmt = "0.3.2" +defmt-rtt = "0.4" +panic-probe = { version = "0.3.0", features = ["print-defmt"] } +stm32f1xx-hal = { version = "0.9.0", features = ["stm32f103", "rt"] } +embedded-hal = {version = "0.2.3"} +systick-monotonic = "1.0.0" +usb-device = {version = "0.2.9", features = ["control-buffer-256"]} +usbd-audio = "0.1.0" + + +[features] +# set logging levels here +default = [ + "defmt-default", + # "dependency-a/defmt-trace", +] + +# do NOT modify these features +defmt-default = [] +defmt-trace = [] +defmt-debug = [] +defmt-info = [] +defmt-warn = [] +defmt-error = [] + +# cargo build/run +[profile.dev] +codegen-units = 1 +debug = 2 +debug-assertions = true # <- +incremental = false +opt-level = 'z' # <- +overflow-checks = true # <- + +# cargo test +[profile.test] +codegen-units = 1 +debug = 2 +debug-assertions = true # <- +incremental = false +opt-level = 3 # <- +overflow-checks = true # <- + +# cargo build/run --release +[profile.release] +codegen-units = 1 +debug = 2 +debug-assertions = false # <- +incremental = false +lto = 'fat' +opt-level = 3 # <- +overflow-checks = false # <- + +# cargo test --release +[profile.bench] +codegen-units = 1 +debug = 2 +debug-assertions = false # <- +incremental = false +lto = 'fat' +opt-level = 3 # <- +overflow-checks = false # <- + +# uncomment this to switch from the crates.io version of defmt to its git version +# check app-template's README for instructions +# [patch.crates-io] +# defmt = { git = "https://github.com/knurling-rs/defmt", rev = "use defmt version reported by `probe-run --version`" } +# defmt-rtt = { git = "https://github.com/knurling-rs/defmt", rev = "use defmt version reported by `probe-run --version`" } +# defmt-test = { git = "https://github.com/knurling-rs/defmt", rev = "use defmt version reported by `probe-run --version`" } +# panic-probe = { git = "https://github.com/knurling-rs/defmt", rev = "use defmt version reported by `probe-run --version`" } diff --git a/memory.x b/memory.x new file mode 100644 index 0000000..a00eaf6 --- /dev/null +++ b/memory.x @@ -0,0 +1,6 @@ +/* bluepill using STM32F103C8T6 */ +MEMORY +{ + FLASH : ORIGIN = 0x08000000, LENGTH = 64K + RAM : ORIGIN = 0x20000000, LENGTH = 20K +} diff --git a/src/main.rs b/src/main.rs new file mode 100644 index 0000000..3bf11ca --- /dev/null +++ b/src/main.rs @@ -0,0 +1,169 @@ +#![no_main] +#![no_std] +use defmt_rtt as _; // global logger + +use panic_probe as _; +use stm32f1xx_hal as _; + +// same panicking *behavior* as `panic-probe` but doesn't print a panic message +// this prevents the panic message being printed *twice* when `defmt::panic` is invoked +#[defmt::panic_handler] +fn panic() -> ! { + cortex_m::asm::udf() +} + +use rtic::app; + +#[app(device = stm32f1xx_hal::pac, peripherals = true, dispatchers = [SPI2])] +mod app { + + use stm32f1xx_hal::{ + gpio::{gpioc, Output, PushPull}, + prelude::*, + usb::{Peripheral, UsbBus}, + }; + + use usb_device::class_prelude::UsbBusAllocator; + use usb_device::prelude::*; + use usbd_audio::{AudioClass, AudioClassBuilder, Format, StreamConfig, TerminalType}; + + use systick_monotonic::Systick; + + #[monotonic(binds = SysTick, default = true)] + type MonoTimer = Systick<1_000>; + + #[shared] + struct Shared { + usb_dev: UsbDevice<'static, UsbBus>, + usb_audio: AudioClass<'static, UsbBus>, + board_led: gpioc::PC13>, + } + + #[local] + struct Local {} + + #[init(local = [usb_bus: Option>> = None])] + fn init(mut cx: init::Context) -> (Shared, Local, init::Monotonics) { + let mut flash = cx.device.FLASH.constrain(); + let rcc = cx.device.RCC.constrain(); + + // Freeze the configuration of all the clocks in the system and store the frozen frequencies in + // `clocks` + let clocks = rcc + .cfgr + .use_hse(8.MHz()) + .sysclk(72.MHz()) + .pclk1(36.MHz()) + .freeze(&mut flash.acr); + + defmt::info!("Clock Setup done"); + + // Acquire the GPIOC peripheral + let mut gpioa = cx.device.GPIOA.split(); + //let mut gpiob = cx.device.GPIOB.split(); + let mut gpioc = cx.device.GPIOC.split(); + + let board_led = gpioc.pc13.into_push_pull_output(&mut gpioc.crh); + defmt::info!("ADC Setup done"); + + // BluePill board has a pull-up resistor on the D+ line. + // Pull the D+ pin down to send a RESET condition to the USB bus. + // This forced reset is needed only for development, without it host + // will not reset your device when you upload new firmware. + let mut usb_dp = gpioa.pa12.into_push_pull_output(&mut gpioa.crh); + let mut delay = cortex_m::delay::Delay::new(cx.core.SYST, clocks.sysclk().to_Hz()); + usb_dp.set_low(); + delay.delay_ms(10); + cx.core.SYST = delay.free(); + + let usb_dm = gpioa.pa11; + let usb_dp = usb_dp.into_floating_input(&mut gpioa.crh); + + let usb = Peripheral { + usb: cx.device.USB, + pin_dm: usb_dm, + pin_dp: usb_dp, + }; + + let usb_bus: &'static _ = cx.local.usb_bus.insert(UsbBus::new(usb)); + + let usb_audio = AudioClassBuilder::new() + .input( + StreamConfig::new_discrete(Format::S16le, 1, &[48000], TerminalType::InMicrophone) + .unwrap(), + ) + .output( + StreamConfig::new_discrete(Format::S16le, 1, &[48000], TerminalType::OutSpeaker) + .unwrap(), + ) + .build(&usb_bus) + .unwrap(); + + let usb_dev = UsbDeviceBuilder::new(&usb_bus, UsbVidPid(0x16c0, 0x27dd)) + .max_packet_size_0(64) + .manufacturer("Kiffie Labs") + .product("Audio port") + .serial_number("42") + .build(); + + let mono = Systick::new(cx.core.SYST, clocks.sysclk().to_Hz()); + + ( + Shared { + usb_dev, + usb_audio, + board_led, + }, + Local {}, + init::Monotonics(mono), + ) + } + + #[task(binds = USB_HP_CAN_TX, shared = [usb_dev, usb_audio])] + fn usb_tx(cx: usb_tx::Context) { + defmt::info!("usb_tx called"); + let mut usb_dev = cx.shared.usb_dev; + let mut usb_audio = cx.shared.usb_audio; + + (&mut usb_dev, &mut usb_audio).lock(|usb_dev, usb_audio| { + if !usb_dev.poll(&mut [usb_audio]) { + return; + } + }); + } + + #[task(binds = USB_LP_CAN_RX0, shared = [usb_dev, usb_audio])] + fn usb_rx0(cx: usb_rx0::Context) { + defmt::info!("usb_rx called"); + let mut usb_dev = cx.shared.usb_dev; + let mut usb_audio = cx.shared.usb_audio; + + (&mut usb_dev, &mut usb_audio).lock(|usb_dev, usb_audio| { + if !usb_dev.poll(&mut [usb_audio]) { + return; + } + + //TODO: Do something with usb_audio.read(); + }); + } + + #[idle(shared = [usb_audio, board_led])] + fn idle(mut cx: idle::Context) -> ! { + defmt::info!("Idle Task"); + let sinetab = [ + 0i16, 4276, 8480, 12539, 16383, 19947, 23169, 25995, 28377, 30272, 31650, 32486, 32767, + 32486, 31650, 30272, 28377, 25995, 23169, 19947, 16383, 12539, 8480, 4276, 0, -4276, + -8480, -12539, -16383, -19947, -23169, -25995, -28377, -30272, -31650, -32486, -32767, + -32486, -31650, -30272, -28377, -25995, -23169, -19947, -16383, -12539, -8480, -4276, + ]; + let sinetab_le = unsafe { &*(&sinetab as *const _ as *const [u8; 96]) }; + + loop { + defmt::info!("Writing samples"); + cx.shared.usb_audio.lock(|usb_audio| { + usb_audio.write(sinetab_le).ok(); + }); + rtic::export::wfi(); + } + } +}