diff --git a/examples/blinky-blocking.rs b/examples/blinky-blocking.rs index 9a09898504625a53a9901723f72c67a30caba5d1..1088983c04d086aa6dba04e8b39b3f774e2f20cf 100644 --- a/examples/blinky-blocking.rs +++ b/examples/blinky-blocking.rs @@ -17,6 +17,7 @@ use f4::Timer; use f4::led::{self, LED}; use f4::prelude::*; use f4::time::Hertz; +use f4::clock; use rtfm::{app, Threshold}; const FREQUENCY: Hertz = Hertz(1); @@ -30,8 +31,10 @@ app! { } fn init(p: init::Peripherals) { - led::init(p.GPIOA, p.RCC); + // Set system clock in order to test that it works + clock::set_84_mhz(&p.RCC, &p.FLASH); + led::init(p.GPIOA, p.RCC); let timer = Timer(&*p.TIM11); timer.init(FREQUENCY.invert(), p.RCC); diff --git a/examples/mco.rs b/examples/mco.rs index ab4cf3aacfe5901df5efafa7f3f7b56e4a986e90..ccded2f728642ab019b7de09f1acf838b6c535fe 100644 --- a/examples/mco.rs +++ b/examples/mco.rs @@ -3,20 +3,35 @@ #![feature(proc_macro)] #![no_std] +extern crate cortex_m; extern crate cortex_m_rtfm as rtfm; extern crate f4; -use rtfm::app; +use rtfm::{app, Threshold}; use f4::led::{self, LED}; use f4::clock; +use cortex_m::peripheral::SystClkSource; + +const FREQUENCY: u32 = 10; // Hz // TASKS & RESOURCES app! { device: f4::stm32f40x, + + resources: { + static ON: bool = false; + }, + + tasks: { + SYS_TICK: { + path: toggle, + resources: [ON], + }, + }, } // INITIALIZATION PHASE -fn init(p: init::Peripherals) { +fn init(p: init::Peripherals, _r: init::Resources) { // See RM0368 6.2.10 Clock-out capability // PC9 outputs SYSCLK/4 MHz and PA8 the frequency of the HSI RC @@ -41,22 +56,38 @@ fn init(p: init::Peripherals) { p.RCC.cfgr.modify(|_, w| unsafe { w.mco2pre().bits(0b110) }); //Divide SYSCLK by 4 // Set the clock to 84 MHz for compatibility with stm32f401 - clock::set_84_mhz(&p.RCC, &p.FLASH); - + // let clk = clock::set_84_mhz(&p.RCC, &p.FLASH); + // The stm32f411 supports 100 MHz. - // clock::set_100_mhz(&p.RCC, &p.FLASH); + let clk = clock::set_100_mhz(&p.RCC, &p.FLASH); // We can also use a lower frequency by providing valid PLL constants. // Since the HSI RC is 16 MHz, we get 16/8*50/4 = 25 MHz - // clock::set(&p.RCC, &p.FLASH, 8, 50, 4); + // let clk = clock::set(&p.RCC, &p.FLASH, 8, 50, 4); // Light the green LED when we start idling. led::init(&p.GPIOA, &p.RCC); + + p.SYST.set_clock_source(SystClkSource::Core); + p.SYST.set_reload(clk / FREQUENCY); + p.SYST.enable_interrupt(); + p.SYST.enable_counter(); +} + +// TASKS +// Toggle the state of the LED +fn toggle(_t: &mut Threshold, r: SYS_TICK::Resources) { + **r.ON = !**r.ON; + + if **r.ON { + LED.on(); + } else { + LED.off(); + } } // IDLE LOOP fn idle() -> ! { - LED.on(); // Sleep loop { rtfm::wfi(); diff --git a/examples/usart2-dma.rs b/examples/usart2-dma.rs index 1e946cd3ce12291d0b121b91aada7b07750048e1..7d1e2c89131aa7d6e7f4da056c05401ddd186357 100644 --- a/examples/usart2-dma.rs +++ b/examples/usart2-dma.rs @@ -17,6 +17,7 @@ use f4::Writer as w; use f4::prelude::*; use f4::dma::{Buffer, Dma1Channel5, Dma1Channel6}; use f4::time::Hertz; +use f4::clock; use heapless::Vec; use rtfm::{app, Threshold}; @@ -52,7 +53,11 @@ app! { }, }, } + fn init(p: init::Peripherals, r: init::Resources) { + // Set clock to higher than default in order to test it works + clock::set_84_mhz(&p.RCC, &p.FLASH); + // There is no need to claim() resources in the init. // Start the serial port let serial = Serial(p.USART2); @@ -98,8 +103,9 @@ fn rx_done(t: &mut Threshold, mut r: DMA1_STREAM5::Resources) { } if byte == b'\r' { // If we got carrige return, send new line as well - if serial.write(b'\n').is_err() { - rtfm::bkpt(); + while serial.write(b'\n').is_err() { + // Since we just transmitted carrige return, + // we need to wait until tx line is free } } // Get ready to receive again diff --git a/src/clock.rs b/src/clock.rs index a1dc1caf5c29c9920f1bb5ff141e662d8802ff5a..a74a0790856725f4e0d320041cacc01a7598a695 100644 --- a/src/clock.rs +++ b/src/clock.rs @@ -21,7 +21,7 @@ fn calculate_pll(m: u8, n: u16, p: u8) -> (u32, u32) { }, _ => panic!("Invalid PLLN multiplier"), }; - let log2p = match p { + let pval = match p { 2 => 0b00, 4 => 0b01, 6 => 0b10, @@ -32,7 +32,7 @@ fn calculate_pll(m: u8, n: u16, p: u8) -> (u32, u32) { 24_000_000...100_000_000 => vco_clock / p as u32, _ => panic!("Invalid PLLP output frequency"), }; - let pll_bitmask = ((log2p as u32) << 16) | ((n as u32) << 6) | (m as u32); + let pll_bitmask = ((pval as u32) << 16) | ((n as u32) << 6) | (m as u32); (pll_bitmask, pll_output) } @@ -45,9 +45,12 @@ pub fn set(rcc: &RCC, flash: &FLASH, m: u8, n: u16, p: u8) -> u32 { // setting up the flash memory latency // RM0368 8.4.1 (register), 3.4 Table 6 - // apb1 will be at 42 MHz + // apb1 will be at half system clock rcc.cfgr.modify(|_, w| unsafe { w.ppre1().bits(4) }); //Configure apb1 prescaler = 2, ::apb1::set_frequency(hclk / 2); + ::ahb1::set_frequency(hclk); + ::ahb2::set_frequency(hclk); + ::apb2::set_frequency(hclk); // we assume 3.3 volt operation, thus 2 cycles for 84MHz flash.acr.modify(|_, w| unsafe { diff --git a/src/serial.rs b/src/serial.rs index c0f7e824b59d1d806f1d7fdbdc97d7910aa1452f..35f336b69343f472a1a1913812683ed2c83d3638 100644 --- a/src/serial.rs +++ b/src/serial.rs @@ -22,7 +22,6 @@ use stm32f40x::{gpioa, DMA1, USART2, usart6, GPIOA, RCC}; use dma::{self, Buffer, Dma1Channel5, Dma1Channel6}; use core::fmt; -use core::iter; /// pub struct Writer<'a> { @@ -237,7 +236,15 @@ where usart.cr2.write(|w| unsafe { w.stop().bits(0b00) }); // baud rate - let brr = baud_rate.into(); + // Check if peripheral does not use default clock + let apb1psc = match rcc.cfgr.read().ppre1().bits() { + 0b100 => 2, + 0b101 => 4, + 0b110 => 8, + 0b111 => 16, + _ => 1, + }; + let brr = baud_rate.into() / apb1psc; assert!(brr >= 16, "impossible baud rate"); usart.brr.write(|w| unsafe { w.bits(brr) }); @@ -394,6 +401,7 @@ impl<'a> Serial<'a, USART2> { where B: Unsize<[u8]>, { + // write!(dma1, "hi {}", 1); let usart2 = self.0; if dma1.s6cr.read().en().bit_is_set() {