//! BLE interface. #![no_std] #![no_main] mod ble; mod i2c; mod logger; mod macros; mod rtc; mod uarte1; use clint::HandlerArray; use core::mem; use cortex_m::{asm::wfi, peripheral::NVIC}; use cortex_m_rt::{entry, exception, ExceptionFrame}; use log::{info, log, trace, Level as LogLevel, LevelFilter}; #[allow(unused_imports)] extern crate panic_semihosting; use nrf52840_mdk_bsp::{ hal::{ gpio::{Floating, Input, Level, Output, Pin, PushPull}, target::{interrupt, Interrupt, UARTE0}, twis::{self, Twis}, uarte::{self, Baudrate as UartBaudrate, Parity as UartParity, Uarte}, Clocks, Rtc, }, Board, }; const I2C_ADDR: u8 = 4; // TODO: // * bluetooth // Interrupt handler table. static HANDLERS: HandlerArray = HandlerArray::new(); #[entry] fn main() -> ! { let nrf52 = Board::take().unwrap(); let uart_wrapped = logger::WriteWrapper::new(nrf52.cdc); let logger = logger::SerialLogger::new(uart_wrapped); let logger_ref: &'static logger::SerialLogger = unsafe { mem::transmute(&logger) }; log::set_logger(logger_ref).expect("setting logger"); log::set_max_level(LevelFilter::Trace); // TODO: use hal interface for this. nrf52 .CLOCK .tasks_hfclkstart .write(|w| w.tasks_hfclkstart().set_bit()); while nrf52 .CLOCK .events_hfclkstarted .read() .events_hfclkstarted() .bit_is_clear() {} nrf52.RTC0.intenset.write(|w| w.tick().set()); let mut rtc_handler = rtc::setup(Rtc::new(nrf52.RTC0), Clocks::new(nrf52.CLOCK)); let (mut twis_reader, mut twis_handler) = i2c::setup(Twis::new( I2C_ADDR, nrf52.TWIS0, twis::Pins { scl: nrf52.pins.P0_06.into_floating_input().degrade(), sda: nrf52.pins.P0_07.into_floating_input().degrade(), }, )); let txp = nrf52 .pins .P0_26 .into_push_pull_output(Level::High) .degrade(); let rxp = nrf52.pins.P0_25.into_floating_input().degrade(); let uarte1 = uarte1(nrf52.UARTE1, txp, rxp); let (mut uarte1_reader, mut uarte1_handler) = uarte1::setup(uarte1); let mut resp = ble::setup(nrf52.RADIO, nrf52.TIMER0, nrf52.FICR); HANDLERS.with_overrides(|hs| { hs.register(0, &mut rtc_handler); hs.register(1, &mut twis_handler); hs.register(2, &mut uarte1_handler); unsafe { NVIC::unmask(Interrupt::RTC0); NVIC::unmask(Interrupt::SPIM0_SPIS0_TWIM0_TWIS0_SPI0_TWI0); NVIC::unmask(Interrupt::UARTE1); NVIC::unmask(Interrupt::TIMER0); NVIC::unmask(Interrupt::RADIO); } info!("Bootstrap complete."); // Buffer is just scratch space that always gets written to // before it's read. let mut buf: [u8; 256] = unsafe { core::mem::MaybeUninit::<[u8; 256]>::uninit().assume_init() }; // TODO: there's some kind of weird multi-millisecond latency // somewhere. It may be in one of the interrupt handlers, so // maybe stick a counter on them for every time they're fired // and then spit out stats once/second from here. // // May need to keep total-time-spent inside the handlers as // well. This lag is infuriatingly hidden. loop { let mut len = twis_reader.shift_into(&mut buf); while len > 0 { info!("i²c data: {:?}", &buf[0..len]); len = twis_reader.shift_into(&mut buf); } let mut len = uarte1_reader.shift_into(&mut buf); while len > 0 { log!(target: "usb", LogLevel::Info, "{}", core::str::from_utf8(&buf[0..len]).expect("utf8conv") ); len = uarte1_reader.shift_into(&mut buf); } if resp.has_work() { trace!("ble responder has work"); resp.process_one().expect("ble response processing"); } wfi(); } }); unreachable!(); } fn uarte1(uarte: U, tx: Pin>, rx: Pin>) -> Uarte where U: uarte::Instance, { Uarte::new( uarte, uarte::Pins { txd: tx, rxd: rx, cts: None, rts: None, }, UartParity::EXCLUDED, UartBaudrate::BAUD115200, ) } #[exception] fn HardFault(ef: &ExceptionFrame) -> ! { log::logger().flush(); logln_now!("!!! Hard Fault - ef: {:?} !!!", ef); logln_now!("flushing log"); loop { log::logger().flush(); wfi() } } #[interrupt] fn RTC0() { HANDLERS.call(0); } #[interrupt] fn SPIM0_SPIS0_TWIM0_TWIS0_SPI0_TWI0() { HANDLERS.call(1); } #[interrupt] fn UARTE1() { HANDLERS.call(2); }