master
Robert Jördens 2019-03-19 15:27:22 +00:00
parent b9f27791ab
commit 4b49f29b17
4 changed files with 119 additions and 28 deletions

View File

@ -1,8 +1,6 @@
[target.thumbv7em-none-eabihf] [target.'cfg(all(target_arch = "arm", target_os = "none"))']
runner = "arm-none-eabi-gdb" runner = "arm-none-eabi-gdb -x openocd.gdb"
rustflags = [ rustflags = ["-C", "link-arg=-Tlink.x"]
"-C", "link-arg=-Tlink.x",
]
[build] [build]
target = "thumbv7em-none-eabihf" target = "thumbv7em-none-eabihf"

View File

@ -3,7 +3,7 @@ name = "stabilizer"
version = "0.1.0" version = "0.1.0"
authors = ["Robert Jördens <rj@quartiq.de>"] authors = ["Robert Jördens <rj@quartiq.de>"]
categories = ["embedded", "no-std"] categories = ["embedded", "no-std"]
license = "Apache-2.0" license = "GPL-3"
keywords = ["ethernet", "eth", "stm32", "adc", "dac", "tcp"] keywords = ["ethernet", "eth", "stm32", "adc", "dac", "tcp"]
repository = "https://github.com/quartiq/stabilizer" repository = "https://github.com/quartiq/stabilizer"
#documentation = "https://docs.rs/stabilizer/" #documentation = "https://docs.rs/stabilizer/"
@ -43,4 +43,4 @@ debug = true
lto = true lto = true
codegen-units = 1 codegen-units = 1
incremental = false incremental = false
opt-level = "s" opt-level = 2

View File

@ -6,6 +6,12 @@ monitor arm semihosting enable
# or uart # or uart
# monitor tpiu config external uart off 168000000 2000000 # monitor tpiu config external uart off 168000000 2000000
# monitor itm port 0 on # monitor itm port 0 on
# detect unhandled exceptions, hard faults and panics
break DefaultHandler
break HardFault
break rust_begin_unwind
load load
# tbreak cortex_m_rt::reset_handler # tbreak cortex_m_rt::reset_handler
# monitor reset halt # monitor reset halt

View File

