Compare commits
4 Commits
ac336b7a26
...
09dbb7d495
Author | SHA1 | Date |
---|---|---|
Astro | 09dbb7d495 | |
Astro | fed3e767e9 | |
Astro | 89b0d142ad | |
Astro | f021ebd6e6 |
|
@ -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",
|
||||
]
|
||||
|
|
|
@ -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 }
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
}
|
18
src/main.rs
18
src/main.rs
|
@ -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);
|
||||
|
||||
|
|
142
src/pins.rs
142
src/pins.rs
|
@ -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,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue