#![no_std]
#![no_main]
extern crate cortex_m;
#[macro_use(block)]
extern crate nb;
#[macro_use]
extern crate log;
use panic_halt as _;
use cortex_m::asm;
use cortex_m::asm::wfi;
use rtfm::app;
//use cortex_m_semihosting as sh; // semihosting
//use cortex_m_semihosting::hprintln; // semihosting
use embedded_hal::digital::v2::OutputPin;
use stm32l4xx_hal::{
gpio::{gpiob::PB3, Output, PushPull},
pac,
prelude::*,
timer::{Event, Timer},
delay::Delay,
i2c::I2c,
serial::{Config, Serial, Event as SerialEvent, Error},
time::{MonoTimer, Instant},
stm32,
dma::{dma1, CircBuffer},
};
extern crate cortex_m_rt as rt;
extern crate panic_halt;
use rt::{exception, pre_init, ExceptionFrame};
#[app(device = stm32l4xx_hal::pac)]
const APP: () = {
static mut LED_STATE: bool = ();
static mut LED: PB3<Output<PushPull>> = ();
static mut TIMER_HANDLER: Timer<pac::TIM7> = ();
static mut USART1_RX: stm32l4xx_hal::serial::Rx<stm32l4xx_hal::stm32l4::stm32l4x2::USART1> = ();
static mut USART1_TX: stm32l4xx_hal::serial::Tx<stm32l4xx_hal::stm32l4::stm32l4x2::USART1> = ();
#[init(resources = [])]
fn init() -> init::LateResources {
core.DCB.enable_trace(); // required for DWT cycle clounter to work when not connected to the debugger
core.DWT.enable_cycle_counter();
let mut flash = device.FLASH.constrain();
let mut rcc = device.RCC.constrain();
let mut gpioa = device.GPIOA.split(&mut rcc.ahb2);
let mut gpiob = device.GPIOB.split(&mut rcc.ahb2);
let clocks = rcc
.cfgr
.sysclk(80.mhz())
.pclk1(80.mhz())
.pclk2(80.mhz())
.freeze(&mut flash.acr);
let mut delay = Delay::new(core.SYST, clocks);
// user led
let led = gpiob
.pb3
.into_push_pull_output(&mut gpiob.moder, &mut gpiob.otyper);
// serial peripheral
let tx = gpiob.pb6.into_af7(&mut gpiob.moder, &mut gpiob.afrl);
let rx = gpiob.pb7.into_af7(&mut gpiob.moder, &mut gpiob.afrl);
let mut serial = Serial::usart1(
device.USART1,
(tx, rx),
Config::default().baudrate(115_200.bps()),
clocks,
&mut rcc.apb2,
);
serial.listen(SerialEvent::Idle); // listen to Idle Line detection, it is NOT enable until after init is complete
let (tx, rx) = serial.split();
delay.delay_ms(100_u8); // allow module to boot
init::LateResources {
USART1_RX: rx,
USART1_TX: tx,
LED_STATE: true,
LASER_SENSORS: laser_sensors,
LASER_VALUES: laser_sensors_val,
LED: led,
TIMER_HANDLER: timer,
}
}
#[idle]
fn idle() -> ! {
loop {
wfi();
}
}
#[interrupt(binds = TIM7, priority = 1, resources = [LED_STATE, LED, TIMER_HANDLER, USART1_RX, USART1_TX])]
fn systick() {
if *resources.LED_STATE == false{
resources.LED.set_high().unwrap();
*resources.LED_STATE = true;
} else {
resources.LED.set_low().unwrap();
*resources.LED_STATE = false;
}
match block!(resources.USART1_RX.read()){
Ok(received) => block!(resources.USART1_TX.write(b'D')).ok(),
Err(e) => match e {
Error::Framing => block!(resources.USART1_TX.write(b'F')).ok(),
Error::Noise => block!(resources.USART1_TX.write(b'N')).ok(),
Error::Overrun => block!(resources.USART1_TX.write(b'O')).ok(),
Error::Parity => block!(resources.USART1_TX.write(b'P')).ok(),
_ => block!(resources.USART1_TX.write(b'U')).ok()
}
};
block!(resources.USART1_TX.write(b'=')).ok();
//block!(resources.USART1_TX.write(received)).ok();
resources.TIMER_HANDLER.clear_update_interrupt_flag();
}
};
#[exception]
fn HardFault(ef: &ExceptionFrame) -> ! {
panic!("{:#?}", ef);
}