diff --git a/.gitignore b/.gitignore index 597fbb9..4cd4ef4 100644 --- a/.gitignore +++ b/.gitignore @@ -7,3 +7,4 @@ Cargo.lock bloat_log* itm.txt .gdb_history +.vscode/STM32F407.svd diff --git a/.vscode/.cortex-debug.peripherals.state.json b/.vscode/.cortex-debug.peripherals.state.json new file mode 100644 index 0000000..0637a08 --- /dev/null +++ b/.vscode/.cortex-debug.peripherals.state.json @@ -0,0 +1 @@ +[] \ No newline at end of file diff --git a/.vscode/.cortex-debug.registers.state.json b/.vscode/.cortex-debug.registers.state.json new file mode 100644 index 0000000..0637a08 --- /dev/null +++ b/.vscode/.cortex-debug.registers.state.json @@ -0,0 +1 @@ +[] \ No newline at end of file diff --git a/.vscode/README.md b/.vscode/README.md new file mode 100644 index 0000000..3b25b25 --- /dev/null +++ b/.vscode/README.md @@ -0,0 +1,109 @@ +# VS Code Configuration + +Example configurations for debugging programs in-editor with VS Code. +This directory contains configurations for two platforms: + + - `LM3S6965EVB` on QEMU + - `STM32F303x` via OpenOCD + +## Required Extensions + +If you have the `code` command in your path, you can run the following commands to install the necessary extensions. + +```sh +code --install-extension rust-lang.rust +code --install-extension marus25.cortex-debug +``` + +Otherwise, you can use the Extensions view to search for and install them, or go directly to their marketplace pages and click the "Install" button. + +- [Rust Language Server (RLS)](https://marketplace.visualstudio.com/items?itemName=rust-lang.rust) +- [Cortex-Debug](https://marketplace.visualstudio.com/items?itemName=marus25.cortex-debug) + +## Use + +The quickstart comes with two debug configurations. +Both are configured to build the project, using the default settings from `.cargo/config`, prior to starting a debug session. + +1. QEMU: Starts a debug session using an emulation of the `LM3S6965EVB` mcu. + - This works on a fresh `cargo generate` without modification of any of the settings described above. + - Semihosting output will be written to the Output view `Adapter Output`. + - `ITM` logging does not work with QEMU emulation. + +2. OpenOCD: Starts a debug session for a `STM32F3DISCOVERY` board (or any `STM32F303x` running at 8MHz). + - Follow the instructions above for configuring the build with `.cargo/config` and the `memory.x` linker script. + - `ITM` output will be written to the Output view `SWO: ITM [port: 0, type: console]` output. + +### Git + +Files in the `.vscode/` directory are `.gitignore`d by default because many files that may end up in the `.vscode/` directory should not be committed and shared. +If you would like to save this debug configuration to your repository and share it with your team, you'll need to explicitly `git add` the files to your repository. + +```sh +git add -f .vscode/launch.json +git add -f .vscode/tasks.json +git add -f .vscode/*.svd +``` + +## Customizing for other targets + +For full documentation, see the [Cortex-Debug][cortex-debug] repository. + +### Device + +Some configurations use this to automatically find the SVD file. +Replace this with the part number for your device. + +```json +"device": "STM32F303VCT6", +``` + +### OpenOCD Config Files + +The `configFiles` property specifies a list of files to pass to OpenOCD. + +```json +"configFiles": [ + "interface/stlink-v2-1.cfg", + "target/stm32f3x.cfg" +], +``` + +See the [OpenOCD config docs][openocd-config] for more information and the [OpenOCD repository for available configuration files][openocd-repo]. + +### SVD + +The SVD file is a standard way of describing all registers and peripherals of an ARM Cortex-M mCU. +Cortex-Debug needs this file to display the current register values for the peripherals on the device. + +You can probably find the SVD for your device on the vendor's website. + + +For example, the STM32F3DISCOVERY board uses an mcu from the `STM32F303x` line of processors. +All the SVD files for the STM32F3 series are available on [ST's Website][stm32f3]. +Download the [stm32f3 SVD pack][stm32f3-svd], and copy the `STM32F303.svd` file into `.vscode/`. +This line of the config tells the Cortex-Debug plug in where to find the file. + +```json +"svdFile": "${workspaceRoot}/.vscode/STM32F303.svd", +``` + +For other processors, simply copy the correct `*.svd` file into the project and update the config accordingly. + +### CPU Frequency + +If your device is running at a frequency other than 8MHz, you'll need to modify this line of `launch.json` for the `ITM` output to work correctly. + +```json +"cpuFrequency": 8000000, +``` + +### Other GDB Servers + +For information on setting up GDB servers other than OpenOCD, see the [Cortex-Debug repository][cortex-debug]. + +[cortex-debug]: https://github.com/Marus/cortex-debug +[stm32f3]: https://www.st.com/content/st_com/en/products/microcontrollers-microprocessors/stm32-32-bit-arm-cortex-mcus/stm32-mainstream-mcus/stm32f3-series.html#resource +[stm32f3-svd]: https://www.st.com/resource/en/svd/stm32f3_svd.zip +[openocd-config]: http://openocd.org/doc/html/Config-File-Guidelines.html +[openocd-repo]: https://sourceforge.net/p/openocd/code/ci/master/tree/tcl/ diff --git a/.vscode/extensions.json b/.vscode/extensions.json new file mode 100644 index 0000000..5a6574b --- /dev/null +++ b/.vscode/extensions.json @@ -0,0 +1,14 @@ +{ + // See https://go.microsoft.com/fwlink/?LinkId=827846 to learn about workspace recommendations. + // Extension identifier format: ${publisher}.${name}. Example: vscode.csharp + + // List of extensions which should be recommended for users of this workspace. + "recommendations": [ + "rust-lang.rust", + "marus25.cortex-debug", + ], + // List of extensions recommended by VS Code that should not be recommended for users of this workspace. + "unwantedRecommendations": [ + + ] +} \ No newline at end of file diff --git a/.vscode/launch.json b/.vscode/launch.json new file mode 100644 index 0000000..b45eec7 --- /dev/null +++ b/.vscode/launch.json @@ -0,0 +1,48 @@ +{ + /* + * Requires the Rust Language Server (RLS) and Cortex-Debug extensions + * https://marketplace.visualstudio.com/items?itemName=rust-lang.rust + * https://marketplace.visualstudio.com/items?itemName=marus25.cortex-debug + */ + "version": "0.2.0", + "configurations": [ + { + "type": "cortex-debug", + "request": "launch", + "name": "Debug (QEMU)", + "servertype": "qemu", + "cwd": "${workspaceRoot}", + "preLaunchTask": "cargo build", + "runToMain": true, + "executable": "./target/thumbv7m-none-eabi/debug/{{project-name}}", + /* Run `cargo build --example hello` and uncomment this line to run semi-hosting example */ + //"executable": "./target/thumbv7m-none-eabi/debug/examples/hello", + "cpu": "cortex-m3", + "machine": "lm3s6965evb" + }, + { + /* Configuration for the STM32F407G Discovery board */ + "type": "cortex-debug", + "request": "launch", + "name": "Debug (OpenOCD)", + "servertype": "openocd", + "cwd": "${workspaceRoot}", + "preLaunchTask": "cargo build --examples", + "runToMain": true, + // "executable": "./target/thumbv7em-none-eabihf/debug/{{project-name}}", + /* Run `cargo build --example itm` and uncomment this line to run itm example */ + // "executable": "./target/thumbv7em-none-eabihf/debug/examples/itm", + "executable": "./target/thumbv7em-none-eabihf/debug/examples/audio", + "device": "STM32F407VGT6", + "configFiles": ["openocd.cfg"], + "svdFile": "${workspaceRoot}/.vscode/STM32F407.svd", + "swoConfig": { + "enabled": true, + "cpuFrequency": 168000000, + "swoFrequency": 2000000, + "source": "probe", + "decoders": [{ "type": "console", "label": "ITM", "port": 0 }] + } + } + ] +} diff --git a/.vscode/tasks.json b/.vscode/tasks.json new file mode 100644 index 0000000..73da208 --- /dev/null +++ b/.vscode/tasks.json @@ -0,0 +1,55 @@ +{ + // See https://go.microsoft.com/fwlink/?LinkId=733558 + // for the documentation about the tasks.json format + "version": "2.0.0", + "tasks": [ + { + /* + * This is the default cargo build task, + * but we need to provide a label for it, + * so we can invoke it from the debug launcher. + */ + "label": "cargo build", + "type": "process", + "command": "cargo", + "args": ["build"], + "problemMatcher": ["$rustc"], + "group": { + "kind": "build", + "isDefault": true + } + }, + { + "label": "cargo build --release", + "type": "process", + "command": "cargo", + "args": ["build", "--release"], + "problemMatcher": ["$rustc"], + "group": "build" + }, + { + "label": "cargo build --examples", + "type": "process", + "command": "cargo", + "args": ["build", "--example", "audio"], + "problemMatcher": ["$rustc"], + "group": "build" + }, + { + "label": "cargo build --examples --release", + "type": "process", + "command": "cargo", + "args": ["build", "--examples", "--release"], + "problemMatcher": ["$rustc"], + "group": "build" + }, + { + "label": "cargo clean", + "type": "process", + "command": "cargo", + "args": ["clean"], + "problemMatcher": [], + "group": "build" + } + ] +} diff --git a/Cargo.toml b/Cargo.toml index 361fb14..71c1959 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -22,20 +22,37 @@ readme = "README.md" accelerometer = "0.11.0" cortex-m = "0.6" cortex-m-rt = "0.6" -lis302dl = "0.1.0" +# lis302dl = "0.1.0" + +[dependencies.lis302dl] +path = "../lis302dl" + +[dependencies.cs43l22] +# git = "https://github.com/maxekman/cs43l22/" +# branch = "master" +path = "../cs43l22" [dependencies.embedded-hal] +# TODO: Update version when I2S proposal is finalized: +# https://github.com/rust-embedded/embedded-hal/pull/204 features = ["unproven"] -version = "0.2" +# version = "0.2.3" +# git = "https://github.com/eldruin/embedded-hal/" +# branch = "i2s-v0.2.x" +path = "../embedded-hal" [dependencies.stm32f4xx-hal] default-features = false features = ["rt", "stm32f407"] -version = "0.8.2" +# version = "0.8.2" +# git = "https://github.com/maxekman/stm32f4xx-hal/" +# branch = "i2s" +path = "../stm32f4xx-hal" [dev-dependencies] ssd1306 = "0.2" nb = "0.1" +cortex-m-log = { version = "~0.6", features = ["itm"] } panic-halt = "0.2" panic-itm = "0.4" diff --git a/examples/audio.rs b/examples/audio.rs new file mode 100644 index 0000000..4c98e33 --- /dev/null +++ b/examples/audio.rs @@ -0,0 +1,74 @@ +//! Plays a test tone through the DAC with headphone amp. + +#![no_main] +#![no_std] + +extern crate panic_itm; + +use cortex_m::peripheral::Peripherals; +use cortex_m_rt::entry; + +use stm32f407g_disc as board; + +use crate::board::{audio_out::AudioOut, hal::delay::Delay, hal::prelude::*, hal::stm32}; +use embedded_hal::blocking::i2s::Write; + +use cortex_m_log::println; +use cortex_m_log::{destination::Itm, printer::itm::InterruptSync as InterruptSyncItm}; + +#[entry] +fn main() -> ! { + let p = stm32::Peripherals::take().unwrap(); + let cp = Peripherals::take().unwrap(); + + let mut log = InterruptSyncItm::new(Itm::new(cp.ITM)); + + let gpioa = p.GPIOA.split(); + let gpiob = p.GPIOB.split(); + let gpioc = p.GPIOC.split(); + let gpiod = p.GPIOD.split(); + + // TODO: Use frequency when setting up clocks. + let audio_freq = 48000; + + // Set clock to 64 MHz and freeze. + let rcc = p.RCC.constrain(); + let clocks = rcc + .cfgr + .use_hse(8.mhz()) + .sysclk(168.mhz()) + .plli2sclk(audio_freq.hz()) + .freeze(); + + // Get delay provider. + let mut delay = Delay::new(cp.SYST, clocks); + + println!(log, "\nSetup audio output"); + let mut audio_out = AudioOut::new( + p.I2C1, p.SPI3, gpioa, gpiob, gpioc, gpiod, clocks, &mut delay, audio_freq, 128, + ); + + println!(log, "Starting audio"); + play_sawtooth(&mut audio_out.i2s); +} + +// Demonstrating decoupling of audio device and application code using the +// embedded-hal trait for I2S. +fn play_sawtooth(i2s: &mut impl Write) -> ! { + let mut s: u16 = 0; + let mut y: u16 = 100; + loop { + // Send both left and right word (without buffering). + i2s.try_write(&[s], &[s]); + + // Sawtooth with incrementing pitch each cycle. + if s >= (65535 - y) { + s = 0; + y += 1; + if y > 400 { + y = 100 + } + } + s += y; + } +} diff --git a/openocd.gdb b/openocd.gdb index 6468bbe..6a19eae 100644 --- a/openocd.gdb +++ b/openocd.gdb @@ -19,7 +19,6 @@ break main # 168000000 is the core clock frequency monitor tpiu config internal itm.txt uart off 168000000 - # OR: make the microcontroller SWO (PB3) pin output compatible with UART (8N1) # 8000000 is the frequency of the SWO pin # monitor tpiu config external uart off 8000000 2000000 diff --git a/src/audio_out.rs b/src/audio_out.rs new file mode 100644 index 0000000..6f6c61a --- /dev/null +++ b/src/audio_out.rs @@ -0,0 +1,70 @@ +//! CS43L22 DAC with headphone amp. + +use crate::hal::prelude::*; + +use crate::hal::gpio::gpioa::{self, PA4}; +use crate::hal::gpio::gpiob::{self, PB6, PB9}; +use crate::hal::gpio::gpioc::{self, PC10, PC12}; +use crate::hal::gpio::gpiod::{self, PD4}; +use crate::hal::gpio::{Alternate, AlternateOD, Output, PushPull, AF4, AF6}; +use crate::hal::i2c::*; +use crate::hal::i2s::*; +use crate::hal::rcc::Clocks; +use crate::hal::stm32::{I2C1, SPI3}; + +use embedded_hal::blocking::delay::DelayMs; + +pub use cs43l22; + +pub struct AudioOut { + pub cs43l22: cs43l22::CS43L22< + I2c>, PB9>)>, + PD4>, + >, + pub i2s: I2s< + SPI3, + ( + PC10>, + PA4>, + PC12>, + NoSdExt, + ), + >, +} + +impl AudioOut { + pub fn new>( + i2c1: I2C1, + spi3: SPI3, + gpioa: gpioa::Parts, + gpiob: gpiob::Parts, + gpioc: gpioc::Parts, + gpiod: gpiod::Parts, + clocks: Clocks, + delay: &mut DELAY, + audio_freq: u32, + vol: u8, + ) -> Self { + // Setup I2C1 using PB6 and PB9 pins at 100kHz bitrate. + let scl = gpiob.pb6.into_alternate_af4().set_open_drain(); + let sda = gpiob.pb9.into_alternate_af4().set_open_drain(); + let i2c1 = I2c::i2c1(i2c1, (scl, sda), 100.khz(), clocks); + + // CS43L22 reset pin. + let reset = gpiod.pd4.into_push_pull_output(); + + // Set PC7 into AF6 to output the MCLK for I2S3. + let _mck = gpioc.pc7.into_alternate_af6(); + + // Setup I2S3 for 48kHz audio. + let ck = gpioc.pc10.into_alternate_af6(); + let ws = gpioa.pa4.into_alternate_af6(); + let sd = gpioc.pc12.into_alternate_af6(); + let i2s3 = I2s::i2s3(spi3, (ck, ws, sd, NoSdExt), audio_freq.hz(), clocks); + + let cs43l22 = cs43l22::CS43L22::new(i2c1, reset, delay, vol) + .expect("could not create CS43L22 driver"); + + AudioOut { cs43l22, i2s: i2s3 } + } +} diff --git a/src/lib.rs b/src/lib.rs index a99e4c3..ac720f7 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -12,4 +12,5 @@ pub use cortex_m::*; pub use cortex_m_rt::*; pub mod accelerometer; +pub mod audio_out; pub mod led;