// #![deny(unsafe_code)] #![no_std] #![no_main] // mod i2c_reg_slave; // mod i2c_slave; mod dmx; // extern crate panic_halt; extern crate panic_semihosting; #[rtic::app(device = stm32f1xx_hal::pac, dispatchers = [SPI1, SPI2, SPI3])] mod app { use crate::dmx::DMX; use cortex_m::singleton; use stm32f1xx_hal::{gpio, pac, prelude::*, serial, timer}; use systick_monotonic::Systick; const DMX_LEN: usize = 512; // A monotonic timer to enable scheduling in RTIC #[monotonic(binds = SysTick, default = true)] type MyMono = Systick<100>; // 100 Hz / 10 ms granularity #[shared] struct Shared { buffer: &'static mut [u8], delay_us: timer::DelayUs, } #[local] struct Local { dmx: DMX, led: gpio::gpioc::PC13>, int_led: gpio::gpiob::PB0>, } #[init] fn init(mut cx: init::Context) -> (Shared, Local, init::Monotonics) { // Take ownership over the raw flash and rcc devices and convert them into the corresponding // HAL structs let mut flash = cx.device.FLASH.constrain(); let rcc = cx.device.RCC.constrain(); // Freeze the configuration of all the clocks in the system and store the frozen frequencies in // `clocks` let clocks = rcc .cfgr // hf external quartz frequency .use_hse(8.MHz()) // system clock frequency .sysclk(72.MHz()) .freeze(&mut flash.acr); // Initialize the monotonic let mono = Systick::new(cx.core.SYST, clocks.sysclk().to_Hz()); // Acquire the peripherals let mut gpioa = cx.device.GPIOA.split(); let mut gpiob = cx.device.GPIOB.split(); let mut gpioc = cx.device.GPIOC.split(); let mut afio = cx.device.AFIO.constrain(); let dma1 = cx.device.DMA1.split(); let _ = gpiob.pb10.into_pull_up_input(&mut gpiob.crh); // enable EXTI10 for port B afio.exticr3 .exticr3() .write(|w| unsafe { w.exti10().bits(0b0001) }); // mask EXTI10 cx.device.EXTI.imr.write(|w| w.mr10().set_bit()); // EXTI10 on falling edge cx.device.EXTI.ftsr.write(|w| w.tr10().set_bit()); // set EXTI10 priority unsafe { // pac::NVIC::unmask(pac::Interrupt::EXTI15_10); cx.core.NVIC.set_priority(pac::Interrupt::EXTI15_10, 1); } // Serial config let serial = serial::Serial::new( cx.device.USART1, ( gpioa.pa9.into_alternate_open_drain(&mut gpioa.crh), gpioa.pa10, //.into_pull_up_input(&mut gpioa.crh), ), &mut afio.mapr, serial::Config::default(), &clocks, ); // rtic::pend(pac::Interrupt::DMA1_CHANNEL4); // ??? // let nvic = cx.device.NVIC_STIR; foo::spawn().unwrap(); ( Shared { buffer: singleton!(: [u8; DMX_LEN] = [0b01010101; DMX_LEN]).unwrap(), // Configure timer delay_us: cx.device.TIM2.delay_us(&clocks), }, Local { dmx: DMX::new(serial, dma1.4, &clocks), // Configure gpio C pin 13 as a push-pull output. The `crh` register is passed to the function // in order to configure the port. For pins 0-7, crl should be passed instead. led: gpioc .pc13 .into_push_pull_output_with_state(&mut gpioc.crh, gpio::PinState::High), int_led: gpiob .pb0 .into_open_drain_output_with_state(&mut gpiob.crl, gpio::PinState::Low), }, init::Monotonics(mono), ) } #[idle] fn idle(_: idle::Context) -> ! { loop { rtic::export::wfi(); } } #[task(local = [dmx, led], shared = [&buffer, delay_us])] fn foo(mut cx: foo::Context) { cx.local.dmx.send(cx.shared.buffer); cx.local.led.toggle(); cx.shared.delay_us.lock(|d| d.delay(1.secs())); // cx.local.dmx.wait(); foo::spawn().unwrap(); } #[task(binds=EXTI15_10, local = [int_led], shared = [delay_us])] fn bar(mut cx: bar::Context) { let dp = unsafe { pac::Peripherals::steal() }; // EXTI10 must be pending if dp.EXTI.pr.read().pr10().bit() { cx.local.int_led.toggle(); cx.shared.delay_us.lock(|d| d.delay(100.millis())); // clear EXTI10 pending status dp.EXTI.pr.write(|w| w.pr10().set_bit()); } } }