@ -17,6 +17,7 @@ extern crate stm32h7;
#[macro_use] #[macro_use]
extern crate log; extern crate log;
use core::ptr;
use cortex_m_rt::{entry, exception}; use cortex_m_rt::{entry, exception};
// use core::fmt::Write; // use core::fmt::Write;
use stm32h7::{stm32h7x3 as stm32}; use stm32h7::{stm32h7x3 as stm32};
@ -102,13 +103,15 @@ fn main() -> ! {
rcc.cfgr.reset(); rcc.cfgr.reset();
// Ensure HSE is on and stable // Ensure HSE is on and stable
rcc.cr.modify(|_, w| w.hseon().set_bit()); rcc.cr.modify(|_, w|
w.hseon().set_bit()
.hsebyp().clear_bit());
while rcc.cr.read().hserdy().bit_is_clear() {} while rcc.cr.read().hserdy().bit_is_clear() {}
rcc.pllckselr.modify(|_, w| unsafe { rcc.pllckselr.modify(|_, w| unsafe {
w.pllsrc().bits(0b10) // hse w.pllsrc().bits(0b10) // hse
.divm1().bits(1) // ref prescaler .divm1().bits(1) // ref prescaler
.divm2().bits(4) // 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| unsafe { rcc.pllcfgr.modify(|_, w| unsafe {
@ -117,7 +120,7 @@ fn main() -> ! {
.pll1fracen().clear_bit() .pll1fracen().clear_bit()
.divp1en().set_bit() .divp1en().set_bit()
.pll2vcosel().set_bit() // 150-420 MHz VCO .pll2vcosel().set_bit() // 150-420 MHz VCO
.pll2rge().bits(0b01) // 2-4 MHz PFD .pll2rge().bits(0b11) // 8-16 MHz PFD
.pll2fracen().clear_bit() .pll2fracen().clear_bit()
.divp2en().set_bit() .divp2en().set_bit()
.divq2en().set_bit() .divq2en().set_bit()
@ -129,9 +132,9 @@ fn main() -> ! {
rcc.cr.modify(|_, w| w.pll1on().set_bit()); rcc.cr.modify(|_, w| w.pll1on().set_bit());
while rcc.cr.read().pll1rdy().bit_is_clear() {} while rcc.cr.read().pll1rdy().bit_is_clear() {}
// Configure PLL2: 8MHz /4 * 125 = 250 MHz // Configure PLL2: 8MHz /1 *25 / 2 = 100 MHz
rcc.pll2divr.write(|w| unsafe { rcc.pll2divr.write(|w| unsafe {
w.divn1().bits(125 - 1) // feebdack divider w.divn1().bits(25 - 1) // feebdack divider
.divp1().bits(2 - 1) // p output divider .divp1().bits(2 - 1) // p output divider
.divq1().bits(2 - 1) // q output divider .divq1().bits(2 - 1) // q output divider
}); });
@ -139,17 +142,19 @@ fn main() -> ! {
while rcc.cr.read().pll2rdy().bit_is_clear() {} while rcc.cr.read().pll2rdy().bit_is_clear() {}
// hclk 200 MHz, pclk 100 MHz // hclk 200 MHz, pclk 100 MHz
let dapb = 0b100;
rcc.d1cfgr.write(|w| unsafe { rcc.d1cfgr.write(|w| unsafe {
w.d1cpre().bits(0) // sys_ck not divided w.d1cpre().bits(0) // sys_ck not divided
.d1ppre().bits(0b100) // rcc_pclk3 = rcc_hclk3 / 2
.hpre().bits(0b1000) // rcc_hclk3 = sys_d1cpre_ck / 2 .hpre().bits(0b1000) // rcc_hclk3 = sys_d1cpre_ck / 2
.d1ppre().bits(dapb) // rcc_pclk3 = rcc_hclk3 / 2
}); });
rcc.d2cfgr.write(|w| unsafe { rcc.d2cfgr.write(|w| unsafe {
w.d2ppre1().bits(0b100) // rcc_pclk1 = rcc_hclk3 / 2 w.d2ppre1().bits(dapb) // rcc_pclk1 = rcc_hclk3 / 2
.d2ppre2().bits(0b100) // rcc_pclk2 = rcc_hclk3 / 2 .d2ppre2().bits(dapb) // rcc_pclk2 = rcc_hclk3 / 2
}); });
rcc.d3cfgr.write(|w| unsafe { rcc.d3cfgr.write(|w| unsafe {
w.d3ppre().bits(0b100) // rcc_pclk4 = rcc_hclk3 / 2 w.d3ppre().bits(dapb) // rcc_pclk4 = rcc_hclk3 / 2
}); });
let flash = dp.FLASH; let flash = dp.FLASH;
@ -161,7 +166,7 @@ fn main() -> ! {
}); });
while flash.acr.read().latency().bits() != 2 {} while flash.acr.read().latency().bits() != 2 {}
// Set system clock to HSI // Set system clock to pll1_p
rcc.cfgr.modify(|_, w| unsafe { w.sw().bits(0b011) }); // pll1p rcc.cfgr.modify(|_, w| unsafe { w.sw().bits(0b011) }); // pll1p
while rcc.cfgr.read().sws().bits() != 0b011 {} while rcc.cfgr.read().sws().bits() != 0b011 {}
@ -171,7 +176,7 @@ fn main() -> ! {
init_log(); init_log();
// info!("Version {} {}", build_info::PKG_VERSION, build_info::GIT_VERSION.unwrap()); // info!("Version {} {}", build_info::PKG_VERSION, build_info::GIT_VERSION.unwrap());
info!("Built on {}", build_info::BUILT_TIME_UTC); // info!("Built on {}", build_info::BUILT_TIME_UTC);
// info!("{} {}", build_info::RUSTC_VERSION, build_info::TARGET); // info!("{} {}", build_info::RUSTC_VERSION, build_info::TARGET);
// FP_LED0 // FP_LED0
@ -198,10 +203,14 @@ fn main() -> ! {
gpiod.moder.modify(|_, w| w.moder12().output()); gpiod.moder.modify(|_, w| w.moder12().output());
gpiod.odr.modify(|_, w| w.odr12().set_bit()); gpiod.odr.modify(|_, w| w.odr12().set_bit());
rcc.d1ccipr.write(|w| unsafe {
w.ckpersrc().bits(1) // hse_ck
});
rcc.d2ccip1r.modify(|_, w| unsafe { rcc.d2ccip1r.modify(|_, w| unsafe {
w.spi123src().bits(1) // pll2_p w.spi123src().bits(1) // pll2_p
.spi45src().bits(1) // pll2_q .spi45src().bits(1) // pll2_q
}); });
rcc.d3ccipr.modify(|_, w| unsafe { rcc.d3ccipr.modify(|_, w| unsafe {
w.spi6src().bits(1) // pll2_q w.spi6src().bits(1) // pll2_q
}); });
@ -244,6 +253,7 @@ fn main() -> ! {
// SCK: PG11 // SCK: PG11
gpiog.moder.modify(|_, w| w.moder11().alternate()); gpiog.moder.modify(|_, w| w.moder11().alternate());
gpiog.otyper.modify(|_, w| w.ot11().push_pull()); gpiog.otyper.modify(|_, w| w.ot11().push_pull());
gpiog.ospeedr.modify(|_, w| w.ospeedr11().very_high_speed());
gpiog.afrh.modify(|_, w| w.afr11().af5()); gpiog.afrh.modify(|_, w| w.afr11().af5());
// MOSI: PD7 // MOSI: PD7
// MISO: PA6 // MISO: PA6
@ -252,6 +262,7 @@ fn main() -> ! {
// NSS: PG10 // NSS: PG10
gpiog.moder.modify(|_, w| w.moder10().alternate()); gpiog.moder.modify(|_, w| w.moder10().alternate());
gpiog.otyper.modify(|_, w| w.ot10().push_pull()); gpiog.otyper.modify(|_, w| w.ot10().push_pull());
gpiog.ospeedr.modify(|_, w| w.ospeedr10().very_high_speed());
gpiog.afrh.modify(|_, w| w.afr10().af5()); gpiog.afrh.modify(|_, w| w.afr10().af5());
let spi1 = dp.SPI1; let spi1 = dp.SPI1;
@ -262,7 +273,69 @@ fn main() -> ! {
.fthvl().bits(1 - 1) // one data .fthvl().bits(1 - 1) // one data
}); });
spi1.cfg2.modify(|_, w| unsafe { spi1.cfg2.modify(|_, w| unsafe {
w.ssom().set_bit() // ss deassert between frames during midi w.afcntr().set_bit()
.ssom().set_bit() // ss deassert between frames during midi
.ssoe().set_bit() // ss output enable
.ssiop().clear_bit() // ss active low
.ssm().clear_bit() // PAD counts
.cpol().set_bit()
.cpha().set_bit()
.lsbfrst().clear_bit()
.master().set_bit()
.sp().bits(0) // motorola
.comm().bits(0b10) // simplex receiver
.ioswp().clear_bit()
.midi().bits(2) // master inter data idle
.mssi().bits(11) // master SS idle
});
spi1.cr2.modify(|_, w| unsafe {
w.tsize().bits(1)
});
spi1.cr1.write(|w| w.spe().set_bit());
let gpiob = dp.GPIOB;
rcc.ahb4enr.modify(|_, w| w.gpioben().set_bit());
// 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());
let gpioe = dp.GPIOE;
rcc.ahb4enr.modify(|_, w| w.gpioeen().set_bit());
// DAC0_LDAC: PE11
gpioe.moder.modify(|_, w| w.moder11().output());
gpioe.otyper.modify(|_, w| w.ot11().push_pull());
gpioe.odr.modify(|_, w| w.odr11().clear_bit());
// DAC_CLR: PE12
gpioe.moder.modify(|_, w| w.moder12().output());
gpioe.otyper.modify(|_, w| w.ot12().push_pull());
gpioe.odr.modify(|_, w| w.odr12().set_bit());
let spi2 = dp.SPI2;
rcc.apb1lrstr.write(|w| w.spi2rst().set_bit());
rcc.apb1lrstr.write(|w| w.spi2rst().clear_bit());
rcc.apb1lenr.modify(|_, w| w.spi2en().set_bit());
spi2.cfg1.modify(|_, w| unsafe {
w.mbr().bits(0) // clk/2
.dsize().bits(16 - 1)
.fthvl().bits(1 - 1) // one data
});
spi2.cfg2.modify(|_, w| unsafe {
w.afcntr().set_bit()
.ssom().set_bit() // ss deassert between frames during midi
.ssoe().set_bit() // ss output enable .ssoe().set_bit() // ss output enable
.ssiop().clear_bit() // ss active low .ssiop().clear_bit() // ss active low
.ssm().clear_bit() // PAD counts .ssm().clear_bit() // PAD counts
@ -271,25 +344,39 @@ fn main() -> ! {
.lsbfrst().clear_bit() .lsbfrst().clear_bit()
.master().set_bit() .master().set_bit()
.sp().bits(0) // motorola .sp().bits(0) // motorola
.comm().bits(0b10) // simplex receiver .comm().bits(0b01) // simplex transmitter
.ioswp().clear_bit() .ioswp().clear_bit()
.midi().bits(2) // master inter data idle .midi().bits(1) // master inter data idle
.mssi().bits(15) // master SS idle .mssi().bits(0) // master SS idle
}); });
spi1.cr2.modify(|_, w| unsafe { spi2.cr2.modify(|_, w| unsafe {
w.tsize().bits(1) w.tsize().bits(0)
}); });
spi1.cr1.write(|w| w.spe().set_bit()); spi2.cr1.write(|w| w.spe().set_bit());
spi2.cr1.modify(|r, w| unsafe { w.bits(r.bits() | (1 << 9)) });
// cortex_m::interrupt::free(|_cs| { });
loop { loop {
// cortex_m::interrupt::free(|_cs| { });
// spi1.cr1.write(|w| w.cstart().set_bit()); // spi1.cr1.write(|w| w.cstart().set_bit());
spi1.cr1.modify(|r, w| unsafe { w.bits(r.bits() | (1 << 9)) }); spi1.cr1.modify(|r, w| unsafe { w.bits(r.bits() | (1 << 9)) });
while spi1.sr.read().eot().bit_is_clear() {} while spi1.sr.read().eot().bit_is_clear() {}
spi1.ifcr.write(|w| w.eotc().set_bit()); spi1.ifcr.write(|w| w.eotc().set_bit());
while spi1.sr.read().rxp().bit_is_set() { while spi1.sr.read().rxp().bit_is_set() {
let a = spi1.rxdr.read().rxdr().bits() as i16; let a = spi1.rxdr.read().rxdr().bits() as i16;
info!("adc {}", a); let d = (a as u16) ^ 0x8000;
// while spi2.sr.read().txp().bit_is_clear() {}
// spi2.txdr.write(|w| unsafe { w.bits(d as u32) });
unsafe { ptr::write_volatile(&spi2.txdr as *const _ as *mut u16, d) };
// write(|w| unsafe { w.bits(d as u32) });
// while spi2.sr.read().txc().bit_is_clear() {}
// while spi2.sr.read().eot().bit_is_clear() {}
// spi2.ifcr.write(|w| w.eotc().set_bit());
info!("dac adc {:#x} cr1 {:#x} sr {:#x} cfg1 {:#x} cr2 {:#x}",
a,
spi2.cr1.read().bits(), spi2.sr.read().bits(),
spi2.cfg1.read().bits(), spi2.cr2.read().bits(),
);
} }
// cortex_m::asm::wfi(); // cortex_m::asm::wfi();
} }