Compare commits

...

4 Commits

Author SHA1 Message Date
Astro 09dbb7d495 add ad5680 2020-03-12 21:41:03 +01:00
Astro fed3e767e9 pins: setup dac spi 0,1 2020-03-12 19:25:21 +01:00
Astro 89b0d142ad main: use HSE clock
supposed to lead to more stable pwm
2020-03-12 18:32:07 +01:00
Astro f021ebd6e6 pins: setup PwmPins 2020-03-12 17:26:14 +01:00
5 changed files with 205 additions and 25 deletions

17
Cargo.lock generated
View File

@ -209,12 +209,6 @@ version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e2a38df5b15c8d5c7e8654189744d8e396bddc18ad48041a500ce52d6948941f"
[[package]]
name = "rand_core"
version = "0.5.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "90bde5296fc891b0cef12a6d03ddccc162ce7b2aff54160af9338f8d40df6d19"
[[package]]
name = "rustc_version"
version = "0.2.3"
@ -260,7 +254,6 @@ checksum = "dba1a27d3efae4351c8051072d619e3ade2820635c3958d826bfea39d59b54c8"
[[package]]
name = "stm32-eth"
version = "0.1.2"
source = "git+https://github.com/stm32-rs/stm32-eth.git#2c5dce379b85a31fb0b9c58a028b6454be1727aa"
dependencies = [
"aligned",
"log",
@ -271,9 +264,9 @@ dependencies = [
[[package]]
name = "stm32f4"
version = "0.10.0"
version = "0.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "44a3d6c58b14e63926273694e7dd644894513c5e35ce6928c4657ddb62cae976"
checksum = "88640ad08c62e0651a1320187f38c3655d025ed580a10f0e4d85a2cc4829069f"
dependencies = [
"bare-metal",
"cortex-m",
@ -283,9 +276,8 @@ dependencies = [
[[package]]
name = "stm32f4xx-hal"
version = "0.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "54abcca9b4abfb0d0518591ea39c2e14a0b07b9791548d4516ab5e61a83067cc"
version = "0.6.0"
source = "git+https://github.com/thalesfragoso/stm32f4xx-hal?branch=pwm-impl#ef939935b90581553dc03f9146d05510b3ceba58"
dependencies = [
"bare-metal",
"cast",
@ -293,7 +285,6 @@ dependencies = [
"cortex-m-rt",
"embedded-hal",
"nb",
"rand_core",
"stm32f4",
"void",
]

View File

@ -22,7 +22,8 @@ cortex-m = "0.6"
cortex-m-rt = { version = "0.6", features = ["device"] }
cortex-m-log = { version = "0.6", features = ["log-integration"] }
embedded-hal = "0.2"
stm32f4xx-hal = { version = "0.7", features = ["rt", "stm32f427"] }
# TODO: pending https://github.com/stm32-rs/stm32f4xx-hal/pull/125
stm32f4xx-hal = { git = "https://github.com/thalesfragoso/stm32f4xx-hal", branch = "pwm-impl", features = ["rt", "stm32f427"] }
stm32-eth = { version = "0.1.2", features = ["smoltcp-phy"], git = "https://github.com/stm32-rs/stm32-eth.git" }
smoltcp = { version = "0.6.0", default-features = false, features = ["proto-ipv4", "socket-tcp", "log"] }
hash2hwaddr = { version = "0.0", optional = true }

50
src/ad5680.rs Normal file
View File

@ -0,0 +1,50 @@
use embedded_hal::{
blocking::spi::Transfer,
digital::v2::OutputPin,
};
use stm32f4xx_hal::{
time::MegaHertz,
spi,
};
pub const SPI_MODE: spi::Mode = spi::Mode {
polarity: spi::Polarity::IdleHigh,
phase: spi::Phase::CaptureOnFirstTransition,
};
/// 30 MHz
pub const SPI_CLOCK: MegaHertz = MegaHertz(30);
/// [AD5680](https://www.analog.com/media/en/technical-documentation/data-sheets/AD5680.pdf) DAC
pub struct Dac<SPI: Transfer<u8>, S: OutputPin> {
spi: SPI,
sync: S,
}
impl<SPI: Transfer<u8>, S: OutputPin> Dac<SPI, S> {
pub fn new(spi: SPI, mut sync: S) -> Self {
let _ = sync.set_high();
Dac {
spi,
sync,
}
}
fn write(&mut self, mut buf: [u8; 3]) -> Result<(), SPI::Error> {
let _ = self.sync.set_low();
let result = self.spi.transfer(&mut buf);
let _ = self.sync.set_high();
result.map(|_| ())
}
/// value: `0..0x20_000`
pub fn set(&mut self, value: u32) -> Result<(), SPI::Error> {
let buf = [
(value >> 14) as u8,
(value >> 6) as u8,
(value << 2) as u8,
];
self.write(buf)
}
}

View File

@ -16,7 +16,7 @@ use embedded_hal::watchdog::{WatchdogEnable, Watchdog};
use stm32f4xx_hal::{
rcc::RccExt,
watchdog::IndependentWatchdog,
time::U32Ext,
time::{U32Ext, MegaHertz},
stm32::{CorePeripherals, Peripherals},
};
use smoltcp::{
@ -29,6 +29,7 @@ use init_log::init_log;
mod pins;
use pins::Pins;
mod ad7172;
mod ad5680;
mod net;
mod server;
use server::Server;
@ -49,6 +50,9 @@ const WATCHDOG_INTERVAL: u32 = 10_000;
const NET_HWADDR: [u8; 6] = [0x02, 0x00, 0xDE, 0xAD, 0xBE, 0xEF];
const HSE: MegaHertz = MegaHertz(8);
/// Initialization and main loop
#[entry]
fn main() -> ! {
@ -61,8 +65,10 @@ fn main() -> ! {
let dp = Peripherals::take().unwrap();
stm32_eth::setup(&dp.RCC, &dp.SYSCFG);
let clocks = dp.RCC.constrain()
.cfgr
.use_hse(HSE)
.sysclk(168.mhz())
.hclk(168.mhz())
.pclk1(32.mhz())
@ -73,9 +79,17 @@ fn main() -> ! {
wd.start(WATCHDOG_INTERVAL.ms());
wd.feed();
let pins = Pins::setup(clocks, dp.GPIOA, dp.GPIOB, dp.GPIOC, dp.GPIOG, dp.SPI2);
let pins = Pins::setup(
clocks, dp.TIM1, dp.TIM3,
dp.GPIOA, dp.GPIOB, dp.GPIOC, dp.GPIOE, dp.GPIOF, dp.GPIOG,
dp.SPI2, dp.SPI4, dp.SPI5
);
let mut adc = ad7172::Adc::new(pins.adc_spi, pins.adc_nss).unwrap();
let mut dac0 = ad5680::Dac::new(pins.dac0_spi, pins.dac0_sync);
dac0.set(0);
let mut dac1 = ad5680::Dac::new(pins.dac1_spi, pins.dac1_sync);
dac1.set(0);
timer::setup(cp.SYST, clocks);

View File

@ -1,34 +1,57 @@
use embedded_hal::{
blocking::spi::Transfer,
digital::v2::OutputPin,
};
use stm32f4xx_hal::{
gpio::{
AF5, Alternate,
gpioa::{PA1, PA2, PA7},
gpiob::{PB10, PB11, PB12, PB13, PB14, PB15},
gpioc::{PC1, PC4, PC5},
gpiog::{PG13},
gpioa::*,
gpiob::*,
gpioc::*,
gpioe::*,
gpiof::*,
gpiog::*,
GpioExt,
Output, PushPull,
Speed::VeryHigh,
},
rcc::Clocks,
spi::Spi,
stm32::{GPIOA, GPIOB, GPIOC, GPIOG, SPI2},
pwm::{self, PwmChannels},
spi::{self, Spi, NoMiso},
stm32::{GPIOA, GPIOB, GPIOC, GPIOE, GPIOF, GPIOG, SPI2, SPI4, SPI5, TIM1, TIM3},
time::{U32Ext, Hertz, MegaHertz},
};
/// SPI peripheral used for communication with the ADC
type AdcSpi = Spi<SPI2, (PB10<Alternate<AF5>>, PB14<Alternate<AF5>>, PB15<Alternate<AF5>>)>;
type Dac0Spi = Spi<SPI4, (PE2<Alternate<AF5>>, NoMiso, PE6<Alternate<AF5>>)>;
type Dac1Spi = Spi<SPI5, (PF7<Alternate<AF5>>, NoMiso, PF9<Alternate<AF5>>)>;
pub struct Pins {
pub adc_spi: AdcSpi,
pub adc_nss: PB12<Output<PushPull>>,
pub pwm: PwmPins,
pub dac0_spi: Dac0Spi,
pub dac0_sync: PE4<Output<PushPull>>,
pub dac1_spi: Dac1Spi,
pub dac1_sync: PF6<Output<PushPull>>,
}
impl Pins {
/// Setup GPIO pins and configure MCU peripherals
pub fn setup(clocks: Clocks, gpioa: GPIOA, gpiob: GPIOB, gpioc: GPIOC, gpiog: GPIOG, spi2: SPI2) -> Self {
pub fn setup(
clocks: Clocks,
tim1: TIM1,
tim3: TIM3,
gpioa: GPIOA, gpiob: GPIOB, gpioc: GPIOC, gpioe: GPIOE, gpiof: GPIOF, gpiog: GPIOG,
spi2: SPI2, spi4: SPI4, spi5: SPI5
) -> Self {
let gpioa = gpioa.split();
let gpiob = gpiob.split();
let gpioc = gpioc.split();
let gpioe = gpioe.split();
let gpiof = gpiof.split();
let gpiog = gpiog.split();
Self::setup_ethernet(
@ -38,9 +61,28 @@ impl Pins {
);
let adc_spi = Self::setup_spi_adc(clocks, spi2, gpiob.pb10, gpiob.pb14, gpiob.pb15);
let adc_nss = gpiob.pb12.into_push_pull_output();
let (dac0_spi, dac0_sync) = Self::setup_dac0(
clocks, spi4,
gpioe.pe2, gpioe.pe4, gpioe.pe6
);
let (dac1_spi, dac1_sync) = Self::setup_dac1(
clocks, spi5,
gpiof.pf7, gpiof.pf6, gpiof.pf9
);
let pwm = PwmPins::setup(
clocks, tim1, tim3,
gpioc.pc6, gpioc.pc7,
gpioe.pe9, gpioe.pe11,
gpioe.pe13, gpioe.pe14
);
Pins {
adc_spi,
adc_nss,
adc_spi, adc_nss,
pwm,
dac0_spi, dac0_sync,
dac1_spi, dac1_sync,
}
}
@ -65,6 +107,42 @@ impl Pins {
)
}
fn setup_dac0<M1, M2, M3>(
clocks: Clocks, spi4: SPI4,
sclk: PE2<M1>, sync: PE4<M2>, sdin: PE6<M3>
) -> (Dac0Spi, PE4<Output<PushPull>>) {
let sclk = sclk.into_alternate_af5();
let sdin = sdin.into_alternate_af5();
let spi = Spi::spi4(
spi4,
(sclk, NoMiso, sdin),
crate::ad5680::SPI_MODE,
crate::ad5680::SPI_CLOCK.into(),
clocks
);
let sync = sync.into_push_pull_output();
(spi, sync)
}
fn setup_dac1<M1, M2, M3>(
clocks: Clocks, spi5: SPI5,
sclk: PF7<M1>, sync: PF6<M2>, sdin: PF9<M3>
) -> (Dac1Spi, PF6<Output<PushPull>>) {
let sclk = sclk.into_alternate_af5();
let sdin = sdin.into_alternate_af5();
let spi = Spi::spi5(
spi5,
(sclk, NoMiso, sdin),
crate::ad5680::SPI_MODE,
crate::ad5680::SPI_CLOCK.into(),
clocks
);
let sync = sync.into_push_pull_output();
(spi, sync)
}
/// Configure the GPIO pins for Ethernet operation
fn setup_ethernet<M1, M2, M3, M4, M5, M6, M7, M8, M9>(
pa1: PA1<M1>, pa2: PA2<M2>, pc1: PC1<M3>, pa7: PA7<M4>,
@ -91,3 +169,49 @@ impl Pins {
pb13.into_alternate_af11().set_speed(VeryHigh);
}
}
pub struct PwmPins {
max_v0: PwmChannels<TIM3, pwm::C1>,
max_v1: PwmChannels<TIM3, pwm::C2>,
max_i_pos0: PwmChannels<TIM1, pwm::C1>,
max_i_pos1: PwmChannels<TIM1, pwm::C2>,
max_i_neg0: PwmChannels<TIM1, pwm::C3>,
max_i_neg1: PwmChannels<TIM1, pwm::C4>,
}
impl PwmPins {
fn setup<M1, M2, M3, M4, M5, M6>(
clocks: Clocks,
tim1: TIM1,
tim3: TIM3,
max_v0: PC6<M1>,
max_v1: PC7<M2>,
max_i_pos0: PE9<M3>,
max_i_pos1: PE11<M4>,
max_i_neg0: PE13<M5>,
max_i_neg1: PE14<M6>,
) -> PwmPins {
let freq = 20u32.khz();
let channels = (
max_v0.into_alternate_af2(),
max_v1.into_alternate_af2(),
);
let (max_v0, max_v1) = pwm::tim3(tim3, channels, clocks, freq);
let channels = (
max_i_pos0.into_alternate_af1(),
max_i_pos1.into_alternate_af1(),
max_i_neg0.into_alternate_af1(),
max_i_neg1.into_alternate_af1(),
);
let (max_i_pos0, max_i_pos1, max_i_neg0, max_i_neg1) =
pwm::tim1(tim1, channels, clocks, freq);
PwmPins {
max_v0, max_v1,
max_i_pos0, max_i_pos1,
max_i_neg0, max_i_neg1,
}
}
}