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

usart_clk

parent 8dd4a304
No related branches found
No related tags found
No related merge requests found
......@@ -66,6 +66,21 @@
],
"cwd": "${workspaceRoot}"
},
{
"type": "gdb",
"request": "attach",
"name": "Debug usart_clk",
"gdbpath": "/usr/bin/arm-none-eabi-gdb",
"target": ":3333",
"remote": true,
"autorun": [
"monitor reset init",
"monitor arm semihosting enable",
"file ./target/thumbv7em-none-eabihf/debug/examples/usart_clk",
"load"
],
"cwd": "${workspaceRoot}"
},
{
"type": "gdb",
"request": "attach",
......
......
......@@ -35,6 +35,18 @@
"$rustc"
]
},
{
"taskName": "xargo build --example usart_clk",
"type": "shell",
"command": "xargo build --example usart_clk",
"group": {
"kind": "build",
"isDefault": true
},
"problemMatcher": [
"$rustc"
]
},
{
"taskName": "xargo build --example itm",
"type": "shell",
......@@ -50,10 +62,6 @@
"problemMatcher": [
"$rustc"
],
"group": {
"kind": "build",
"isDefault": true
}
},
{
"type": "shell",
......
......
//! Test the USART1 instance
//!
//! Connect the TX and RX pins to run this test
//!
//! PA2 (TX), PA3(RX) on the MCU is connected to the pin header CN3
//#![deny(unsafe_code)]
#![deny(warnings)]
#![allow(warnings)]
#![feature(proc_macro)]
#![no_std]
extern crate cortex_m_rtfm as rtfm;
extern crate cortex_m_semihosting as semihosting;
extern crate hal;
#[macro_use]
extern crate nb;
#[macro_use]
extern crate nucleo_64;
extern crate stm32f40x;
use hal::usart::USART;
use nucleo_64::time::Hertz;
use rtfm::app;
use core::ptr;
use nucleo_64::apb1;
const BAUD_RATE: Hertz = Hertz(115_200);
app! {
device: nucleo_64::stm32f40x,
}
use stm32f40x::USART2;
fn serial_init(p: &init::Peripherals) {
// RM0368 6.3.9
// enable clock to GPIOA, USART2
p.RCC.ahb1enr.modify(|_, w| w.gpioaen().enable());
// enable clock to
p.RCC.apb1enr.modify(|_, w| w.usart2en().bit(true));
// PA2 = TX, PA3 = RX
// p.AFIO.mapr.modify(|_, w| w.usart2_remap().clear_bit());
// RM0368 8.4.1
// set output mode for GPIOA
// PA2 = TX (output mode), PA3 = RX (input mode)
p.GPIOA.moder.modify(|_, w| {
w.moder2()
.variant(stm32f40x::gpioa::moder::MODER15W::ALTERNATEMODE)
.moder3()
.variant(stm32f40x::gpioa::moder::MODER15W::ALTERNATEMODE)
});
// we don't care about the speed register atm
// DM00102166
// AF7, Table 9
// PA2 and PA3 is connected to USART2 TX and RX respectively
p.GPIOA.afrl.modify(|_, w| w.afrl2().af7().afrl3().af7());
// 8N1, stop bit
p.USART2.cr2.write(|w| unsafe { w.stop().bits(0b00) });
// baud rate
// let brr :<U::Ticks>= BAUD_RATE.into();
let brr: apb1::Ticks = BAUD_RATE.invert().into();
let brr = brr.0;
assert!(brr >= 16, "impossible baud rate");
p.USART2.brr.write(|w| unsafe { w.bits(brr) });
// disable hardware flow control
// enable DMA TX and RX transfers
p.USART2.cr3.write(|w| {
w.rtse() /* Ready To Send disable */
.clear_bit()
.ctse() /* Clear To Send disable */
.clear_bit()
.dmat() /* Enable DMA Transmit */
.set_bit()
.dmar() /* Enable DMA Receive */
.set_bit()
});
// enable TX, RX; disable parity checking
p.USART2.cr1.write(|w| {
w.ue() /* Usart Enable */
.set_bit()
.re() /* Receiver Enable */
.set_bit()
.te() /* Transmitter Enable */
.set_bit()
.m() /* Word Length, 8 */
.clear_bit()
.pce() /* Parity Control Enable */
.clear_bit()
.rxneie() /* Reception Interrupt Enable */
.clear_bit()
});
}
fn clk_init(p: &init::Peripherals) {
// setting up the flash memory latency
// RM0368 8.4.1 (register), 3.4 Table 6
// we assume 3.3 volt operation, thus 2 cycles for 84mHz
p.FLASH.acr.modify(|_, w| unsafe { w.latency().bits(2) });
p.FLASH.acr.modify(|_, w| unsafe { w.latency().bits(2) });
println!("Init! {:x}", p.FLASH.acr.read().latency().bits());
p.RCC
.cfgr
.modify(|_, w| w.sw0().clear_bit().sw1().clear_bit()); //Switch to HSI
p.RCC.cfgr.modify(|_, w| unsafe { w.ppre1().bits(4) }); //Configure apb1 prescaler = 2
p.RCC.apb1enr.modify(|_, w| w.pwren().set_bit());
p.RCC.cr.write(|w| w.pllon().clear_bit());
//Enable PLL
// PP PLLN PLLM
// 0b0000 0000 0000 00 01 0 101010000 010000
// RM0368 6.3.2
p.RCC
.pllcfgr
.write(|w| unsafe { w.bits(0b00000000000000010101010000010000) }); //Configure PLL
p.RCC.cr.modify(|_, w| w.pllon().set_bit()); //Enable PLL
while p.RCC.cr.read().pllrdy().bit_is_clear() {}
p.RCC.cfgr.modify(|_, w| w.sw0().clear_bit()); //Switch to PLL
p.RCC.cfgr.modify(|_, w| w.sw1().set_bit()); //Switch to PLL
p.RCC.apb2enr.modify(|_, w| w.syscfgen().set_bit());
p.RCC.ahb1enr.modify(|_, w| w.gpioaen().set_bit()); //Enable GPIOA clock
p.RCC.ahb1enr.modify(|_, w| w.gpioben().set_bit()); //Enable GPIOB clock
//USART::send(p.USART2, "\n\n\nUSART initialized\n\r");
}
#[inline(never)]
fn init(p: init::Peripherals) {
println!("Init!");
clk_init(&p);
//serial_init(&p);
USART::initialize(p.GPIOA, p.RCC, p.USART2);
USART::send(p.USART2, "\n\n\nUSART \n\r");
loop {
let b = block!(read(p.USART2)).unwrap();
write(p.USART2, b).unwrap();
}
}
// Specialized `Result` type
pub type Result<T> = ::core::result::Result<T, nb::Error<Error>>;
/// An error
#[derive(Debug)]
pub enum Error {
/// De-synchronization, excessive noise or a break character detected
Framing,
/// Noise detected in the received frame
Noise,
/// RX buffer overrun
Overrun,
#[doc(hidden)] _Extensible,
}
fn write(usart2: &USART2, byte: u8) -> Result<()> {
let sr = usart2.sr.read();
if sr.ore().bit_is_set() {
Err(nb::Error::Other(Error::Overrun))
} else if sr.nf().bit_is_set() {
Err(nb::Error::Other(Error::Noise))
} else if sr.fe().bit_is_set() {
Err(nb::Error::Other(Error::Framing))
} else if sr.txe().bit_is_set() {
// NOTE(write_volatile) see NOTE in the `read` method
unsafe { ptr::write_volatile(&usart2.dr as *const _ as *mut u8, byte) }
Ok(())
} else {
Err(nb::Error::WouldBlock)
}
}
fn read(usart2: &USART2) -> Result<u8> {
let sr = usart2.sr.read();
if sr.ore().bit_is_set() {
Err(nb::Error::Other(Error::Overrun))
} else if sr.nf().bit_is_set() {
Err(nb::Error::Other(Error::Noise))
} else if sr.fe().bit_is_set() {
Err(nb::Error::Other(Error::Framing))
} else if sr.rxne().bit_is_set() {
// NOTE(read_volatile) the register is 9 bits big but we'll only
// work with the first 8 bits
Ok(unsafe {
ptr::read_volatile(&usart2.dr as *const _ as *const u8)
})
} else {
Err(nb::Error::WouldBlock)
}
}
fn idle() -> ! {
// Will never be hit, as
rtfm::bkpt();
// Sleep
loop {
rtfm::wfi();
}
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment