diff --git a/Cargo.toml b/Cargo.toml index 95f4dfc4a4d420392db96e6b1726f94609a64c1b..a6f3ab5c2add40a7d6173aba58370dbe46b7c236 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -19,6 +19,7 @@ panic-semihosting = "0.5.1" panic-itm = "0.4.0" bare-metal = "0.2.4" nb = "0.1.1" +heapless = "0.4.1" [dependencies.cortex-m-rtfm] version = "0.4.0" diff --git a/examples/bare7.rs b/examples/bare7.rs new file mode 100644 index 0000000000000000000000000000000000000000..89ada1fb4ddec34245811518503f46ddf4c7a7c8 --- /dev/null +++ b/examples/bare7.rs @@ -0,0 +1,195 @@ +//! Serial echo +//! +//! Connect using e.g., `moserial` to `/dev/ttyACM0` +//! 115200 8N1 +//! +//! The MCU will echo incoming data and send a trace over ITM. +//! Notice, as the hardware has a single byte buffer only, the input +//! buffer may overflow. + +#![deny(unsafe_code)] +#![feature(uniform_paths)] +#![deny(warnings)] +#![no_main] +#![no_std] + +extern crate panic_halt; + +use cortex_m::iprintln; +use cortex_m_rt::entry; +use nb::block; + +extern crate stm32f4xx_hal as hal; +use crate::hal::prelude::*; +use crate::hal::serial::{config::Config, Serial}; + +#[entry] +fn main() -> ! { + let mut c = hal::stm32::CorePeripherals::take().unwrap(); + let stim = &mut c.ITM.stim[0]; + iprintln!(stim, "bare7"); + + let p = hal::stm32::Peripherals::take().unwrap(); + + let rcc = p.RCC.constrain(); + + // 16 MHz (default, all clocks) + let clocks = rcc.cfgr.freeze(); + + let gpioa = p.GPIOA.split(); + + let tx = gpioa.pa2.into_alternate_af7(); + let rx = gpioa.pa3.into_alternate_af7(); // try comment out + + let serial = Serial::usart2( + p.USART2, + (tx, rx), + Config::default().baudrate(115_200.bps()), + clocks, + ) + .unwrap(); + + // Separate out the sender and receiver of the serial port + let (mut tx, mut rx) = serial.split(); + + loop { + match block!(rx.read()) { + Ok(byte) => { + iprintln!(stim, "Ok {:?}", byte); + let _ = tx.write(byte); + } + Err(err) => { + iprintln!(stim, "Error {:?}", err); + } + } + } +} + +// 0. Background reading: +// STM32F401xD STM32F401xE, section 3.11 +// We have two AMBA High-performance Bus (AHB) +// APB1 low speed bus (max freq 42 MHz) +// APB2 high speed bus (max frex 84 MHz) +// +// RM0368 Section 6.2 +// Some important/useful clock acronymes and their use: +// +// SYSCLK - the clock that drives the `core` +// HCLK - the clock that drives the AMBA bus(es), memory, DMA, trace unit, etc. +// +// Typically we set HCLK = SYSCLK / 1 (no prescale) for our applications +// +// FCLK - Free running clock runing at HCLK +// +// CST - CoreSystemTimer drives the SysTick counter, HCLK/(1 or 8) +// PCLK1 - The clock driving the APB1 (<= 42 MHz) +// Timers on the APB1 bus will be triggered at PCLK1 * 2 +// PCLK2 - The clock driving the APB2 (<= 84 MHz) +// Timers on the APB2 bus will be triggered at PCLK2 +// +// 1. The rcc.cfgr. ... .freeze set the clock according to the configuration given. +// +// rcc.cfgr.freeze(); sets a default configuration. +// sysclk = hclk = pclk1 = pclk2 = 16MHz +// +// What is wrong with the following configurations? +// +// rcc.cfgr.sysclk(64.mhz()).pclk1(64.mhz()).pclk2(64.mhz()).freeze(); +// +// ** your answer here ** +// +// rcc.cfgr.sysclk(84.mhz()).pclk1(42.mhz()).pclk2(64.mhz()).freeze(); +// +// ** your answer here ** +// +// commit your answers (bare7_1) +// +// Tip: You may use `stm32cubemx` to get a graphical view for experimentation. +// This is a good tool when designing your PCB (as pinouts are given). +// +// 2. Now give the system with a valid clock, sysclk of 84 MHz. +// +// Include the code for outputting the clock to MCO2. +// +// Repeat the expermient bare6_2. +// +// What is the frequency of MCO2 read by the oscilloscope. +// +// ** your answer here ** +// +// Compute the value of SYSCLK based on the oscilloscope reading. +// +// ** your answer here ** +// +// What is the peak to peak reading of the signal. +// +// ** your answer here ** +// +// Make a screen dump or photo of the oscilloscope output. +// Save the the picture as "bare_6_84mhz_high_speed" +// +// commit your answers (bare7_2) +// +// 3. Now reprogram the PC9 to be "Low Speed", and re-run at 84Mz. +// +// Did the frequency change in comparison to assignment 5? +// +// ** your answer here ** +// +// What is the peak to peak reading of the signal (and why did it change)? +// +// ** your answer here ** +// +// Make a screen dump or photo of the oscilloscope output. +// Save the the picture as "bare_6_84mhz_low_speed". +// +// commit your answers (bare7_3) +// +// 4. Revisit the `README.md` regarding serial communication. +// +// Run the example, make sure your ITM is set to 84MHz. +// +// Verify that sent bytes are echoed back, and that ITM tracing is working. +// If not go back check your ITM setting, clocks etc. +// +// Now Try sending a string of characters `abcdef`. +// +// What was the ITM trace output? +// +// ** your answer here ** +// +// Explain why the buffer overflows. +// +// ** your answer here ** +// +// commit your answers (bare7_4) +// +// Discussion: +// Common to all MCUs is that they have multiple clocking options. +// Understanding the possibilities and limitations of clocking is fundamental +// to designing both the embedded hardware and software. Tools like +// `stm32cubemx` can be helpful to give you the big picture. +// You will likely finding it useful when designing your board (e.g., checking +// what functionality can be associated to each pin etc.) +// +// The `stm32f4xx-hal` gives you an abstraction for programming, +// setting up clocks, assigning pins, etc. +// +// The hal is under development, and already covers some basic functionality +// like serial communication. Still, in order to fully understand what is +// going on under the hood you need to check the documentation (data sheets, +// user manuals etc.) +// +// Your crate can be autmatically documentedthread: +// +// $ cargo doc --open --features stm32f4 +// +// This will document both your crate and its dependencies besides the `core` library. +// +// You can open the `core` library documentation by +// +// $ rustup doc +// +// or just show the path to the doc (to open it manually) +// +// $ rustup doc --path