From d7f46c1f12bf6bd50c4053ea73b0fa055d6cc9d6 Mon Sep 17 00:00:00 2001 From: Chris Ballance Date: Wed, 13 Nov 2019 20:33:14 +0000 Subject: [PATCH] factor CPU and board-specific initialisation out of main (NFC) --- src/board.rs | 532 ++++++++++++++++++++++++++++++++++++++++++++++++++ src/main.rs | 533 +-------------------------------------------------- 2 files changed, 537 insertions(+), 528 deletions(-) create mode 100644 src/board.rs diff --git a/src/board.rs b/src/board.rs new file mode 100644 index 0000000..f391f99 --- /dev/null +++ b/src/board.rs @@ -0,0 +1,532 @@ +use super::pac; +use super::i2c; +use super::eth; + +fn pwr_setup(pwr: &pac::PWR) { + // go to VOS1 voltage scale for high perf + pwr.cr3.write(|w| + w.scuen().set_bit() + .ldoen().set_bit() + .bypass().clear_bit() + ); + while pwr.csr1.read().actvosrdy().bit_is_clear() {} + pwr.d3cr.write(|w| unsafe { w.vos().bits(0b11) }); // vos1 + while pwr.d3cr.read().vosrdy().bit_is_clear() {} +} + +fn rcc_reset(rcc: &pac::RCC) { + // Reset all peripherals + rcc.ahb1rstr.write(|w| unsafe { w.bits(0xFFFF_FFFF) }); + rcc.ahb1rstr.write(|w| unsafe { w.bits(0)}); + rcc.apb1lrstr.write(|w| unsafe { w.bits(0xFFFF_FFFF) }); + rcc.apb1lrstr.write(|w| unsafe { w.bits(0)}); + rcc.apb1hrstr.write(|w| unsafe { w.bits(0xFFFF_FFFF) }); + rcc.apb1hrstr.write(|w| unsafe { w.bits(0)}); + + rcc.ahb2rstr.write(|w| unsafe { w.bits(0xFFFF_FFFF) }); + rcc.ahb2rstr.write(|w| unsafe { w.bits(0)}); + rcc.apb2rstr.write(|w| unsafe { w.bits(0xFFFF_FFFF) }); + rcc.apb2rstr.write(|w| unsafe { w.bits(0)}); + + // do not reset the cpu + rcc.ahb3rstr.write(|w| unsafe { w.bits(0x7FFF_FFFF) }); + rcc.ahb3rstr.write(|w| unsafe { w.bits(0)}); + rcc.apb3rstr.write(|w| unsafe { w.bits(0xFFFF_FFFF) }); + rcc.apb3rstr.write(|w| unsafe { w.bits(0)}); + + rcc.ahb4rstr.write(|w| unsafe { w.bits(0xFFFF_FFFF) }); + rcc.ahb4rstr.write(|w| unsafe { w.bits(0)}); + rcc.apb4rstr.write(|w| unsafe { w.bits(0xFFFF_FFFF) }); + rcc.apb4rstr.write(|w| unsafe { w.bits(0)}); +} + +fn rcc_pll_setup(rcc: &pac::RCC, flash: &pac::FLASH) { + // Switch to HSI to mess with HSE + rcc.cr.modify(|_, w| w.hsion().on()); + while rcc.cr.read().hsirdy().is_not_ready() {} + rcc.cfgr.modify(|_, w| w.sw().hsi()); + while !rcc.cfgr.read().sws().is_hsi() {} + rcc.cr.write(|w| w.hsion().on()); + rcc.cfgr.reset(); + + // Ensure HSE is on and stable + rcc.cr.modify(|_, w| + w.hseon().on() + .hsebyp().not_bypassed()); + while !rcc.cr.read().hserdy().is_ready() {} + + rcc.pllckselr.modify(|_, w| + w.pllsrc().hse() + .divm1().bits(1) // ref prescaler + .divm2().bits(1) // ref prescaler + ); + // Configure PLL1: 8MHz /1 *100 /2 = 400 MHz + rcc.pllcfgr.modify(|_, w| + w.pll1vcosel().wide_vco() // 192-836 MHz VCO + .pll1rge().range8() // 8-16 MHz PFD + .pll1fracen().reset() + .divp1en().enabled() + .pll2vcosel().medium_vco() // 150-420 MHz VCO + .pll2rge().range8() // 8-16 MHz PFD + .pll2fracen().reset() + .divp2en().enabled() + .divq2en().enabled() + ); + rcc.pll1divr.write(|w| unsafe { + w.divn1().bits(100 - 1) // feebdack divider + .divp1().div2() // p output divider + }); + rcc.cr.modify(|_, w| w.pll1on().on()); + while !rcc.cr.read().pll1rdy().is_ready() {} + + // Configure PLL2: 8MHz /1 *25 / 2 = 100 MHz + rcc.pll2divr.write(|w| unsafe { + w.divn2().bits(25 - 1) // feebdack divider + .divp2().bits(2 - 1) // p output divider + .divq2().bits(2 - 1) // q output divider + }); + rcc.cr.modify(|_, w| w.pll2on().on()); + while !rcc.cr.read().pll2rdy().is_ready() {} + + // hclk 200 MHz, pclk 100 MHz + rcc.d1cfgr.write(|w| + w.d1cpre().div1() // sys_ck not divided + .hpre().div2() // rcc_hclk3 = sys_d1cpre_ck / 2 + .d1ppre().div2() // rcc_pclk3 = rcc_hclk3 / 2 + ); + rcc.d2cfgr.write(|w| + w.d2ppre1().div2() // rcc_pclk1 = rcc_hclk3 / 2 + .d2ppre2().div2() // rcc_pclk2 = rcc_hclk3 / 2 + ); + rcc.d3cfgr.write(|w| + w.d3ppre().div2() // rcc_pclk4 = rcc_hclk3 / 2 + ); + + // 2 wait states, 0b10 programming delay + // 185-210 MHz + flash.acr.write(|w| unsafe { + w.wrhighfreq().bits(2) + .latency().bits(2) + }); + while flash.acr.read().latency().bits() != 2 {} + + // CSI for I/O compensationc ell + rcc.cr.modify(|_, w| w.csion().on()); + while !rcc.cr.read().csirdy().is_ready() {} + + // Set system clock to pll1_p + rcc.cfgr.modify(|_, w| w.sw().pll1()); + while !rcc.cfgr.read().sws().is_pll1() {} + + rcc.d1ccipr.write(|w| w.ckpersel().hse()); + rcc.d2ccip1r.modify(|_, w| + w.spi123sel().pll2_p() + .spi45sel().pll2_q() + ); + rcc.d3ccipr.modify(|_, w| w.spi6sel().pll2_q()); +} + +fn io_compensation_setup(syscfg: &pac::SYSCFG) { + syscfg.cccsr.modify(|_, w| + w.en().set_bit() + .cs().clear_bit() + .hslv().clear_bit() + ); + while syscfg.cccsr.read().ready().bit_is_clear() {} +} + +fn gpio_setup(gpioa: &pac::GPIOA, gpiob: &pac::GPIOB, gpiod: &pac::GPIOD, + gpioe: &pac::GPIOE, gpiof: &pac::GPIOF, gpiog: &pac::GPIOG) { + // FP_LED0 + gpiod.otyper.modify(|_, w| w.ot5().push_pull()); + gpiod.moder.modify(|_, w| w.moder5().output()); + gpiod.odr.modify(|_, w| w.odr5().low()); + + // FP_LED1 + gpiod.otyper.modify(|_, w| w.ot6().push_pull()); + gpiod.moder.modify(|_, w| w.moder6().output()); + gpiod.odr.modify(|_, w| w.odr6().low()); + + // LED_FP2 + gpiog.otyper.modify(|_, w| w.ot4().push_pull()); + gpiog.moder.modify(|_, w| w.moder4().output()); + gpiog.odr.modify(|_, w| w.odr4().low()); + + // LED_FP3 + gpiod.otyper.modify(|_, w| w.ot12().push_pull()); + gpiod.moder.modify(|_, w| w.moder12().output()); + gpiod.odr.modify(|_, w| w.odr12().low()); + + // AFE0_A0,1: PG2,PG3 + gpiog.otyper.modify(|_, w| + w.ot2().push_pull() + .ot3().push_pull() + ); + gpiog.moder.modify(|_, w| + w.moder2().output() + .moder3().output() + ); + gpiog.odr.modify(|_, w| + w.odr2().low() + .odr3().low() + ); + + // ADC0 + // SCK: PG11 + gpiog.moder.modify(|_, w| w.moder11().alternate()); + gpiog.otyper.modify(|_, w| w.ot11().push_pull()); + gpiog.ospeedr.modify(|_, w| w.ospeedr11().very_high_speed()); + gpiog.afrh.modify(|_, w| w.afr11().af5()); + // MOSI: PD7 + // MISO: PA6 + gpioa.moder.modify(|_, w| w.moder6().alternate()); + gpioa.afrl.modify(|_, w| w.afr6().af5()); + // NSS: PG10 + gpiog.moder.modify(|_, w| w.moder10().alternate()); + gpiog.otyper.modify(|_, w| w.ot10().push_pull()); + gpiog.ospeedr.modify(|_, w| w.ospeedr10().very_high_speed()); + gpiog.afrh.modify(|_, w| w.afr10().af5()); + + // DAC0 + // SCK: PB10 + gpiob.moder.modify(|_, w| w.moder10().alternate()); + gpiob.otyper.modify(|_, w| w.ot10().push_pull()); + gpiob.ospeedr.modify(|_, w| w.ospeedr10().very_high_speed()); + gpiob.afrh.modify(|_, w| w.afr10().af5()); + // MOSI: PB15 + gpiob.moder.modify(|_, w| w.moder15().alternate()); + gpiob.otyper.modify(|_, w| w.ot15().push_pull()); + gpiob.ospeedr.modify(|_, w| w.ospeedr15().very_high_speed()); + gpiob.afrh.modify(|_, w| w.afr15().af5()); + // MISO: PB14 + // NSS: PB9 + gpiob.moder.modify(|_, w| w.moder9().alternate()); + gpiob.otyper.modify(|_, w| w.ot9().push_pull()); + gpiob.ospeedr.modify(|_, w| w.ospeedr9().very_high_speed()); + gpiob.afrh.modify(|_, w| w.afr9().af5()); + + // DAC0_LDAC: PE11 + gpioe.moder.modify(|_, w| w.moder11().output()); + gpioe.otyper.modify(|_, w| w.ot11().push_pull()); + gpioe.odr.modify(|_, w| w.odr11().low()); + + // DAC_CLR: PE12 + gpioe.moder.modify(|_, w| w.moder12().output()); + gpioe.otyper.modify(|_, w| w.ot12().push_pull()); + gpioe.odr.modify(|_, w| w.odr12().high()); + + // AFE1_A0,1: PD14,PD15 + gpiod.otyper.modify(|_, w| + w.ot14().push_pull() + .ot15().push_pull() + ); + gpiod.moder.modify(|_, w| + w.moder14().output() + .moder15().output() + ); + gpiod.odr.modify(|_, w| + w.odr14().low() + .odr15().low() + ); + + // I2C2: SDA,SCL: PF0,PF1 + gpiof.moder.modify(|_, w| + w.moder0().alternate() + .moder1().alternate() + ); + gpiof.afrl.modify(|_, w| + w.afr0().af4() + .afr1().af4() + ); + gpiof.otyper.modify(|_, w| + w.ot0().open_drain() + .ot1().open_drain() + ); + + // ADC1 + // SCK: PF6 + gpiof.moder.modify(|_, w| w.moder7().alternate()); + gpiof.otyper.modify(|_, w| w.ot7().push_pull()); + gpiof.ospeedr.modify(|_, w| w.ospeedr7().very_high_speed()); + gpiof.afrl.modify(|_, w| w.afr7().af5()); + // MOSI: PF9 + // MISO: PF7 + gpiof.moder.modify(|_, w| w.moder8().alternate()); + gpiof.afrh.modify(|_, w| w.afr8().af5()); + // NSS: PF8 + gpiof.moder.modify(|_, w| w.moder6().alternate()); + gpiof.otyper.modify(|_, w| w.ot6().push_pull()); + gpiof.ospeedr.modify(|_, w| w.ospeedr6().very_high_speed()); + gpiof.afrl.modify(|_, w| w.afr6().af5()); + + // DAC1 + // SCK: PE2 + gpioe.moder.modify(|_, w| w.moder2().alternate()); + gpioe.otyper.modify(|_, w| w.ot2().push_pull()); + gpioe.ospeedr.modify(|_, w| w.ospeedr2().very_high_speed()); + gpioe.afrl.modify(|_, w| w.afr2().af5()); + // MOSI: PE6 + gpioe.moder.modify(|_, w| w.moder6().alternate()); + gpioe.otyper.modify(|_, w| w.ot6().push_pull()); + gpioe.ospeedr.modify(|_, w| w.ospeedr6().very_high_speed()); + gpioe.afrl.modify(|_, w| w.afr6().af5()); + // MISO: PE5 + // NSS: PE4 + gpioe.moder.modify(|_, w| w.moder4().alternate()); + gpioe.otyper.modify(|_, w| w.ot4().push_pull()); + gpioe.ospeedr.modify(|_, w| w.ospeedr4().very_high_speed()); + gpioe.afrl.modify(|_, w| w.afr4().af5()); + + // DAC1_LDAC: PE15 + gpioe.moder.modify(|_, w| w.moder15().output()); + gpioe.otyper.modify(|_, w| w.ot15().push_pull()); + gpioe.odr.modify(|_, w| w.odr15().low()); +} + +// ADC0 +fn spi1_setup(spi1: &pac::SPI1) { + spi1.cfg1.modify(|_, w| + w.mbr().div4() + .dsize().bits(16 - 1) + .fthlv().one_frame() + ); + spi1.cfg2.modify(|_, w| + w.afcntr().controlled() + .ssom().not_asserted() + .ssoe().enabled() + .ssiop().active_low() + .ssm().disabled() + .cpol().idle_high() + .cpha().second_edge() + .lsbfrst().msbfirst() + .master().master() + .sp().motorola() + .comm().receiver() + .ioswp().disabled() + .midi().bits(0) + .mssi().bits(6) + ); + spi1.cr2.modify(|_, w| w.tsize().bits(1)); + spi1.cr1.write(|w| w.spe().enabled()); +} + +// ADC1 +fn spi5_setup(spi5: &pac::SPI5) { + spi5.cfg1.modify(|_, w| + w.mbr().div4() + .dsize().bits(16 - 1) + .fthlv().one_frame() + ); + spi5.cfg2.modify(|_, w| + w.afcntr().controlled() + .ssom().not_asserted() + .ssoe().enabled() + .ssiop().active_low() + .ssm().disabled() + .cpol().idle_high() + .cpha().second_edge() + .lsbfrst().msbfirst() + .master().master() + .sp().motorola() + .comm().receiver() + .ioswp().disabled() + .midi().bits(0) + .mssi().bits(6) + ); + spi5.cr2.modify(|_, w| w.tsize().bits(1)); + spi5.cr1.write(|w| w.spe().enabled()); +} + +// DAC0 +fn spi2_setup(spi2: &pac::SPI2) { + spi2.cfg1.modify(|_, w| + w.mbr().div2() + .dsize().bits(16 - 1) + .fthlv().one_frame() + ); + spi2.cfg2.modify(|_, w| + w.afcntr().controlled() + .ssom().not_asserted() + .ssoe().enabled() + .ssiop().active_low() + .ssm().disabled() + .cpol().idle_low() + .cpha().first_edge() + .lsbfrst().msbfirst() + .master().master() + .sp().motorola() + .comm().transmitter() + .ioswp().disabled() + .midi().bits(0) + .mssi().bits(0) + ); + spi2.cr2.modify(|_, w| w.tsize().bits(0)); + spi2.cr1.write(|w| w.spe().enabled()); + spi2.cr1.modify(|_, w| w.cstart().started()); +} + +// DAC1 +fn spi4_setup(spi4: &pac::SPI4) { + spi4.cfg1.modify(|_, w| + w.mbr().div2() + .dsize().bits(16 - 1) + .fthlv().one_frame() + ); + spi4.cfg2.modify(|_, w| + w.afcntr().controlled() + .ssom().not_asserted() + .ssoe().enabled() + .ssiop().active_low() + .ssm().disabled() + .cpol().idle_low() + .cpha().first_edge() + .lsbfrst().msbfirst() + .master().master() + .sp().motorola() + .comm().transmitter() + .ioswp().disabled() + .midi().bits(0) + .mssi().bits(0) + ); + spi4.cr2.modify(|_, w| w.tsize().bits(0)); + spi4.cr1.write(|w| w.spe().enabled()); + spi4.cr1.modify(|_, w| w.cstart().started()); +} + +fn tim2_setup(tim2: &pac::TIM2) { + tim2.psc.write(|w| w.psc().bits(200 - 1)); // from 200 MHz + tim2.arr.write(|w| unsafe { w.bits(2 - 1) }); // µs + tim2.dier.write(|w| w.ude().set_bit()); + tim2.egr.write(|w| w.ug().set_bit()); + tim2.cr1.modify(|_, w| + w.dir().clear_bit() // up + .cen().set_bit()); // enable +} + +fn dma1_setup(dma1: &pac::DMA1, dmamux1: &pac::DMAMUX1, ma: usize, pa0: usize, pa1: usize) { + dma1.st[0].cr.modify(|_, w| w.en().clear_bit()); + while dma1.st[0].cr.read().en().bit_is_set() {} + + dma1.st[0].par.write(|w| unsafe { w.bits(pa0 as u32) }); + dma1.st[0].m0ar.write(|w| unsafe { w.bits(ma as u32) }); + dma1.st[0].ndtr.write(|w| unsafe { w.ndt().bits(1) }); + dmamux1.ccr[0].modify(|_, w| w.dmareq_id().tim2_up()); + dma1.st[0].cr.modify(|_, w| unsafe { + w.pl().bits(0b01) // medium + .circ().set_bit() // reload ndtr + .msize().bits(0b10) // 32 + .minc().clear_bit() + .mburst().bits(0b00) + .psize().bits(0b10) // 32 + .pinc().clear_bit() + .pburst().bits(0b00) + .dbm().clear_bit() + .dir().bits(0b01) // memory_to_peripheral + .pfctrl().clear_bit() // dma is FC + }); + dma1.st[0].fcr.modify(|_, w| w.dmdis().clear_bit()); + dma1.st[0].cr.modify(|_, w| w.en().set_bit()); + + dma1.st[1].cr.modify(|_, w| w.en().clear_bit()); + while dma1.st[1].cr.read().en().bit_is_set() {} + + dma1.st[1].par.write(|w| unsafe { w.bits(pa1 as u32) }); + dma1.st[1].m0ar.write(|w| unsafe { w.bits(ma as u32) }); + dma1.st[1].ndtr.write(|w| unsafe { w.ndt().bits(1) }); + dmamux1.ccr[1].modify(|_, w| w.dmareq_id().tim2_up()); + dma1.st[1].cr.modify(|_, w| unsafe { + w.pl().bits(0b01) // medium + .circ().set_bit() // reload ndtr + .msize().bits(0b10) // 32 + .minc().clear_bit() + .mburst().bits(0b00) + .psize().bits(0b10) // 32 + .pinc().clear_bit() + .pburst().bits(0b00) + .dbm().clear_bit() + .dir().bits(0b01) // memory_to_peripheral + .pfctrl().clear_bit() // dma is FC + }); + dma1.st[1].fcr.modify(|_, w| w.dmdis().clear_bit()); + dma1.st[1].cr.modify(|_, w| w.en().set_bit()); +} + +#[link_section = ".sram1.datspi"] +static mut DAT: u32 = 0x201; // EN | CSTART + +pub fn init() { + let mut cp = unsafe{ cortex_m::Peripherals::steal() }; + let dp = unsafe{ pac::Peripherals::steal()}; + + let rcc = dp.RCC; + rcc_reset(&rcc); + pwr_setup(&dp.PWR); + rcc_pll_setup(&rcc, &dp.FLASH); + rcc.apb4enr.modify(|_, w| w.syscfgen().set_bit()); + io_compensation_setup(&dp.SYSCFG); + + cp.SCB.enable_icache(); + // TODO: ETH DMA coherence issues + // cp.SCB.enable_dcache(&mut cp.CPUID); + cp.DWT.enable_cycle_counter(); // japaric/cortex-m-rtfm#184 + + rcc.ahb4enr.modify(|_, w| + w.gpioaen().set_bit() + .gpioben().set_bit() + .gpiocen().set_bit() + .gpioden().set_bit() + .gpioeen().set_bit() + .gpiofen().set_bit() + .gpiogen().set_bit() + ); + gpio_setup(&dp.GPIOA, &dp.GPIOB, &dp.GPIOD, &dp.GPIOE, &dp.GPIOF, &dp.GPIOG); + + rcc.apb1lenr.modify(|_, w| w.spi2en().set_bit()); + let spi2 = dp.SPI2; + spi2_setup(&spi2); + + rcc.apb2enr.modify(|_, w| w.spi4en().set_bit()); + let spi4 = dp.SPI4; + spi4_setup(&spi4); + + rcc.apb2enr.modify(|_, w| w.spi1en().set_bit()); + let spi1 = dp.SPI1; + spi1_setup(&spi1); + spi1.ier.write(|w| w.eotie().set_bit()); + + rcc.apb2enr.modify(|_, w| w.spi5en().set_bit()); + let spi5 = dp.SPI5; + spi5_setup(&spi5); + // spi5.ier.write(|w| w.eotie().set_bit()); + + rcc.ahb2enr.modify(|_, w| + w + .sram1en().set_bit() + .sram2en().set_bit() + .sram3en().set_bit() + ); + rcc.ahb1enr.modify(|_, w| w.dma1en().set_bit()); + // init SRAM1 rodata can't load with sram1 disabled + unsafe { DAT = 0x201 }; // EN | CSTART + cortex_m::asm::dsb(); + let dat_addr = unsafe { &DAT as *const _ } as usize; + cp.SCB.clean_dcache_by_address(dat_addr, 4); + + dma1_setup(&dp.DMA1, &dp.DMAMUX1, dat_addr, + &spi1.cr1 as *const _ as usize, + &spi5.cr1 as *const _ as usize); + + rcc.apb1lenr.modify(|_, w| w.tim2en().set_bit()); + + // work around the SPI stall erratum + let dbgmcu = dp.DBGMCU; + dbgmcu.apb1lfz1.modify(|_, w| w.tim2().set_bit()); + + tim2_setup(&dp.TIM2); + + let i2c2 = dp.I2C2; + i2c::setup(&rcc, &i2c2); + + eth::setup(&rcc, &dp.SYSCFG); + eth::setup_pins(&dp.GPIOA, &dp.GPIOB, &dp.GPIOC, &dp.GPIOG); +} diff --git a/src/main.rs b/src/main.rs index 4c48a44..a9c02e5 100644 --- a/src/main.rs +++ b/src/main.rs @@ -45,6 +45,7 @@ use iir::*; mod i2c; mod eeprom; +mod board; #[cfg(not(feature = "semihosting"))] fn init_log() {} @@ -72,460 +73,9 @@ mod build_info { // include!(concat!(env!("OUT_DIR"), "/built.rs")); } -fn pwr_setup(pwr: &pac::PWR) { - // go to VOS1 voltage scale for high perf - pwr.cr3.write(|w| - w.scuen().set_bit() - .ldoen().set_bit() - .bypass().clear_bit() - ); - while pwr.csr1.read().actvosrdy().bit_is_clear() {} - pwr.d3cr.write(|w| unsafe { w.vos().bits(0b11) }); // vos1 - while pwr.d3cr.read().vosrdy().bit_is_clear() {} -} - -fn rcc_reset(rcc: &pac::RCC) { - // Reset all peripherals - rcc.ahb1rstr.write(|w| unsafe { w.bits(0xFFFF_FFFF) }); - rcc.ahb1rstr.write(|w| unsafe { w.bits(0)}); - rcc.apb1lrstr.write(|w| unsafe { w.bits(0xFFFF_FFFF) }); - rcc.apb1lrstr.write(|w| unsafe { w.bits(0)}); - rcc.apb1hrstr.write(|w| unsafe { w.bits(0xFFFF_FFFF) }); - rcc.apb1hrstr.write(|w| unsafe { w.bits(0)}); - - rcc.ahb2rstr.write(|w| unsafe { w.bits(0xFFFF_FFFF) }); - rcc.ahb2rstr.write(|w| unsafe { w.bits(0)}); - rcc.apb2rstr.write(|w| unsafe { w.bits(0xFFFF_FFFF) }); - rcc.apb2rstr.write(|w| unsafe { w.bits(0)}); - - // do not reset the cpu - rcc.ahb3rstr.write(|w| unsafe { w.bits(0x7FFF_FFFF) }); - rcc.ahb3rstr.write(|w| unsafe { w.bits(0)}); - rcc.apb3rstr.write(|w| unsafe { w.bits(0xFFFF_FFFF) }); - rcc.apb3rstr.write(|w| unsafe { w.bits(0)}); - - rcc.ahb4rstr.write(|w| unsafe { w.bits(0xFFFF_FFFF) }); - rcc.ahb4rstr.write(|w| unsafe { w.bits(0)}); - rcc.apb4rstr.write(|w| unsafe { w.bits(0xFFFF_FFFF) }); - rcc.apb4rstr.write(|w| unsafe { w.bits(0)}); -} - -fn rcc_pll_setup(rcc: &pac::RCC, flash: &pac::FLASH) { - // Switch to HSI to mess with HSE - rcc.cr.modify(|_, w| w.hsion().on()); - while rcc.cr.read().hsirdy().is_not_ready() {} - rcc.cfgr.modify(|_, w| w.sw().hsi()); - while !rcc.cfgr.read().sws().is_hsi() {} - rcc.cr.write(|w| w.hsion().on()); - rcc.cfgr.reset(); - - // Ensure HSE is on and stable - rcc.cr.modify(|_, w| - w.hseon().on() - .hsebyp().not_bypassed()); - while !rcc.cr.read().hserdy().is_ready() {} - - rcc.pllckselr.modify(|_, w| - w.pllsrc().hse() - .divm1().bits(1) // ref prescaler - .divm2().bits(1) // ref prescaler - ); - // Configure PLL1: 8MHz /1 *100 /2 = 400 MHz - rcc.pllcfgr.modify(|_, w| - w.pll1vcosel().wide_vco() // 192-836 MHz VCO - .pll1rge().range8() // 8-16 MHz PFD - .pll1fracen().reset() - .divp1en().enabled() - .pll2vcosel().medium_vco() // 150-420 MHz VCO - .pll2rge().range8() // 8-16 MHz PFD - .pll2fracen().reset() - .divp2en().enabled() - .divq2en().enabled() - ); - rcc.pll1divr.write(|w| unsafe { - w.divn1().bits(100 - 1) // feebdack divider - .divp1().div2() // p output divider - }); - rcc.cr.modify(|_, w| w.pll1on().on()); - while !rcc.cr.read().pll1rdy().is_ready() {} - - // Configure PLL2: 8MHz /1 *25 / 2 = 100 MHz - rcc.pll2divr.write(|w| unsafe { - w.divn2().bits(25 - 1) // feebdack divider - .divp2().bits(2 - 1) // p output divider - .divq2().bits(2 - 1) // q output divider - }); - rcc.cr.modify(|_, w| w.pll2on().on()); - while !rcc.cr.read().pll2rdy().is_ready() {} - - // hclk 200 MHz, pclk 100 MHz - rcc.d1cfgr.write(|w| - w.d1cpre().div1() // sys_ck not divided - .hpre().div2() // rcc_hclk3 = sys_d1cpre_ck / 2 - .d1ppre().div2() // rcc_pclk3 = rcc_hclk3 / 2 - ); - rcc.d2cfgr.write(|w| - w.d2ppre1().div2() // rcc_pclk1 = rcc_hclk3 / 2 - .d2ppre2().div2() // rcc_pclk2 = rcc_hclk3 / 2 - ); - rcc.d3cfgr.write(|w| - w.d3ppre().div2() // rcc_pclk4 = rcc_hclk3 / 2 - ); - - // 2 wait states, 0b10 programming delay - // 185-210 MHz - flash.acr.write(|w| unsafe { - w.wrhighfreq().bits(2) - .latency().bits(2) - }); - while flash.acr.read().latency().bits() != 2 {} - - // CSI for I/O compensationc ell - rcc.cr.modify(|_, w| w.csion().on()); - while !rcc.cr.read().csirdy().is_ready() {} - - // Set system clock to pll1_p - rcc.cfgr.modify(|_, w| w.sw().pll1()); - while !rcc.cfgr.read().sws().is_pll1() {} - - rcc.d1ccipr.write(|w| w.ckpersel().hse()); - rcc.d2ccip1r.modify(|_, w| - w.spi123sel().pll2_p() - .spi45sel().pll2_q() - ); - rcc.d3ccipr.modify(|_, w| w.spi6sel().pll2_q()); -} - -fn io_compensation_setup(syscfg: &pac::SYSCFG) { - syscfg.cccsr.modify(|_, w| - w.en().set_bit() - .cs().clear_bit() - .hslv().clear_bit() - ); - while syscfg.cccsr.read().ready().bit_is_clear() {} -} - -fn gpio_setup(gpioa: &pac::GPIOA, gpiob: &pac::GPIOB, gpiod: &pac::GPIOD, - gpioe: &pac::GPIOE, gpiof: &pac::GPIOF, gpiog: &pac::GPIOG) { - // FP_LED0 - gpiod.otyper.modify(|_, w| w.ot5().push_pull()); - gpiod.moder.modify(|_, w| w.moder5().output()); - gpiod.odr.modify(|_, w| w.odr5().low()); - - // FP_LED1 - gpiod.otyper.modify(|_, w| w.ot6().push_pull()); - gpiod.moder.modify(|_, w| w.moder6().output()); - gpiod.odr.modify(|_, w| w.odr6().low()); - - // LED_FP2 - gpiog.otyper.modify(|_, w| w.ot4().push_pull()); - gpiog.moder.modify(|_, w| w.moder4().output()); - gpiog.odr.modify(|_, w| w.odr4().low()); - - // LED_FP3 - gpiod.otyper.modify(|_, w| w.ot12().push_pull()); - gpiod.moder.modify(|_, w| w.moder12().output()); - gpiod.odr.modify(|_, w| w.odr12().low()); - - // AFE0_A0,1: PG2,PG3 - gpiog.otyper.modify(|_, w| - w.ot2().push_pull() - .ot3().push_pull() - ); - gpiog.moder.modify(|_, w| - w.moder2().output() - .moder3().output() - ); - gpiog.odr.modify(|_, w| - w.odr2().low() - .odr3().low() - ); - - // ADC0 - // SCK: PG11 - gpiog.moder.modify(|_, w| w.moder11().alternate()); - gpiog.otyper.modify(|_, w| w.ot11().push_pull()); - gpiog.ospeedr.modify(|_, w| w.ospeedr11().very_high_speed()); - gpiog.afrh.modify(|_, w| w.afr11().af5()); - // MOSI: PD7 - // MISO: PA6 - gpioa.moder.modify(|_, w| w.moder6().alternate()); - gpioa.afrl.modify(|_, w| w.afr6().af5()); - // NSS: PG10 - gpiog.moder.modify(|_, w| w.moder10().alternate()); - gpiog.otyper.modify(|_, w| w.ot10().push_pull()); - gpiog.ospeedr.modify(|_, w| w.ospeedr10().very_high_speed()); - gpiog.afrh.modify(|_, w| w.afr10().af5()); - - // DAC0 - // SCK: PB10 - gpiob.moder.modify(|_, w| w.moder10().alternate()); - gpiob.otyper.modify(|_, w| w.ot10().push_pull()); - gpiob.ospeedr.modify(|_, w| w.ospeedr10().very_high_speed()); - gpiob.afrh.modify(|_, w| w.afr10().af5()); - // MOSI: PB15 - gpiob.moder.modify(|_, w| w.moder15().alternate()); - gpiob.otyper.modify(|_, w| w.ot15().push_pull()); - gpiob.ospeedr.modify(|_, w| w.ospeedr15().very_high_speed()); - gpiob.afrh.modify(|_, w| w.afr15().af5()); - // MISO: PB14 - // NSS: PB9 - gpiob.moder.modify(|_, w| w.moder9().alternate()); - gpiob.otyper.modify(|_, w| w.ot9().push_pull()); - gpiob.ospeedr.modify(|_, w| w.ospeedr9().very_high_speed()); - gpiob.afrh.modify(|_, w| w.afr9().af5()); - - // DAC0_LDAC: PE11 - gpioe.moder.modify(|_, w| w.moder11().output()); - gpioe.otyper.modify(|_, w| w.ot11().push_pull()); - gpioe.odr.modify(|_, w| w.odr11().low()); - - // DAC_CLR: PE12 - gpioe.moder.modify(|_, w| w.moder12().output()); - gpioe.otyper.modify(|_, w| w.ot12().push_pull()); - gpioe.odr.modify(|_, w| w.odr12().high()); - - // AFE1_A0,1: PD14,PD15 - gpiod.otyper.modify(|_, w| - w.ot14().push_pull() - .ot15().push_pull() - ); - gpiod.moder.modify(|_, w| - w.moder14().output() - .moder15().output() - ); - gpiod.odr.modify(|_, w| - w.odr14().low() - .odr15().low() - ); - - // I2C2: SDA,SCL: PF0,PF1 - gpiof.moder.modify(|_, w| - w.moder0().alternate() - .moder1().alternate() - ); - gpiof.afrl.modify(|_, w| - w.afr0().af4() - .afr1().af4() - ); - gpiof.otyper.modify(|_, w| - w.ot0().open_drain() - .ot1().open_drain() - ); - - // ADC1 - // SCK: PF6 - gpiof.moder.modify(|_, w| w.moder7().alternate()); - gpiof.otyper.modify(|_, w| w.ot7().push_pull()); - gpiof.ospeedr.modify(|_, w| w.ospeedr7().very_high_speed()); - gpiof.afrl.modify(|_, w| w.afr7().af5()); - // MOSI: PF9 - // MISO: PF7 - gpiof.moder.modify(|_, w| w.moder8().alternate()); - gpiof.afrh.modify(|_, w| w.afr8().af5()); - // NSS: PF8 - gpiof.moder.modify(|_, w| w.moder6().alternate()); - gpiof.otyper.modify(|_, w| w.ot6().push_pull()); - gpiof.ospeedr.modify(|_, w| w.ospeedr6().very_high_speed()); - gpiof.afrl.modify(|_, w| w.afr6().af5()); - - // DAC1 - // SCK: PE2 - gpioe.moder.modify(|_, w| w.moder2().alternate()); - gpioe.otyper.modify(|_, w| w.ot2().push_pull()); - gpioe.ospeedr.modify(|_, w| w.ospeedr2().very_high_speed()); - gpioe.afrl.modify(|_, w| w.afr2().af5()); - // MOSI: PE6 - gpioe.moder.modify(|_, w| w.moder6().alternate()); - gpioe.otyper.modify(|_, w| w.ot6().push_pull()); - gpioe.ospeedr.modify(|_, w| w.ospeedr6().very_high_speed()); - gpioe.afrl.modify(|_, w| w.afr6().af5()); - // MISO: PE5 - // NSS: PE4 - gpioe.moder.modify(|_, w| w.moder4().alternate()); - gpioe.otyper.modify(|_, w| w.ot4().push_pull()); - gpioe.ospeedr.modify(|_, w| w.ospeedr4().very_high_speed()); - gpioe.afrl.modify(|_, w| w.afr4().af5()); - - // DAC1_LDAC: PE15 - gpioe.moder.modify(|_, w| w.moder15().output()); - gpioe.otyper.modify(|_, w| w.ot15().push_pull()); - gpioe.odr.modify(|_, w| w.odr15().low()); -} - -// ADC0 -fn spi1_setup(spi1: &pac::SPI1) { - spi1.cfg1.modify(|_, w| - w.mbr().div4() - .dsize().bits(16 - 1) - .fthlv().one_frame() - ); - spi1.cfg2.modify(|_, w| - w.afcntr().controlled() - .ssom().not_asserted() - .ssoe().enabled() - .ssiop().active_low() - .ssm().disabled() - .cpol().idle_high() - .cpha().second_edge() - .lsbfrst().msbfirst() - .master().master() - .sp().motorola() - .comm().receiver() - .ioswp().disabled() - .midi().bits(0) - .mssi().bits(6) - ); - spi1.cr2.modify(|_, w| w.tsize().bits(1)); - spi1.cr1.write(|w| w.spe().enabled()); -} - -// ADC1 -fn spi5_setup(spi5: &pac::SPI5) { - spi5.cfg1.modify(|_, w| - w.mbr().div4() - .dsize().bits(16 - 1) - .fthlv().one_frame() - ); - spi5.cfg2.modify(|_, w| - w.afcntr().controlled() - .ssom().not_asserted() - .ssoe().enabled() - .ssiop().active_low() - .ssm().disabled() - .cpol().idle_high() - .cpha().second_edge() - .lsbfrst().msbfirst() - .master().master() - .sp().motorola() - .comm().receiver() - .ioswp().disabled() - .midi().bits(0) - .mssi().bits(6) - ); - spi5.cr2.modify(|_, w| w.tsize().bits(1)); - spi5.cr1.write(|w| w.spe().enabled()); -} - -// DAC0 -fn spi2_setup(spi2: &pac::SPI2) { - spi2.cfg1.modify(|_, w| - w.mbr().div2() - .dsize().bits(16 - 1) - .fthlv().one_frame() - ); - spi2.cfg2.modify(|_, w| - w.afcntr().controlled() - .ssom().not_asserted() - .ssoe().enabled() - .ssiop().active_low() - .ssm().disabled() - .cpol().idle_low() - .cpha().first_edge() - .lsbfrst().msbfirst() - .master().master() - .sp().motorola() - .comm().transmitter() - .ioswp().disabled() - .midi().bits(0) - .mssi().bits(0) - ); - spi2.cr2.modify(|_, w| w.tsize().bits(0)); - spi2.cr1.write(|w| w.spe().enabled()); - spi2.cr1.modify(|_, w| w.cstart().started()); -} - -// DAC1 -fn spi4_setup(spi4: &pac::SPI4) { - spi4.cfg1.modify(|_, w| - w.mbr().div2() - .dsize().bits(16 - 1) - .fthlv().one_frame() - ); - spi4.cfg2.modify(|_, w| - w.afcntr().controlled() - .ssom().not_asserted() - .ssoe().enabled() - .ssiop().active_low() - .ssm().disabled() - .cpol().idle_low() - .cpha().first_edge() - .lsbfrst().msbfirst() - .master().master() - .sp().motorola() - .comm().transmitter() - .ioswp().disabled() - .midi().bits(0) - .mssi().bits(0) - ); - spi4.cr2.modify(|_, w| w.tsize().bits(0)); - spi4.cr1.write(|w| w.spe().enabled()); - spi4.cr1.modify(|_, w| w.cstart().started()); -} - -fn tim2_setup(tim2: &pac::TIM2) { - tim2.psc.write(|w| w.psc().bits(200 - 1)); // from 200 MHz - tim2.arr.write(|w| unsafe { w.bits(2 - 1) }); // µs - tim2.dier.write(|w| w.ude().set_bit()); - tim2.egr.write(|w| w.ug().set_bit()); - tim2.cr1.modify(|_, w| - w.dir().clear_bit() // up - .cen().set_bit()); // enable -} - -fn dma1_setup(dma1: &pac::DMA1, dmamux1: &pac::DMAMUX1, ma: usize, pa0: usize, pa1: usize) { - dma1.st[0].cr.modify(|_, w| w.en().clear_bit()); - while dma1.st[0].cr.read().en().bit_is_set() {} - - dma1.st[0].par.write(|w| unsafe { w.bits(pa0 as u32) }); - dma1.st[0].m0ar.write(|w| unsafe { w.bits(ma as u32) }); - dma1.st[0].ndtr.write(|w| unsafe { w.ndt().bits(1) }); - dmamux1.ccr[0].modify(|_, w| w.dmareq_id().tim2_up()); - dma1.st[0].cr.modify(|_, w| unsafe { - w.pl().bits(0b01) // medium - .circ().set_bit() // reload ndtr - .msize().bits(0b10) // 32 - .minc().clear_bit() - .mburst().bits(0b00) - .psize().bits(0b10) // 32 - .pinc().clear_bit() - .pburst().bits(0b00) - .dbm().clear_bit() - .dir().bits(0b01) // memory_to_peripheral - .pfctrl().clear_bit() // dma is FC - }); - dma1.st[0].fcr.modify(|_, w| w.dmdis().clear_bit()); - dma1.st[0].cr.modify(|_, w| w.en().set_bit()); - - dma1.st[1].cr.modify(|_, w| w.en().clear_bit()); - while dma1.st[1].cr.read().en().bit_is_set() {} - - dma1.st[1].par.write(|w| unsafe { w.bits(pa1 as u32) }); - dma1.st[1].m0ar.write(|w| unsafe { w.bits(ma as u32) }); - dma1.st[1].ndtr.write(|w| unsafe { w.ndt().bits(1) }); - dmamux1.ccr[1].modify(|_, w| w.dmareq_id().tim2_up()); - dma1.st[1].cr.modify(|_, w| unsafe { - w.pl().bits(0b01) // medium - .circ().set_bit() // reload ndtr - .msize().bits(0b10) // 32 - .minc().clear_bit() - .mburst().bits(0b00) - .psize().bits(0b10) // 32 - .pinc().clear_bit() - .pburst().bits(0b00) - .dbm().clear_bit() - .dir().bits(0b01) // memory_to_peripheral - .pfctrl().clear_bit() // dma is FC - }); - dma1.st[1].fcr.modify(|_, w| w.dmdis().clear_bit()); - dma1.st[1].cr.modify(|_, w| w.en().set_bit()); -} const SCALE: f32 = ((1 << 15) - 1) as f32; -#[link_section = ".sram1.datspi"] -static mut DAT: u32 = 0x201; // EN | CSTART - // static ETHERNET_PENDING: AtomicBool = AtomicBool::new(true); const TCP_RX_BUFFER_SIZE: usize = 8192; @@ -559,92 +109,19 @@ const APP: () = { #[init(schedule = [tick])] fn init(c: init::Context) -> init::LateResources { - let dp = c.device; - let mut cp = c.core; - - let rcc = dp.RCC; - rcc_reset(&rcc); + board::init(); init_log(); // info!("Version {} {}", build_info::PKG_VERSION, build_info::GIT_VERSION.unwrap()); // info!("Built on {}", build_info::BUILT_TIME_UTC); // info!("{} {}", build_info::RUSTC_VERSION, build_info::TARGET); - pwr_setup(&dp.PWR); - rcc_pll_setup(&rcc, &dp.FLASH); - rcc.apb4enr.modify(|_, w| w.syscfgen().set_bit()); - io_compensation_setup(&dp.SYSCFG); - - cp.SCB.enable_icache(); - // TODO: ETH DMA coherence issues - // cp.SCB.enable_dcache(&mut cp.CPUID); - cp.DWT.enable_cycle_counter(); // japaric/cortex-m-rtfm#184 - - rcc.ahb4enr.modify(|_, w| - w.gpioaen().set_bit() - .gpioben().set_bit() - .gpiocen().set_bit() - .gpioden().set_bit() - .gpioeen().set_bit() - .gpiofen().set_bit() - .gpiogen().set_bit() - ); - gpio_setup(&dp.GPIOA, &dp.GPIOB, &dp.GPIOD, &dp.GPIOE, &dp.GPIOF, &dp.GPIOG); - - rcc.apb1lenr.modify(|_, w| w.spi2en().set_bit()); - let spi2 = dp.SPI2; - spi2_setup(&spi2); - - rcc.apb2enr.modify(|_, w| w.spi4en().set_bit()); - let spi4 = dp.SPI4; - spi4_setup(&spi4); - - rcc.apb2enr.modify(|_, w| w.spi1en().set_bit()); - let spi1 = dp.SPI1; - spi1_setup(&spi1); - spi1.ier.write(|w| w.eotie().set_bit()); - - rcc.apb2enr.modify(|_, w| w.spi5en().set_bit()); - let spi5 = dp.SPI5; - spi5_setup(&spi5); - // spi5.ier.write(|w| w.eotie().set_bit()); - - rcc.ahb2enr.modify(|_, w| - w - .sram1en().set_bit() - .sram2en().set_bit() - .sram3en().set_bit() - ); - rcc.ahb1enr.modify(|_, w| w.dma1en().set_bit()); - // init SRAM1 rodata can't load with sram1 disabled - unsafe { DAT = 0x201 }; // EN | CSTART - cortex_m::asm::dsb(); - let dat_addr = unsafe { &DAT as *const _ } as usize; - cp.SCB.clean_dcache_by_address(dat_addr, 4); - - dma1_setup(&dp.DMA1, &dp.DMAMUX1, dat_addr, - &spi1.cr1 as *const _ as usize, - &spi5.cr1 as *const _ as usize); - - rcc.apb1lenr.modify(|_, w| w.tim2en().set_bit()); - - // work around the SPI stall erratum - let dbgmcu = dp.DBGMCU; - dbgmcu.apb1lfz1.modify(|_, w| w.tim2().set_bit()); - - tim2_setup(&dp.TIM2); - - let i2c2 = dp.I2C2; - i2c::setup(&rcc, &i2c2); - - eth::setup(&rcc, &dp.SYSCFG); - eth::setup_pins(&dp.GPIOA, &dp.GPIOB, &dp.GPIOC, &dp.GPIOG); - // c.schedule.tick(Instant::now()).unwrap(); + let dp = c.device; init::LateResources { - spi: (spi1, spi2, spi4, spi5), - i2c: i2c2, + spi: (dp.SPI1, dp.SPI2, dp.SPI4, dp.SPI5), + i2c: dp.I2C2, ethernet_periph: (dp.ETHERNET_MAC, dp.ETHERNET_DMA, dp.ETHERNET_MTL), } }