rustfmt: run

This commit is contained in:
Robert Jördens 2019-11-24 15:09:52 +01:00
parent 501b3c11d3
commit b34fdf7c48
6 changed files with 720 additions and 466 deletions

View File

@ -1,14 +1,11 @@
use super::pac;
use super::i2c;
use super::eth; use super::eth;
use super::i2c;
use super::pac;
fn pwr_setup(pwr: &pac::PWR) { fn pwr_setup(pwr: &pac::PWR) {
// go to VOS1 voltage scale for high perf // go to VOS1 voltage scale for high perf
pwr.cr3.write(|w| pwr.cr3
w.scuen().set_bit() .write(|w| w.scuen().set_bit().ldoen().set_bit().bypass().clear_bit());
.ldoen().set_bit()
.bypass().clear_bit()
);
while pwr.csr1.read().actvosrdy().bit_is_clear() {} while pwr.csr1.read().actvosrdy().bit_is_clear() {}
pwr.d3cr.write(|w| unsafe { w.vos().bits(0b11) }); // vos1 pwr.d3cr.write(|w| unsafe { w.vos().bits(0b11) }); // vos1
while pwr.d3cr.read().vosrdy().bit_is_clear() {} while pwr.d3cr.read().vosrdy().bit_is_clear() {}
@ -50,64 +47,89 @@ fn rcc_pll_setup(rcc: &pac::RCC, flash: &pac::FLASH) {
rcc.cfgr.reset(); rcc.cfgr.reset();
// Ensure HSE is on and stable // Ensure HSE is on and stable
rcc.cr.modify(|_, w| rcc.cr.modify(|_, w| w.hseon().on().hsebyp().not_bypassed());
w.hseon().on()
.hsebyp().not_bypassed());
while !rcc.cr.read().hserdy().is_ready() {} while !rcc.cr.read().hserdy().is_ready() {}
rcc.pllckselr.modify(|_, w| rcc.pllckselr.modify(
w.pllsrc().hse() |_, w| {
.divm1().bits(1) // ref prescaler w.pllsrc()
.divm2().bits(1) // ref prescaler .hse()
.divm1()
.bits(1) // ref prescaler
.divm2()
.bits(1)
}, // ref prescaler
); );
// Configure PLL1: 8MHz /1 *100 /2 = 400 MHz // Configure PLL1: 8MHz /1 *100 /2 = 400 MHz
rcc.pllcfgr.modify(|_, w| rcc.pllcfgr.modify(|_, w| {
w.pll1vcosel().wide_vco() // 192-836 MHz VCO w.pll1vcosel()
.pll1rge().range8() // 8-16 MHz PFD .wide_vco() // 192-836 MHz VCO
.pll1fracen().reset() .pll1rge()
.divp1en().enabled() .range8() // 8-16 MHz PFD
.pll2vcosel().medium_vco() // 150-420 MHz VCO .pll1fracen()
.pll2rge().range8() // 8-16 MHz PFD .reset()
.pll2fracen().reset() .divp1en()
.divp2en().enabled() .enabled()
.divq2en().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 { rcc.pll1divr.write(|w| unsafe {
w.divn1().bits(100 - 1) // feebdack divider w.divn1()
.divp1().div2() // p output divider .bits(100 - 1) // feebdack divider
.divp1()
.div2() // p output divider
}); });
rcc.cr.modify(|_, w| w.pll1on().on()); rcc.cr.modify(|_, w| w.pll1on().on());
while !rcc.cr.read().pll1rdy().is_ready() {} while !rcc.cr.read().pll1rdy().is_ready() {}
// Configure PLL2: 8MHz /1 *25 / 2 = 100 MHz // Configure PLL2: 8MHz /1 *25 / 2 = 100 MHz
rcc.pll2divr.write(|w| unsafe { rcc.pll2divr.write(|w| unsafe {
w.divn2().bits(25 - 1) // feebdack divider w.divn2()
.divp2().bits(2 - 1) // p output divider .bits(25 - 1) // feebdack divider
.divq2().bits(2 - 1) // q output divider .divp2()
.bits(2 - 1) // p output divider
.divq2()
.bits(2 - 1) // q output divider
}); });
rcc.cr.modify(|_, w| w.pll2on().on()); rcc.cr.modify(|_, w| w.pll2on().on());
while !rcc.cr.read().pll2rdy().is_ready() {} while !rcc.cr.read().pll2rdy().is_ready() {}
// hclk 200 MHz, pclk 100 MHz // hclk 200 MHz, pclk 100 MHz
rcc.d1cfgr.write(|w| rcc.d1cfgr.write(
w.d1cpre().div1() // sys_ck not divided |w| {
.hpre().div2() // rcc_hclk3 = sys_d1cpre_ck / 2 w.d1cpre()
.d1ppre().div2() // rcc_pclk3 = rcc_hclk3 / 2 .div1() // sys_ck not divided
.hpre()
.div2() // rcc_hclk3 = sys_d1cpre_ck / 2
.d1ppre()
.div2()
}, // rcc_pclk3 = rcc_hclk3 / 2
); );
rcc.d2cfgr.write(|w| rcc.d2cfgr.write(
w.d2ppre1().div2() // rcc_pclk1 = rcc_hclk3 / 2 |w| {
.d2ppre2().div2() // rcc_pclk2 = rcc_hclk3 / 2 w.d2ppre1()
.div2() // rcc_pclk1 = rcc_hclk3 / 2
.d2ppre2()
.div2()
}, // rcc_pclk2 = rcc_hclk3 / 2
); );
rcc.d3cfgr.write(|w| rcc.d3cfgr.write(
w.d3ppre().div2() // rcc_pclk4 = rcc_hclk3 / 2 |w| w.d3ppre().div2(), // rcc_pclk4 = rcc_hclk3 / 2
); );
// 2 wait states, 0b10 programming delay // 2 wait states, 0b10 programming delay
// 185-210 MHz // 185-210 MHz
flash.acr.write(|w| unsafe { flash
w.wrhighfreq().bits(2) .acr
.latency().bits(2) .write(|w| unsafe { w.wrhighfreq().bits(2).latency().bits(2) });
});
while flash.acr.read().latency().bits() != 2 {} while flash.acr.read().latency().bits() != 2 {}
// CSI for I/O compensationc ell // CSI for I/O compensationc ell
@ -119,24 +141,26 @@ fn rcc_pll_setup(rcc: &pac::RCC, flash: &pac::FLASH) {
while !rcc.cfgr.read().sws().is_pll1() {} while !rcc.cfgr.read().sws().is_pll1() {}
rcc.d1ccipr.write(|w| w.ckpersel().hse()); rcc.d1ccipr.write(|w| w.ckpersel().hse());
rcc.d2ccip1r.modify(|_, w| rcc.d2ccip1r
w.spi123sel().pll2_p() .modify(|_, w| w.spi123sel().pll2_p().spi45sel().pll2_q());
.spi45sel().pll2_q()
);
rcc.d3ccipr.modify(|_, w| w.spi6sel().pll2_q()); rcc.d3ccipr.modify(|_, w| w.spi6sel().pll2_q());
} }
fn io_compensation_setup(syscfg: &pac::SYSCFG) { fn io_compensation_setup(syscfg: &pac::SYSCFG) {
syscfg.cccsr.modify(|_, w| syscfg
w.en().set_bit() .cccsr
.cs().clear_bit() .modify(|_, w| w.en().set_bit().cs().clear_bit().hslv().clear_bit());
.hslv().clear_bit()
);
while syscfg.cccsr.read().ready().bit_is_clear() {} while syscfg.cccsr.read().ready().bit_is_clear() {}
} }
fn gpio_setup(gpioa: &pac::GPIOA, gpiob: &pac::GPIOB, gpiod: &pac::GPIOD, fn gpio_setup(
gpioe: &pac::GPIOE, gpiof: &pac::GPIOF, gpiog: &pac::GPIOG) { gpioa: &pac::GPIOA,
gpiob: &pac::GPIOB,
gpiod: &pac::GPIOD,
gpioe: &pac::GPIOE,
gpiof: &pac::GPIOF,
gpiog: &pac::GPIOG,
) {
// FP_LED0 // FP_LED0
gpiod.otyper.modify(|_, w| w.ot5().push_pull()); gpiod.otyper.modify(|_, w| w.ot5().push_pull());
gpiod.moder.modify(|_, w| w.moder5().output()); gpiod.moder.modify(|_, w| w.moder5().output());
@ -158,18 +182,13 @@ fn gpio_setup(gpioa: &pac::GPIOA, gpiob: &pac::GPIOB, gpiod: &pac::GPIOD,
gpiod.odr.modify(|_, w| w.odr12().low()); gpiod.odr.modify(|_, w| w.odr12().low());
// AFE0_A0,1: PG2,PG3 // AFE0_A0,1: PG2,PG3
gpiog.otyper.modify(|_, w| gpiog
w.ot2().push_pull() .otyper
.ot3().push_pull() .modify(|_, w| w.ot2().push_pull().ot3().push_pull());
); gpiog
gpiog.moder.modify(|_, w| .moder
w.moder2().output() .modify(|_, w| w.moder2().output().moder3().output());
.moder3().output() gpiog.odr.modify(|_, w| w.odr2().low().odr3().low());
);
gpiog.odr.modify(|_, w|
w.odr2().low()
.odr3().low()
);
// ADC0 // ADC0
// SCK: PG11 // SCK: PG11
@ -216,32 +235,22 @@ fn gpio_setup(gpioa: &pac::GPIOA, gpiob: &pac::GPIOB, gpiod: &pac::GPIOD,
gpioe.odr.modify(|_, w| w.odr12().high()); gpioe.odr.modify(|_, w| w.odr12().high());
// AFE1_A0,1: PD14,PD15 // AFE1_A0,1: PD14,PD15
gpiod.otyper.modify(|_, w| gpiod
w.ot14().push_pull() .otyper
.ot15().push_pull() .modify(|_, w| w.ot14().push_pull().ot15().push_pull());
); gpiod
gpiod.moder.modify(|_, w| .moder
w.moder14().output() .modify(|_, w| w.moder14().output().moder15().output());
.moder15().output() gpiod.odr.modify(|_, w| w.odr14().low().odr15().low());
);
gpiod.odr.modify(|_, w|
w.odr14().low()
.odr15().low()
);
// I2C2: SDA,SCL: PF0,PF1 // I2C2: SDA,SCL: PF0,PF1
gpiof.moder.modify(|_, w| gpiof
w.moder0().alternate() .moder
.moder1().alternate() .modify(|_, w| w.moder0().alternate().moder1().alternate());
); gpiof.afrl.modify(|_, w| w.afr0().af4().afr1().af4());
gpiof.afrl.modify(|_, w| gpiof
w.afr0().af4() .otyper
.afr1().af4() .modify(|_, w| w.ot0().open_drain().ot1().open_drain());
);
gpiof.otyper.modify(|_, w|
w.ot0().open_drain()
.ot1().open_drain()
);
// ADC1 // ADC1
// SCK: PF6 // SCK: PF6
@ -285,81 +294,114 @@ fn gpio_setup(gpioa: &pac::GPIOA, gpiob: &pac::GPIOB, gpiod: &pac::GPIOD,
// ADC0 // ADC0
fn spi1_setup(spi1: &pac::SPI1) { fn spi1_setup(spi1: &pac::SPI1) {
spi1.cfg1.modify(|_, w| spi1.cfg1
w.mbr().div4() .modify(|_, w| w.mbr().div4().dsize().bits(16 - 1).fthlv().one_frame());
.dsize().bits(16 - 1) spi1.cfg2.modify(|_, w| {
.fthlv().one_frame() w.afcntr()
); .controlled()
spi1.cfg2.modify(|_, w| .ssom()
w.afcntr().controlled() .not_asserted()
.ssom().not_asserted() .ssoe()
.ssoe().enabled() .enabled()
.ssiop().active_low() .ssiop()
.ssm().disabled() .active_low()
.cpol().idle_high() .ssm()
.cpha().second_edge() .disabled()
.lsbfrst().msbfirst() .cpol()
.master().master() .idle_high()
.sp().motorola() .cpha()
.comm().receiver() .second_edge()
.ioswp().disabled() .lsbfrst()
.midi().bits(0) .msbfirst()
.mssi().bits(6) .master()
); .master()
.sp()
.motorola()
.comm()
.receiver()
.ioswp()
.disabled()
.midi()
.bits(0)
.mssi()
.bits(6)
});
spi1.cr2.modify(|_, w| w.tsize().bits(1)); spi1.cr2.modify(|_, w| w.tsize().bits(1));
spi1.cr1.write(|w| w.spe().enabled()); spi1.cr1.write(|w| w.spe().enabled());
} }
// ADC1 // ADC1
fn spi5_setup(spi5: &pac::SPI5) { fn spi5_setup(spi5: &pac::SPI5) {
spi5.cfg1.modify(|_, w| spi5.cfg1
w.mbr().div4() .modify(|_, w| w.mbr().div4().dsize().bits(16 - 1).fthlv().one_frame());
.dsize().bits(16 - 1) spi5.cfg2.modify(|_, w| {
.fthlv().one_frame() w.afcntr()
); .controlled()
spi5.cfg2.modify(|_, w| .ssom()
w.afcntr().controlled() .not_asserted()
.ssom().not_asserted() .ssoe()
.ssoe().enabled() .enabled()
.ssiop().active_low() .ssiop()
.ssm().disabled() .active_low()
.cpol().idle_high() .ssm()
.cpha().second_edge() .disabled()
.lsbfrst().msbfirst() .cpol()
.master().master() .idle_high()
.sp().motorola() .cpha()
.comm().receiver() .second_edge()
.ioswp().disabled() .lsbfrst()
.midi().bits(0) .msbfirst()
.mssi().bits(6) .master()
); .master()
.sp()
.motorola()
.comm()
.receiver()
.ioswp()
.disabled()
.midi()
.bits(0)
.mssi()
.bits(6)
});
spi5.cr2.modify(|_, w| w.tsize().bits(1)); spi5.cr2.modify(|_, w| w.tsize().bits(1));
spi5.cr1.write(|w| w.spe().enabled()); spi5.cr1.write(|w| w.spe().enabled());
} }
// DAC0 // DAC0
fn spi2_setup(spi2: &pac::SPI2) { fn spi2_setup(spi2: &pac::SPI2) {
spi2.cfg1.modify(|_, w| spi2.cfg1
w.mbr().div2() .modify(|_, w| w.mbr().div2().dsize().bits(16 - 1).fthlv().one_frame());
.dsize().bits(16 - 1) spi2.cfg2.modify(|_, w| {
.fthlv().one_frame() w.afcntr()
); .controlled()
spi2.cfg2.modify(|_, w| .ssom()
w.afcntr().controlled() .not_asserted()
.ssom().not_asserted() .ssoe()
.ssoe().enabled() .enabled()
.ssiop().active_low() .ssiop()
.ssm().disabled() .active_low()
.cpol().idle_low() .ssm()
.cpha().first_edge() .disabled()
.lsbfrst().msbfirst() .cpol()
.master().master() .idle_low()
.sp().motorola() .cpha()
.comm().transmitter() .first_edge()
.ioswp().disabled() .lsbfrst()
.midi().bits(0) .msbfirst()
.mssi().bits(0) .master()
); .master()
.sp()
.motorola()
.comm()
.transmitter()
.ioswp()
.disabled()
.midi()
.bits(0)
.mssi()
.bits(0)
});
spi2.cr2.modify(|_, w| w.tsize().bits(0)); spi2.cr2.modify(|_, w| w.tsize().bits(0));
spi2.cr1.write(|w| w.spe().enabled()); spi2.cr1.write(|w| w.spe().enabled());
spi2.cr1.modify(|_, w| w.cstart().started()); spi2.cr1.modify(|_, w| w.cstart().started());
@ -367,27 +409,38 @@ fn spi2_setup(spi2: &pac::SPI2) {
// DAC1 // DAC1
fn spi4_setup(spi4: &pac::SPI4) { fn spi4_setup(spi4: &pac::SPI4) {
spi4.cfg1.modify(|_, w| spi4.cfg1
w.mbr().div2() .modify(|_, w| w.mbr().div2().dsize().bits(16 - 1).fthlv().one_frame());
.dsize().bits(16 - 1) spi4.cfg2.modify(|_, w| {
.fthlv().one_frame() w.afcntr()
); .controlled()
spi4.cfg2.modify(|_, w| .ssom()
w.afcntr().controlled() .not_asserted()
.ssom().not_asserted() .ssoe()
.ssoe().enabled() .enabled()
.ssiop().active_low() .ssiop()
.ssm().disabled() .active_low()
.cpol().idle_low() .ssm()
.cpha().first_edge() .disabled()
.lsbfrst().msbfirst() .cpol()
.master().master() .idle_low()
.sp().motorola() .cpha()
.comm().transmitter() .first_edge()
.ioswp().disabled() .lsbfrst()
.midi().bits(0) .msbfirst()
.mssi().bits(0) .master()
); .master()
.sp()
.motorola()
.comm()
.transmitter()
.ioswp()
.disabled()
.midi()
.bits(0)
.mssi()
.bits(0)
});
spi4.cr2.modify(|_, w| w.tsize().bits(0)); spi4.cr2.modify(|_, w| w.tsize().bits(0));
spi4.cr1.write(|w| w.spe().enabled()); spi4.cr1.write(|w| w.spe().enabled());
spi4.cr1.modify(|_, w| w.cstart().started()); spi4.cr1.modify(|_, w| w.cstart().started());
@ -398,11 +451,16 @@ fn tim2_setup(tim2: &pac::TIM2) {
tim2.arr.write(|w| unsafe { w.bits(2 - 1) }); // ‘s tim2.arr.write(|w| unsafe { w.bits(2 - 1) }); // ‘s
tim2.dier.write(|w| w.ude().set_bit()); tim2.dier.write(|w| w.ude().set_bit());
tim2.egr.write(|w| w.ug().set_bit()); tim2.egr.write(|w| w.ug().set_bit());
tim2.cr1.modify(|_, w| tim2.cr1.modify(|_, w| w.dir().clear_bit()); // up
w.dir().clear_bit()); // up
} }
fn dma1_setup(dma1: &pac::DMA1, dmamux1: &pac::DMAMUX1, ma: usize, pa0: usize, pa1: usize) { 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()); dma1.st[0].cr.modify(|_, w| w.en().clear_bit());
while dma1.st[0].cr.read().en().bit_is_set() {} while dma1.st[0].cr.read().en().bit_is_set() {}
@ -411,17 +469,28 @@ fn dma1_setup(dma1: &pac::DMA1, dmamux1: &pac::DMAMUX1, ma: usize, pa0: usize, p
dma1.st[0].ndtr.write(|w| unsafe { w.ndt().bits(1) }); dma1.st[0].ndtr.write(|w| unsafe { w.ndt().bits(1) });
dmamux1.ccr[0].modify(|_, w| w.dmareq_id().tim2_up()); dmamux1.ccr[0].modify(|_, w| w.dmareq_id().tim2_up());
dma1.st[0].cr.modify(|_, w| unsafe { dma1.st[0].cr.modify(|_, w| unsafe {
w.pl().bits(0b01) // medium w.pl()
.circ().set_bit() // reload ndtr .bits(0b01) // medium
.msize().bits(0b10) // 32 .circ()
.minc().clear_bit() .set_bit() // reload ndtr
.mburst().bits(0b00) .msize()
.psize().bits(0b10) // 32 .bits(0b10) // 32
.pinc().clear_bit() .minc()
.pburst().bits(0b00) .clear_bit()
.dbm().clear_bit() .mburst()
.dir().bits(0b01) // memory_to_peripheral .bits(0b00)
.pfctrl().clear_bit() // dma is FC .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].fcr.modify(|_, w| w.dmdis().clear_bit());
dma1.st[0].cr.modify(|_, w| w.en().set_bit()); dma1.st[0].cr.modify(|_, w| w.en().set_bit());
@ -434,17 +503,28 @@ fn dma1_setup(dma1: &pac::DMA1, dmamux1: &pac::DMAMUX1, ma: usize, pa0: usize, p
dma1.st[1].ndtr.write(|w| unsafe { w.ndt().bits(1) }); dma1.st[1].ndtr.write(|w| unsafe { w.ndt().bits(1) });
dmamux1.ccr[1].modify(|_, w| w.dmareq_id().tim2_up()); dmamux1.ccr[1].modify(|_, w| w.dmareq_id().tim2_up());
dma1.st[1].cr.modify(|_, w| unsafe { dma1.st[1].cr.modify(|_, w| unsafe {
w.pl().bits(0b01) // medium w.pl()
.circ().set_bit() // reload ndtr .bits(0b01) // medium
.msize().bits(0b10) // 32 .circ()
.minc().clear_bit() .set_bit() // reload ndtr
.mburst().bits(0b00) .msize()
.psize().bits(0b10) // 32 .bits(0b10) // 32
.pinc().clear_bit() .minc()
.pburst().bits(0b00) .clear_bit()
.dbm().clear_bit() .mburst()
.dir().bits(0b01) // memory_to_peripheral .bits(0b00)
.pfctrl().clear_bit() // dma is FC .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].fcr.modify(|_, w| w.dmdis().clear_bit());
dma1.st[1].cr.modify(|_, w| w.en().set_bit()); dma1.st[1].cr.modify(|_, w| w.en().set_bit());
@ -469,16 +549,25 @@ pub fn init() {
// cp.SCB.enable_dcache(&mut cp.CPUID); // cp.SCB.enable_dcache(&mut cp.CPUID);
cp.DWT.enable_cycle_counter(); // japaric/cortex-m-rtfm#184 cp.DWT.enable_cycle_counter(); // japaric/cortex-m-rtfm#184
rcc.ahb4enr.modify(|_, w| rcc.ahb4enr.modify(|_, w| {
w.gpioaen().set_bit() w.gpioaen()
.gpioben().set_bit() .set_bit()
.gpiocen().set_bit() .gpioben()
.gpioden().set_bit() .set_bit()
.gpioeen().set_bit() .gpiocen()
.gpiofen().set_bit() .set_bit()
.gpiogen().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,
); );
gpio_setup(&dp.GPIOA, &dp.GPIOB, &dp.GPIOD, &dp.GPIOE, &dp.GPIOF, &dp.GPIOG);
rcc.apb1lenr.modify(|_, w| w.spi2en().set_bit()); rcc.apb1lenr.modify(|_, w| w.spi2en().set_bit());
let spi2 = dp.SPI2; let spi2 = dp.SPI2;
@ -498,12 +587,14 @@ pub fn init() {
spi5_setup(&spi5); spi5_setup(&spi5);
// spi5.ier.write(|w| w.eotie().set_bit()); // spi5.ier.write(|w| w.eotie().set_bit());
rcc.ahb2enr.modify(|_, w| rcc.ahb2enr.modify(|_, w| {
w w.sram1en()
.sram1en().set_bit() .set_bit()
.sram2en().set_bit() .sram2en()
.sram3en().set_bit() .set_bit()
); .sram3en()
.set_bit()
});
rcc.ahb1enr.modify(|_, w| w.dma1en().set_bit()); rcc.ahb1enr.modify(|_, w| w.dma1en().set_bit());
// init SRAM1 rodata can't load with sram1 disabled // init SRAM1 rodata can't load with sram1 disabled
unsafe { DAT = 0x201 }; // EN | CSTART unsafe { DAT = 0x201 }; // EN | CSTART
@ -511,9 +602,13 @@ pub fn init() {
let dat_addr = unsafe { &DAT as *const _ } as usize; let dat_addr = unsafe { &DAT as *const _ } as usize;
cp.SCB.clean_dcache_by_address(dat_addr, 4); cp.SCB.clean_dcache_by_address(dat_addr, 4);
dma1_setup(&dp.DMA1, &dp.DMAMUX1, dat_addr, dma1_setup(
&dp.DMA1,
&dp.DMAMUX1,
dat_addr,
&spi1.cr1 as *const _ as usize, &spi1.cr1 as *const _ as usize,
&spi5.cr1 as *const _ as usize); &spi5.cr1 as *const _ as usize,
);
rcc.apb1lenr.modify(|_, w| w.tim2en().set_bit()); rcc.apb1lenr.modify(|_, w| w.tim2en().set_bit());
@ -528,11 +623,16 @@ pub fn init() {
rcc.apb4enr.modify(|_, w| w.syscfgen().set_bit()); rcc.apb4enr.modify(|_, w| w.syscfgen().set_bit());
rcc.ahb1enr.modify(|_, w| { rcc.ahb1enr.modify(|_, w| {
w.eth1macen().set_bit() w.eth1macen()
.eth1txen().set_bit() .set_bit()
.eth1rxen().set_bit() .eth1txen()
.set_bit()
.eth1rxen()
.set_bit()
}); });
dp.SYSCFG.pmcr.modify(|_, w| unsafe { w.epis().bits(0b100) }); // RMII dp.SYSCFG
.pmcr
.modify(|_, w| unsafe { w.epis().bits(0b100) }); // RMII
eth::setup_pins(&dp.GPIOA, &dp.GPIOB, &dp.GPIOC, &dp.GPIOG); eth::setup_pins(&dp.GPIOA, &dp.GPIOB, &dp.GPIOC, &dp.GPIOG);
// enable TIM2 this must be late to be able to handle the first ADC SPI // enable TIM2 this must be late to be able to handle the first ADC SPI

View File

@ -1,5 +1,5 @@
use stm32h7::stm32h743 as pac;
use super::i2c; use super::i2c;
use stm32h7::stm32h743 as pac;
const I2C_ADDR: u8 = 0xa0; const I2C_ADDR: u8 = 0xa0;

View File

@ -1,9 +1,9 @@
use core::{slice, cmp}; use core::{cmp, slice};
use stm32h7::stm32h743 as pac; use smoltcp::phy;
use smoltcp::Result;
use smoltcp::time::Instant; use smoltcp::time::Instant;
use smoltcp::wire::EthernetAddress; use smoltcp::wire::EthernetAddress;
use smoltcp::phy; use smoltcp::Result;
use stm32h7::stm32h743 as pac;
#[allow(dead_code)] #[allow(dead_code)]
mod phy_consts { mod phy_consts {
@ -85,8 +85,12 @@ use self::cr_consts::*;
// 200 MHz AHB clock = eth_hclk // 200 MHz AHB clock = eth_hclk
const CLOCK_RANGE: u8 = ETH_MACMIIAR_CR_HCLK_DIV_102; const CLOCK_RANGE: u8 = ETH_MACMIIAR_CR_HCLK_DIV_102;
pub fn setup_pins(gpioa: &pac::GPIOA, gpiob: &pac::GPIOB, pub fn setup_pins(
gpioc: &pac::GPIOC, gpiog: &pac::GPIOG) { gpioa: &pac::GPIOA,
gpiob: &pac::GPIOB,
gpioc: &pac::GPIOC,
gpiog: &pac::GPIOG,
) {
// PA1 RMII_REF_CLK // PA1 RMII_REF_CLK
gpioa.moder.modify(|_, w| w.moder1().alternate()); gpioa.moder.modify(|_, w| w.moder1().alternate());
gpioa.afrl.modify(|_, w| w.afr1().af11()); gpioa.afrl.modify(|_, w| w.afr1().af11());
@ -130,12 +134,16 @@ const PHY_ADDR: u8 = 0;
fn phy_read(reg_addr: u8, mac: &pac::ETHERNET_MAC) -> u16 { fn phy_read(reg_addr: u8, mac: &pac::ETHERNET_MAC) -> u16 {
while mac.macmdioar.read().mb().bit_is_set() {} while mac.macmdioar.read().mb().bit_is_set() {}
mac.macmdioar.modify(|_, w| unsafe { mac.macmdioar.modify(|_, w| unsafe {
w w.pa()
.pa().bits(PHY_ADDR) .bits(PHY_ADDR)
.rda().bits(reg_addr) .rda()
.goc().bits(0b11) // read .bits(reg_addr)
.cr().bits(CLOCK_RANGE) .goc()
.mb().set_bit() .bits(0b11) // read
.cr()
.bits(CLOCK_RANGE)
.mb()
.set_bit()
}); });
while mac.macmdioar.read().mb().bit_is_set() {} while mac.macmdioar.read().mb().bit_is_set() {}
mac.macmdiodr.read().md().bits() mac.macmdiodr.read().md().bits()
@ -145,12 +153,16 @@ fn phy_write(reg_addr: u8, reg_data: u16, mac: &pac::ETHERNET_MAC) {
while mac.macmdioar.read().mb().bit_is_set() {} while mac.macmdioar.read().mb().bit_is_set() {}
mac.macmdiodr.write(|w| unsafe { w.md().bits(reg_data) }); mac.macmdiodr.write(|w| unsafe { w.md().bits(reg_data) });
mac.macmdioar.modify(|_, w| unsafe { mac.macmdioar.modify(|_, w| unsafe {
w w.pa()
.pa().bits(PHY_ADDR) .bits(PHY_ADDR)
.rda().bits(reg_addr) .rda()
.goc().bits(0b01) // write .bits(reg_addr)
.cr().bits(CLOCK_RANGE) .goc()
.mb().set_bit() .bits(0b01) // write
.cr()
.bits(CLOCK_RANGE)
.mb()
.set_bit()
}); });
while mac.macmdioar.read().mb().bit_is_set() {} while mac.macmdioar.read().mb().bit_is_set() {}
} }
@ -195,7 +207,8 @@ impl RxRing {
let addr = &self.desc_buf as *const _ as u32; let addr = &self.desc_buf as *const _ as u32;
assert_eq!(addr & 0x3, 0); assert_eq!(addr & 0x3, 0);
dma.dmacrx_dlar.write(|w| w.bits(addr)); dma.dmacrx_dlar.write(|w| w.bits(addr));
dma.dmacrx_rlr.write(|w| w.rdrl().bits(self.desc_buf.len() as u16 - 1)); dma.dmacrx_rlr
.write(|w| w.rdrl().bits(self.desc_buf.len() as u16 - 1));
self.cur_desc = 0; self.cur_desc = 0;
for _ in 0..self.desc_buf.len() { for _ in 0..self.desc_buf.len() {
@ -213,9 +226,9 @@ impl RxRing {
} }
fn buf_valid(&self) -> bool { fn buf_valid(&self) -> bool {
self.desc_buf[self.cur_desc][3] & self.desc_buf[self.cur_desc][3]
(EMAC_DES3_FD | EMAC_DES3_LD | EMAC_DES3_ES | EMAC_DES3_CTXT) == & (EMAC_DES3_FD | EMAC_DES3_LD | EMAC_DES3_ES | EMAC_DES3_CTXT)
(EMAC_DES3_FD | EMAC_DES3_LD) == (EMAC_DES3_FD | EMAC_DES3_LD)
} }
unsafe fn buf_as_slice_mut<'a>(&self) -> &'a mut [u8] { unsafe fn buf_as_slice_mut<'a>(&self) -> &'a mut [u8] {
@ -228,7 +241,8 @@ impl RxRing {
fn buf_release(&mut self) { fn buf_release(&mut self) {
let addr = &self.pkt_buf[self.cur_desc] as *const _; let addr = &self.pkt_buf[self.cur_desc] as *const _;
self.desc_buf[self.cur_desc][0] = addr as u32 & EMAC_DES0_BUF1AP; self.desc_buf[self.cur_desc][0] = addr as u32 & EMAC_DES0_BUF1AP;
self.desc_buf[self.cur_desc][3] = EMAC_RDES3_BUF1V | EMAC_RDES3_IOC | EMAC_DES3_OWN; self.desc_buf[self.cur_desc][3] =
EMAC_RDES3_BUF1V | EMAC_RDES3_IOC | EMAC_DES3_OWN;
let addr = &self.desc_buf[self.cur_desc] as *const _ as u32; let addr = &self.desc_buf[self.cur_desc] as *const _ as u32;
assert_eq!(addr & 0x3, 0); assert_eq!(addr & 0x3, 0);
@ -278,7 +292,8 @@ impl TxRing {
let addr = &self.desc_buf as *const _ as u32; let addr = &self.desc_buf as *const _ as u32;
assert_eq!(addr & 0x3, 0); assert_eq!(addr & 0x3, 0);
dma.dmactx_dlar.write(|w| w.bits(addr)); dma.dmactx_dlar.write(|w| w.bits(addr));
dma.dmactx_rlr.write(|w| w.tdrl().bits(self.desc_buf.len() as u16 - 1)); dma.dmactx_rlr
.write(|w| w.tdrl().bits(self.desc_buf.len() as u16 - 1));
let addr = &self.desc_buf[0] as *const _ as u32; let addr = &self.desc_buf[0] as *const _ as u32;
assert_eq!(addr & 0x3, 0); assert_eq!(addr & 0x3, 0);
dma.dmactx_dtpr.write(|w| w.bits(addr)); dma.dmactx_dtpr.write(|w| w.bits(addr));
@ -295,14 +310,16 @@ impl TxRing {
unsafe fn buf_as_slice_mut<'a>(&mut self, len: usize) -> &'a mut [u8] { unsafe fn buf_as_slice_mut<'a>(&mut self, len: usize) -> &'a mut [u8] {
let len = cmp::min(len, ETH_BUFFER_SIZE); let len = cmp::min(len, ETH_BUFFER_SIZE);
self.desc_buf[self.cur_desc][2] = EMAC_TDES2_IOC | (len as u32 & EMAC_TDES2_B1L); self.desc_buf[self.cur_desc][2] =
EMAC_TDES2_IOC | (len as u32 & EMAC_TDES2_B1L);
let addr = &self.pkt_buf[self.cur_desc] as *const _ as *mut u8; let addr = &self.pkt_buf[self.cur_desc] as *const _ as *mut u8;
self.desc_buf[self.cur_desc][0] = addr as u32 & EMAC_DES0_BUF1AP; self.desc_buf[self.cur_desc][0] = addr as u32 & EMAC_DES0_BUF1AP;
slice::from_raw_parts_mut(addr, len) slice::from_raw_parts_mut(addr, len)
} }
fn buf_release(&mut self) { fn buf_release(&mut self) {
self.desc_buf[self.cur_desc][3] = EMAC_DES3_OWN | EMAC_DES3_FD | EMAC_DES3_LD; self.desc_buf[self.cur_desc][3] =
EMAC_DES3_OWN | EMAC_DES3_FD | EMAC_DES3_LD;
self.cur_desc = self.next_desc(); self.cur_desc = self.next_desc();
let addr = &self.desc_buf[self.cur_desc] as *const _ as u32; let addr = &self.desc_buf[self.cur_desc] as *const _ as u32;
@ -325,7 +342,10 @@ pub struct Device {
impl Device { impl Device {
pub const fn new() -> Self { pub const fn new() -> Self {
Self{ rx: RxRing::new(), tx: TxRing::new() } Self {
rx: RxRing::new(),
tx: TxRing::new(),
}
} }
// Initialize the ethernet peripherals // Initialize the ethernet peripherals
@ -337,7 +357,9 @@ impl Device {
// are correct. // are correct.
// //
// After `init` is called, `Device` shall not be moved. // After `init` is called, `Device` shall not be moved.
pub unsafe fn init(&mut self, mac: EthernetAddress, pub unsafe fn init(
&mut self,
mac: EthernetAddress,
eth_mac: &pac::ETHERNET_MAC, eth_mac: &pac::ETHERNET_MAC,
eth_dma: &pac::ETHERNET_DMA, eth_dma: &pac::ETHERNET_DMA,
eth_mtl: &pac::ETHERNET_MTL, eth_mtl: &pac::ETHERNET_MTL,
@ -346,66 +368,97 @@ impl Device {
while eth_dma.dmamr.read().swr().bit_is_set() {} while eth_dma.dmamr.read().swr().bit_is_set() {}
// 200 MHz // 200 MHz
eth_mac.mac1ustcr.modify(|_, w| w.tic_1us_cntr().bits(200 - 1)); eth_mac
.mac1ustcr
.modify(|_, w| w.tic_1us_cntr().bits(200 - 1));
// Configuration Register // Configuration Register
eth_mac.maccr.modify(|_, w| { eth_mac.maccr.modify(|_, w| {
w w.arpen()
.arpen().clear_bit() .clear_bit()
.ipc().set_bit() .ipc()
.ipg().bits(0b000) // 96 bit .set_bit()
.ecrsfd().clear_bit() .ipg()
.dcrs().clear_bit() .bits(0b000) // 96 bit
.bl().bits(0b00) // 19 .ecrsfd()
.prelen().bits(0b00) // 7 .clear_bit()
.dcrs()
.clear_bit()
.bl()
.bits(0b00) // 19
.prelen()
.bits(0b00) // 7
// CRC stripping for Type frames // CRC stripping for Type frames
.cst().set_bit() .cst()
.set_bit()
// Fast Ethernet speed // Fast Ethernet speed
.fes().set_bit() .fes()
.set_bit()
// Duplex mode // Duplex mode
.dm().set_bit() .dm()
.set_bit()
// Automatic pad/CRC stripping // Automatic pad/CRC stripping
.acs().set_bit() .acs()
.set_bit()
// Retry disable in half-duplex mode // Retry disable in half-duplex mode
.dr().set_bit() .dr()
.set_bit()
}); });
eth_mac.macecr.modify(|_, w| { eth_mac.macecr.modify(|_, w| {
w w.eipgen()
.eipgen().clear_bit() .clear_bit()
.usp().clear_bit() .usp()
.spen().clear_bit() .clear_bit()
.dcrcc().clear_bit() .spen()
.clear_bit()
.dcrcc()
.clear_bit()
}); });
// Set the MAC address // Set the MAC address
eth_mac.maca0lr.write(|w| eth_mac.maca0lr.write(|w| {
w.addrlo().bits( u32::from(mac.0[0]) | w.addrlo().bits(
(u32::from(mac.0[1]) << 8) | u32::from(mac.0[0])
(u32::from(mac.0[2]) << 16) | | (u32::from(mac.0[1]) << 8)
(u32::from(mac.0[3]) << 24)) | (u32::from(mac.0[2]) << 16)
); | (u32::from(mac.0[3]) << 24),
eth_mac.maca0hr.write(|w| )
w.addrhi().bits( u16::from(mac.0[4]) | });
(u16::from(mac.0[5]) << 8)) eth_mac.maca0hr.write(|w| {
); w.addrhi()
.bits(u16::from(mac.0[4]) | (u16::from(mac.0[5]) << 8))
});
// frame filter register // frame filter register
eth_mac.macpfr.modify(|_, w| { eth_mac.macpfr.modify(|_, w| {
w w.dntu()
.dntu().clear_bit() .clear_bit()
.ipfe().clear_bit() .ipfe()
.vtfe().clear_bit() .clear_bit()
.hpf().clear_bit() .vtfe()
.saf().clear_bit() .clear_bit()
.saif().clear_bit() .hpf()
.pcf().bits(0b00) .clear_bit()
.dbf().clear_bit() .saf()
.pm().clear_bit() .clear_bit()
.daif().clear_bit() .saif()
.hmc().clear_bit() .clear_bit()
.huc().clear_bit() .pcf()
.bits(0b00)
.dbf()
.clear_bit()
.pm()
.clear_bit()
.daif()
.clear_bit()
.hmc()
.clear_bit()
.huc()
.clear_bit()
// Receive All // Receive All
.ra().clear_bit() .ra()
.clear_bit()
// Promiscuous mode // Promiscuous mode
.pr().clear_bit() .pr()
.clear_bit()
}); });
eth_mac.macwtr.write(|w| w.pwe().clear_bit()); eth_mac.macwtr.write(|w| w.pwe().clear_bit());
// Flow Control Register // Flow Control Register
@ -414,31 +467,44 @@ impl Device {
w.pt().bits(0x100) w.pt().bits(0x100)
}); });
eth_mac.macrx_fcr.modify(|_, w| w); eth_mac.macrx_fcr.modify(|_, w| w);
eth_mtl.mtlrx_qomr.modify(|_, w| eth_mtl.mtlrx_qomr.modify(|_, w| {
w w
// Receive store and forward // Receive store and forward
.rsf().set_bit() .rsf()
.set_bit()
// Dropping of TCP/IP checksum error frames disable // Dropping of TCP/IP checksum error frames disable
.dis_tcp_ef().clear_bit() .dis_tcp_ef()
.clear_bit()
// Forward error frames // Forward error frames
.fep().clear_bit() .fep()
.clear_bit()
// Forward undersized good packets // Forward undersized good packets
.fup().clear_bit() .fup()
); .clear_bit()
});
eth_mtl.mtltx_qomr.modify(|_, w| { eth_mtl.mtltx_qomr.modify(|_, w| {
w w
// Transmit store and forward // Transmit store and forward
.tsf().set_bit() .tsf()
.set_bit()
}); });
if (phy_read(PHY_REG_ID1, eth_mac) != 0x0007) | (phy_read(PHY_REG_ID2, eth_mac) != 0xC131) { if (phy_read(PHY_REG_ID1, eth_mac) != 0x0007)
| (phy_read(PHY_REG_ID2, eth_mac) != 0xC131)
{
error!("PHY ID error!"); error!("PHY ID error!");
} }
phy_write(PHY_REG_BCR, PHY_REG_BCR_RESET, eth_mac); phy_write(PHY_REG_BCR, PHY_REG_BCR_RESET, eth_mac);
while phy_read(PHY_REG_BCR, eth_mac) & PHY_REG_BCR_RESET == PHY_REG_BCR_RESET {}; while phy_read(PHY_REG_BCR, eth_mac) & PHY_REG_BCR_RESET
== PHY_REG_BCR_RESET
{}
phy_write_ext(PHY_REG_WUCSR, 0, eth_mac); phy_write_ext(PHY_REG_WUCSR, 0, eth_mac);
phy_write(PHY_REG_BCR, PHY_REG_BCR_AN | PHY_REG_BCR_ANRST | PHY_REG_BCR_100M, eth_mac); phy_write(
PHY_REG_BCR,
PHY_REG_BCR_AN | PHY_REG_BCR_ANRST | PHY_REG_BCR_100M,
eth_mac,
);
/* /*
while phy_read(PHY_REG_BSR) & PHY_REG_BSR_UP == 0 {}; while phy_read(PHY_REG_BSR) & PHY_REG_BSR_UP == 0 {};
while phy_read(PHY_REG_BSR) & PHY_REG_BSR_ANDONE == 0 {}; while phy_read(PHY_REG_BSR) & PHY_REG_BSR_ANDONE == 0 {};
@ -448,43 +514,51 @@ impl Device {
// operation mode register // operation mode register
eth_dma.dmamr.modify(|_, w| { eth_dma.dmamr.modify(|_, w| {
w w.intm()
.intm().bits(0b00) .bits(0b00)
// Rx Tx priority ratio 1:1 // Rx Tx priority ratio 1:1
.pr().bits(0b000) .pr()
.txpr().clear_bit() .bits(0b000)
.da().clear_bit() .txpr()
.clear_bit()
.da()
.clear_bit()
}); });
// bus mode register // bus mode register
eth_dma.dmasbmr.modify(|_, w| { eth_dma.dmasbmr.modify(|_, w| {
// Address-aligned beats // Address-aligned beats
w.aal().set_bit() w.aal()
.set_bit()
// Fixed burst // Fixed burst
.fb().set_bit() .fb()
}); .set_bit()
eth_dma.dmaccr.modify(|_, w| {
w
.dsl().bits(0)
.pblx8().clear_bit()
.mss().bits(536)
}); });
eth_dma
.dmaccr
.modify(|_, w| w.dsl().bits(0).pblx8().clear_bit().mss().bits(536));
eth_dma.dmactx_cr.modify(|_, w| { eth_dma.dmactx_cr.modify(|_, w| {
w w
// Tx DMA PBL // Tx DMA PBL
.txpbl().bits(32) .txpbl()
.tse().clear_bit() .bits(32)
.tse()
.clear_bit()
// Operate on second frame // Operate on second frame
.osf().clear_bit() .osf()
.clear_bit()
}); });
eth_dma.dmacrx_cr.modify(|_, w| { eth_dma.dmacrx_cr.modify(|_, w| {
w w
// receive buffer size // receive buffer size
.rbsz().bits(ETH_BUFFER_SIZE as u16) .rbsz()
.bits(ETH_BUFFER_SIZE as u16)
// Rx DMA PBL // Rx DMA PBL
.rxpbl().bits(32) .rxpbl()
.bits(32)
// Disable flushing of received frames // Disable flushing of received frames
.rpf().clear_bit() .rpf()
.clear_bit()
}); });
self.rx.init(eth_dma); self.rx.init(eth_dma);
@ -492,8 +566,10 @@ impl Device {
// Manage MAC transmission and reception // Manage MAC transmission and reception
eth_mac.maccr.modify(|_, w| { eth_mac.maccr.modify(|_, w| {
w.re().bit(true) // Receiver Enable w.re()
.te().bit(true) // Transmiter Enable .bit(true) // Receiver Enable
.te()
.bit(true) // Transmiter Enable
}); });
eth_mtl.mtltx_qomr.modify(|_, w| w.ftq().set_bit()); eth_mtl.mtltx_qomr.modify(|_, w| w.ftq().set_bit());
@ -505,10 +581,9 @@ impl Device {
eth_dma.dmactx_cr.modify(|_, w| w.st().set_bit()); eth_dma.dmactx_cr.modify(|_, w| w.st().set_bit());
eth_dma.dmacrx_cr.modify(|_, w| w.sr().set_bit()); eth_dma.dmacrx_cr.modify(|_, w| w.sr().set_bit());
eth_dma.dmacsr.modify(|_, w| eth_dma
w.tps().set_bit() .dmacsr
.rps().set_bit() .modify(|_, w| w.tps().set_bit().rps().set_bit());
);
} }
} }
@ -532,7 +607,7 @@ impl<'a, 'b> phy::Device<'a> for &'b mut Device {
} }
if !(self.rx.buf_owned() && self.tx.buf_owned()) { if !(self.rx.buf_owned() && self.tx.buf_owned()) {
return None return None;
} }
Some((RxToken(&mut self.rx), TxToken(&mut self.tx))) Some((RxToken(&mut self.rx), TxToken(&mut self.tx)))
@ -540,7 +615,7 @@ impl<'a, 'b> phy::Device<'a> for &'b mut Device {
fn transmit(&mut self) -> Option<TxToken> { fn transmit(&mut self) -> Option<TxToken> {
if !self.tx.buf_owned() { if !self.tx.buf_owned() {
return None return None;
} }
Some(TxToken(&mut self.tx)) Some(TxToken(&mut self.tx))
@ -551,7 +626,9 @@ pub struct RxToken<'a>(&'a mut RxRing);
impl<'a> phy::RxToken for RxToken<'a> { impl<'a> phy::RxToken for RxToken<'a> {
fn consume<R, F>(self, _timestamp: Instant, f: F) -> Result<R> fn consume<R, F>(self, _timestamp: Instant, f: F) -> Result<R>
where F: FnOnce(&mut [u8]) -> Result<R> { where
F: FnOnce(&mut [u8]) -> Result<R>,
{
let result = f(unsafe { self.0.buf_as_slice_mut() }); let result = f(unsafe { self.0.buf_as_slice_mut() });
self.0.buf_release(); self.0.buf_release();
result result
@ -562,7 +639,9 @@ pub struct TxToken<'a>(&'a mut TxRing);
impl<'a> phy::TxToken for TxToken<'a> { impl<'a> phy::TxToken for TxToken<'a> {
fn consume<R, F>(self, _timestamp: Instant, len: usize, f: F) -> Result<R> fn consume<R, F>(self, _timestamp: Instant, len: usize, f: F) -> Result<R>
where F: FnOnce(&mut [u8]) -> Result<R> { where
F: FnOnce(&mut [u8]) -> Result<R>,
{
let result = f(unsafe { self.0.buf_as_slice_mut(len) }); let result = f(unsafe { self.0.buf_as_slice_mut(len) });
self.0.buf_release(); self.0.buf_release();
result result

View File

@ -12,7 +12,7 @@ pub enum Error {
// Address not ACKd within a reasonable time (no device present?) // Address not ACKd within a reasonable time (no device present?)
Timeout, Timeout,
// Unexpected NACK during transfer // Unexpected NACK during transfer
NAck NAck,
} }
// Maximum number of times to retry NACKed address phase before timing out // Maximum number of times to retry NACKed address phase before timing out
@ -20,25 +20,28 @@ pub enum Error {
// EEPROMs during write) // EEPROMs during write)
const N_RETRY: usize = 100; // ~ 10ms @ 100 kHz bus clock const N_RETRY: usize = 100; // ~ 10ms @ 100 kHz bus clock
pub fn setup(i2c: &pac::I2C2) { pub fn setup(i2c: &pac::I2C2) {
// Disable the peripheral before setting timings // Disable the peripheral before setting timings
i2c.cr1.modify(|_, w| w.pe().clear_bit()); i2c.cr1.modify(|_, w| w.pe().clear_bit());
// Values from STM32MXCube for 100 kHz I2C clock with 100 MHz peripheral clock // Values from STM32MXCube for 100 kHz I2C clock with 100 MHz peripheral clock
i2c.timingr.modify( |_,w| i2c.timingr.modify(|_, w| {
w.presc().bits(1) w.presc()
.scldel().bits(0x12) .bits(1)
.sdadel().bits(0) .scldel()
.sclh().bits(0xec) .bits(0x12)
.scll().bits(0xff) .sdadel()
); .bits(0)
.sclh()
.bits(0xec)
.scll()
.bits(0xff)
});
// Enable the peripheral // Enable the peripheral
i2c.cr1.write(|w| w.pe().set_bit()); i2c.cr1.write(|w| w.pe().set_bit());
} }
// Busy-wait for a flag to be asserted, erroring out on unrecoverable problems // Busy-wait for a flag to be asserted, erroring out on unrecoverable problems
macro_rules! busy_wait_errors { macro_rules! busy_wait_errors {
($i2c:expr, $flag:ident) => { ($i2c:expr, $flag:ident) => {
@ -58,25 +61,29 @@ macro_rules! busy_wait_errors {
}; };
} }
fn poll_for_start_ack( fn poll_for_start_ack(
i2c: &pac::I2C2, i2c: &pac::I2C2,
addr: u8, addr: u8,
r_wn: bool, r_wn: bool,
data_len: usize, data_len: usize,
autoend: bool, autoend: bool,
start: bool start: bool,
) -> Result<(), Error> ) -> Result<(), Error> {
{
for _i in 0..N_RETRY { for _i in 0..N_RETRY {
// START and prepare to send `data_len` // START and prepare to send `data_len`
i2c.cr2.write(|w| { i2c.cr2.write(|w| {
w.start().bit(start) w.start()
.sadd().bits(addr as u16) .bit(start)
.add10().clear_bit() .sadd()
.rd_wrn().bit(r_wn) .bits(addr as u16)
.nbytes().bits( data_len as u8 ) .add10()
.autoend().bit(autoend) .clear_bit()
.rd_wrn()
.bit(r_wn)
.nbytes()
.bits(data_len as u8)
.autoend()
.bit(autoend)
}); });
loop { loop {
@ -87,7 +94,7 @@ fn poll_for_start_ack(
} else if isr.arlo().bit_is_set() { } else if isr.arlo().bit_is_set() {
return Err(Error::Arbitration); return Err(Error::Arbitration);
} else if isr.nackf().bit_is_set() { } else if isr.nackf().bit_is_set() {
i2c.icr.write(|w| { w.nackcf().set_bit() }); i2c.icr.write(|w| w.nackcf().set_bit());
// Wait to finish handling NACK-STOP // Wait to finish handling NACK-STOP
loop { loop {
if i2c.isr.read().busy().bit_is_clear() { if i2c.isr.read().busy().bit_is_clear() {
@ -96,7 +103,7 @@ fn poll_for_start_ack(
} }
break; break;
} else if isr.txis().bit_is_set() || isr.rxne().bit_is_set() { } else if isr.txis().bit_is_set() || isr.rxne().bit_is_set() {
return Ok(()) return Ok(());
} }
} }
} }
@ -104,7 +111,6 @@ fn poll_for_start_ack(
Err(Error::Timeout) Err(Error::Timeout)
} }
pub fn write_read( pub fn write_read(
i2c: &pac::I2C2, i2c: &pac::I2C2,
addr: u8, addr: u8,

View File

@ -1,5 +1,5 @@
use core::ops::{Add, Mul}; use core::ops::{Add, Mul};
use serde::{Serialize, Deserialize}; use serde::{Deserialize, Serialize};
use core::f32; use core::f32;
@ -14,7 +14,11 @@ pub struct IIR {
} }
fn abs(x: f32) -> f32 { fn abs(x: f32) -> f32 {
if x >= 0. { x } else { -x } if x >= 0. {
x
} else {
-x
}
} }
fn copysign(x: f32, y: f32) -> f32 { fn copysign(x: f32, y: f32) -> f32 {
@ -26,34 +30,48 @@ fn copysign(x: f32, y: f32) -> f32 {
} }
fn max(x: f32, y: f32) -> f32 { fn max(x: f32, y: f32) -> f32 {
if x > y { x } else { y } if x > y {
x
} else {
y
}
} }
fn min(x: f32, y: f32) -> f32 { fn min(x: f32, y: f32) -> f32 {
if x < y { x } else { y } if x < y {
x
} else {
y
}
} }
fn macc<T>(y0: T, x: &[T], a: &[T]) -> T fn macc<T>(y0: T, x: &[T], a: &[T]) -> T
where T: Add<Output=T> + Mul<Output=T> + Copy where
T: Add<Output = T> + Mul<Output = T> + Copy,
{ {
x.iter().zip(a.iter()).map(|(&i, &j)| i * j).fold(y0, |y, xa| y + xa) x.iter()
.zip(a.iter())
.map(|(&i, &j)| i * j)
.fold(y0, |y, xa| y + xa)
} }
impl IIR { impl IIR {
pub fn set_pi(&mut self, kp: f32, ki: f32, g: f32) -> Result<(), &str> { pub fn set_pi(&mut self, kp: f32, ki: f32, g: f32) -> Result<(), &str> {
let ki = copysign(ki, kp); let ki = copysign(ki, kp);
let g = copysign(g, kp); let g = copysign(g, kp);
let (a1, b0, b1) = let (a1, b0, b1) = if abs(ki) < f32::EPSILON {
if abs(ki) < f32::EPSILON {
(0., kp, 0.) (0., kp, 0.)
} else { } else {
let c = if abs(g) < f32::EPSILON { 1. } let c = if abs(g) < f32::EPSILON {
else { 1./(1. + ki/g) }; 1.
} else {
1. / (1. + ki / g)
};
let a1 = 2. * c - 1.; let a1 = 2. * c - 1.;
let b0 = ki * c + kp; let b0 = ki * c + kp;
let b1 = ki * c - a1 * kp; let b1 = ki * c - a1 * kp;
if abs(b0 + b1) < f32::EPSILON { if abs(b0 + b1) < f32::EPSILON {
return Err("low integrator gain and/or gain limit") return Err("low integrator gain and/or gain limit");
} }
(a1, b0, b1) (a1, b0, b1)
}; };

View File

@ -1,6 +1,5 @@
#![deny(warnings)] #![deny(warnings)]
#![allow(clippy::missing_safety_doc)] #![allow(clippy::missing_safety_doc)]
#![no_std] #![no_std]
#![no_main] #![no_main]
#![cfg_attr(feature = "nightly", feature(asm))] #![cfg_attr(feature = "nightly", feature(asm))]
@ -14,7 +13,9 @@
fn panic(_info: &core::panic::PanicInfo) -> ! { fn panic(_info: &core::panic::PanicInfo) -> ! {
let gpiod = unsafe { &*pac::GPIOD::ptr() }; let gpiod = unsafe { &*pac::GPIOD::ptr() };
gpiod.odr.modify(|_, w| w.odr6().high().odr12().high()); // FP_LED_1, FP_LED_3 gpiod.odr.modify(|_, w| w.odr6().high().odr12().high()); // FP_LED_1, FP_LED_3
unsafe { core::intrinsics::abort(); } unsafe {
core::intrinsics::abort();
}
} }
#[cfg(feature = "semihosting")] #[cfg(feature = "semihosting")]
@ -30,40 +31,38 @@ use core::ptr;
// use core::sync::atomic::{AtomicU32, AtomicBool, Ordering}; // use core::sync::atomic::{AtomicU32, AtomicBool, Ordering};
use core::fmt::Write; use core::fmt::Write;
use cortex_m_rt::exception; use cortex_m_rt::exception;
use stm32h7::stm32h743 as pac; use heapless::{consts::*, String, Vec};
use heapless::{String, Vec, consts::*};
use rtfm::cyccnt::{Instant, U32Ext as _}; use rtfm::cyccnt::{Instant, U32Ext as _};
use stm32h7::stm32h743 as pac;
use smoltcp as net; use smoltcp as net;
use serde::{Serialize, Deserialize, de::DeserializeOwned}; use serde::{de::DeserializeOwned, Deserialize, Serialize};
use serde_json_core::{ser::to_string, de::from_slice}; use serde_json_core::{de::from_slice, ser::to_string};
mod eth; mod eth;
mod iir; mod iir;
use iir::*; use iir::*;
mod i2c;
mod eeprom;
mod board; mod board;
mod eeprom;
mod i2c;
#[cfg(not(feature = "semihosting"))] #[cfg(not(feature = "semihosting"))]
fn init_log() {} fn init_log() {}
#[cfg(feature = "semihosting")] #[cfg(feature = "semihosting")]
fn init_log() { fn init_log() {
use cortex_m_log::log::{init as init_log, Logger};
use cortex_m_log::printer::semihosting::{hio::HStdout, InterruptOk};
use log::LevelFilter; use log::LevelFilter;
use cortex_m_log::log::{Logger, init as init_log};
use cortex_m_log::printer::semihosting::{InterruptOk, hio::HStdout};
static mut LOGGER: Option<Logger<InterruptOk<HStdout>>> = None; static mut LOGGER: Option<Logger<InterruptOk<HStdout>>> = None;
let logger = Logger { let logger = Logger {
inner: InterruptOk::<_>::stdout().unwrap(), inner: InterruptOk::<_>::stdout().unwrap(),
level: LevelFilter::Info, level: LevelFilter::Info,
}; };
let logger = unsafe { let logger = unsafe { LOGGER.get_or_insert(logger) };
LOGGER.get_or_insert(logger)
};
init_log(logger).unwrap(); init_log(logger).unwrap();
} }
@ -74,7 +73,6 @@ mod build_info {
// include!(concat!(env!("OUT_DIR"), "/built.rs")); // include!(concat!(env!("OUT_DIR"), "/built.rs"));
} }
const SCALE: f32 = ((1 << 15) - 1) as f32; const SCALE: f32 = ((1 << 15) - 1) as f32;
// static ETHERNET_PENDING: AtomicBool = AtomicBool::new(true); // static ETHERNET_PENDING: AtomicBool = AtomicBool::new(true);
@ -83,14 +81,17 @@ const TCP_RX_BUFFER_SIZE: usize = 8192;
const TCP_TX_BUFFER_SIZE: usize = 8192; const TCP_TX_BUFFER_SIZE: usize = 8192;
macro_rules! create_socket { macro_rules! create_socket {
($set:ident, $rx_storage:ident, $tx_storage:ident, $target:ident) => ( ($set:ident, $rx_storage:ident, $tx_storage:ident, $target:ident) => {
let mut $rx_storage = [0; TCP_RX_BUFFER_SIZE]; let mut $rx_storage = [0; TCP_RX_BUFFER_SIZE];
let mut $tx_storage = [0; TCP_TX_BUFFER_SIZE]; let mut $tx_storage = [0; TCP_TX_BUFFER_SIZE];
let tcp_rx_buffer = net::socket::TcpSocketBuffer::new(&mut $rx_storage[..]); let tcp_rx_buffer =
let tcp_tx_buffer = net::socket::TcpSocketBuffer::new(&mut $tx_storage[..]); net::socket::TcpSocketBuffer::new(&mut $rx_storage[..]);
let tcp_socket = net::socket::TcpSocket::new(tcp_rx_buffer, tcp_tx_buffer); let tcp_tx_buffer =
net::socket::TcpSocketBuffer::new(&mut $tx_storage[..]);
let tcp_socket =
net::socket::TcpSocket::new(tcp_rx_buffer, tcp_tx_buffer);
let $target = $set.add(tcp_socket); let $target = $set.add(tcp_socket);
) };
} }
#[rtfm::app(device = stm32h7::stm32h743, peripherals = true, monotonic = rtfm::cyccnt::CYCCNT)] #[rtfm::app(device = stm32h7::stm32h743, peripherals = true, monotonic = rtfm::cyccnt::CYCCNT)]
@ -98,7 +99,8 @@ const APP: () = {
struct Resources { struct Resources {
spi: (pac::SPI1, pac::SPI2, pac::SPI4, pac::SPI5), spi: (pac::SPI1, pac::SPI2, pac::SPI4, pac::SPI5),
i2c: pac::I2C2, i2c: pac::I2C2,
ethernet_periph: (pac::ETHERNET_MAC, pac::ETHERNET_DMA, pac::ETHERNET_MTL), ethernet_periph:
(pac::ETHERNET_MAC, pac::ETHERNET_DMA, pac::ETHERNET_MTL),
#[init([[0.; 5]; 2])] #[init([[0.; 5]; 2])]
iir_state: [IIRState; 2], iir_state: [IIRState; 2],
#[init([IIR { ba: [1., 0., 0., 0., 0.], y_offset: 0., y_min: -SCALE - 1., y_max: SCALE }; 2])] #[init([IIR { ba: [1., 0., 0., 0., 0.], y_offset: 0., y_min: -SCALE - 1., y_max: SCALE }; 2])]
@ -123,7 +125,11 @@ const APP: () = {
init::LateResources { init::LateResources {
spi: (dp.SPI1, dp.SPI2, dp.SPI4, dp.SPI5), spi: (dp.SPI1, dp.SPI2, dp.SPI4, dp.SPI5),
i2c: dp.I2C2, i2c: dp.I2C2,
ethernet_periph: (dp.ETHERNET_MAC, dp.ETHERNET_DMA, dp.ETHERNET_MTL), ethernet_periph: (
dp.ETHERNET_MAC,
dp.ETHERNET_DMA,
dp.ETHERNET_MTL,
),
} }
} }
@ -135,23 +141,26 @@ const APP: () = {
Err(_) => { Err(_) => {
info!("Could not read EEPROM, using default MAC address"); info!("Could not read EEPROM, using default MAC address");
net::wire::EthernetAddress([0x10, 0xE2, 0xD5, 0x00, 0x03, 0x00]) net::wire::EthernetAddress([0x10, 0xE2, 0xD5, 0x00, 0x03, 0x00])
}, }
Ok(raw_mac) => net::wire::EthernetAddress(raw_mac) Ok(raw_mac) => net::wire::EthernetAddress(raw_mac),
}; };
info!("MAC: {}", hardware_addr); info!("MAC: {}", hardware_addr);
unsafe { c.resources.ethernet.init(hardware_addr, MAC, DMA, MTL) }; unsafe { c.resources.ethernet.init(hardware_addr, MAC, DMA, MTL) };
let mut neighbor_cache_storage = [None; 8]; let mut neighbor_cache_storage = [None; 8];
let neighbor_cache = net::iface::NeighborCache::new(&mut neighbor_cache_storage[..]); let neighbor_cache =
net::iface::NeighborCache::new(&mut neighbor_cache_storage[..]);
let local_addr = net::wire::IpAddress::v4(10, 0, 16, 99); let local_addr = net::wire::IpAddress::v4(10, 0, 16, 99);
let mut ip_addrs = [net::wire::IpCidr::new(local_addr, 24)]; let mut ip_addrs = [net::wire::IpCidr::new(local_addr, 24)];
let mut iface = net::iface::EthernetInterfaceBuilder::new(c.resources.ethernet) let mut iface =
net::iface::EthernetInterfaceBuilder::new(c.resources.ethernet)
.ethernet_addr(hardware_addr) .ethernet_addr(hardware_addr)
.neighbor_cache(neighbor_cache) .neighbor_cache(neighbor_cache)
.ip_addrs(&mut ip_addrs[..]) .ip_addrs(&mut ip_addrs[..])
.finalize(); .finalize();
let mut socket_set_entries: [_; 8] = Default::default(); let mut socket_set_entries: [_; 8] = Default::default();
let mut sockets = net::socket::SocketSet::new(&mut socket_set_entries[..]); let mut sockets =
net::socket::SocketSet::new(&mut socket_set_entries[..]);
create_socket!(sockets, tcp_rx_storage0, tcp_tx_storage0, tcp_handle0); create_socket!(sockets, tcp_rx_storage0, tcp_tx_storage0, tcp_handle0);
create_socket!(sockets, tcp_rx_storage0, tcp_tx_storage0, tcp_handle1); create_socket!(sockets, tcp_rx_storage0, tcp_tx_storage0, tcp_handle1);
@ -170,41 +179,55 @@ const APP: () = {
time += 1; time += 1;
} }
{ {
let socket = &mut *sockets.get::<net::socket::TcpSocket>(tcp_handle0); let socket =
&mut *sockets.get::<net::socket::TcpSocket>(tcp_handle0);
if socket.state() == net::socket::TcpState::CloseWait { if socket.state() == net::socket::TcpState::CloseWait {
socket.close(); socket.close();
} else if !(socket.is_open() || socket.is_listening()) { } else if !(socket.is_open() || socket.is_listening()) {
socket.listen(1234).unwrap_or_else(|e| warn!("TCP listen error: {:?}", e)); socket
.listen(1234)
.unwrap_or_else(|e| warn!("TCP listen error: {:?}", e));
} else if tick && socket.can_send() { } else if tick && socket.can_send() {
let s = iir_state.lock(|iir_state| Status { let s = iir_state.lock(|iir_state| Status {
t: time, t: time,
x0: iir_state[0][0], x0: iir_state[0][0],
y0: iir_state[0][2], y0: iir_state[0][2],
x1: iir_state[1][0], x1: iir_state[1][0],
y1: iir_state[1][2] y1: iir_state[1][2],
}); });
json_reply(socket, &s); json_reply(socket, &s);
} }
} }
{ {
let socket = &mut *sockets.get::<net::socket::TcpSocket>(tcp_handle1); let socket =
&mut *sockets.get::<net::socket::TcpSocket>(tcp_handle1);
if socket.state() == net::socket::TcpState::CloseWait { if socket.state() == net::socket::TcpState::CloseWait {
socket.close(); socket.close();
} else if !(socket.is_open() || socket.is_listening()) { } else if !(socket.is_open() || socket.is_listening()) {
socket.listen(1235).unwrap_or_else(|e| warn!("TCP listen error: {:?}", e)); socket
.listen(1235)
.unwrap_or_else(|e| warn!("TCP listen error: {:?}", e));
} else { } else {
server.poll(socket, |req: &Request| { server.poll(socket, |req: &Request| {
if req.channel < 2 { if req.channel < 2 {
iir_ch.lock(|iir_ch| iir_ch[req.channel as usize] = req.iir); iir_ch.lock(|iir_ch| {
iir_ch[req.channel as usize] = req.iir
});
} }
}); });
} }
} }
if !match iface.poll(&mut sockets, net::time::Instant::from_millis(time as i64)) { if !match iface.poll(
&mut sockets,
net::time::Instant::from_millis(time as i64),
) {
Ok(changed) => changed, Ok(changed) => changed,
Err(net::Error::Unrecognized) => true, Err(net::Error::Unrecognized) => true,
Err(e) => { info!("iface poll error: {:?}", e); true } Err(e) => {
info!("iface poll error: {:?}", e);
true
}
} { } {
// cortex_m::asm::wfi(); // cortex_m::asm::wfi();
} }
@ -296,7 +319,7 @@ struct Status {
x0: f32, x0: f32,
y0: f32, y0: f32,
x1: f32, x1: f32,
y1: f32 y1: f32,
} }
fn json_reply<T: Serialize>(socket: &mut net::socket::TcpSocket, msg: &T) { fn json_reply<T: Serialize>(socket: &mut net::socket::TcpSocket, msg: &T) {
@ -312,17 +335,26 @@ struct Server {
impl Server { impl Server {
fn new() -> Self { fn new() -> Self {
Self { data: Vec::new(), discard: false } Self {
data: Vec::new(),
discard: false,
}
} }
fn poll<T, F, R>(&mut self, socket: &mut net::socket::TcpSocket, f: F) -> Option<R> fn poll<T, F, R>(
&mut self,
socket: &mut net::socket::TcpSocket,
f: F,
) -> Option<R>
where where
T: DeserializeOwned, T: DeserializeOwned,
F: FnOnce(&T) -> R, F: FnOnce(&T) -> R,
{ {
while socket.can_recv() { while socket.can_recv() {
let found = socket.recv(|buf| { let found = socket
let (len, found) = match buf.iter().position(|&c| c as char == '\n') { .recv(|buf| {
let (len, found) =
match buf.iter().position(|&c| c as char == '\n') {
Some(end) => (end + 1, true), Some(end) => (end + 1, true),
None => (buf.len(), false), None => (buf.len(), false),
}; };
@ -333,11 +365,18 @@ impl Server {
self.data.extend_from_slice(&buf[..len]).unwrap(); self.data.extend_from_slice(&buf[..len]).unwrap();
} }
(len, found) (len, found)
}).unwrap(); })
.unwrap();
if found { if found {
if self.discard { if self.discard {
self.discard = false; self.discard = false;
json_reply(socket, &Response { code: 520, message: "command buffer overflow" }); json_reply(
socket,
&Response {
code: 520,
message: "command buffer overflow",
},
);
self.data.clear(); self.data.clear();
} else { } else {
let r = from_slice::<T>(&self.data[..self.data.len() - 1]); let r = from_slice::<T>(&self.data[..self.data.len() - 1]);
@ -345,13 +384,25 @@ impl Server {
match r { match r {
Ok(res) => { Ok(res) => {
let r = f(&res); let r = f(&res);
json_reply(socket, &Response { code: 200, message: "ok" }); json_reply(
return Some(r); socket,
&Response {
code: 200,
message: "ok",
}, },
);
return Some(r);
}
Err(err) => { Err(err) => {
warn!("parse error {:?}", err); warn!("parse error {:?}", err);
json_reply(socket, &Response { code: 550, message: "parse error" }); json_reply(
socket,
&Response {
code: 550,
message: "parse error",
}, },
);
}
} }
} }
} }