Skip to content

Commit af97ae7

Browse files
author
Johannes Cornelis Draaijer
committed
Add ability to configure PPS pin
1 parent 2354f43 commit af97ae7

File tree

9 files changed

+120
-11
lines changed

9 files changed

+120
-11
lines changed

examples/arp.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ fn main() -> ! {
4141

4242
defmt::info!("Enabling ethernet...");
4343

44-
let (eth_pins, mdio, mdc) = common::setup_pins(gpio);
44+
let (eth_pins, mdio, mdc, _) = common::setup_pins(gpio);
4545

4646
let mut rx_ring: [RxRingEntry; 2] = Default::default();
4747
let mut tx_ring: [TxRingEntry; 2] = Default::default();

examples/common.rs

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -133,12 +133,19 @@ mod pins {
133133
pub type Mdio = PA2<Alternate<11>>;
134134
pub type Mdc = PC1<Alternate<11>>;
135135

136+
#[cfg(not(pps = "alternate"))]
137+
pub type Pps = PB5<Output<PushPull>>;
138+
139+
#[cfg(pps = "alternate")]
140+
pub type Pps = PG8<Output<PushPull>>;
141+
136142
pub fn setup_pins(
137143
gpio: Gpio,
138144
) -> (
139145
EthPins<RefClk, Crs, TxEn, TxD0, TxD1, RxD0, RxD1>,
140146
Mdio,
141147
Mdc,
148+
Pps,
142149
) {
143150
#[allow(unused_variables)]
144151
let Gpio {
@@ -183,6 +190,11 @@ mod pins {
183190
gpioc.pc1.into_alternate().set_speed(Speed::VeryHigh),
184191
);
185192

193+
#[cfg(not(pps = "alternate"))]
194+
let pps = gpiob.pb5.into_push_pull_output();
195+
#[cfg(pps = "alternate")]
196+
let pps = gpiog.pg8.into_push_pull_output();
197+
186198
(
187199
EthPins {
188200
ref_clk,
@@ -195,6 +207,7 @@ mod pins {
195207
},
196208
mdio,
197209
mdc,
210+
pps,
198211
)
199212
}
200213
}
@@ -223,12 +236,15 @@ mod pins {
223236
pub type Mdio = PA2<Alternate<PushPull>>;
224237
pub type Mdc = PC1<Alternate<PushPull>>;
225238

239+
pub type Pps = PB5<Output<PushPull>>;
240+
226241
pub fn setup_pins(
227242
gpio: Gpio,
228243
) -> (
229244
EthPins<RefClk, Crs, TxEn, TxD0, TxD1, RxD0, RxD1>,
230245
Mdio,
231246
Mdc,
247+
Pps,
232248
) {
233249
let Gpio {
234250
mut gpioa,
@@ -248,6 +264,8 @@ mod pins {
248264
let tx_d0 = gpiob.pb12.into_alternate_push_pull(&mut gpiob.crh);
249265
let tx_d1 = gpiob.pb13.into_alternate_push_pull(&mut gpiob.crh);
250266

267+
let pps = gpiob.pb5.into_push_pull_output(&mut gpiob.crl);
268+
251269
let pins = EthPins {
252270
ref_clk,
253271
crs,
@@ -258,7 +276,7 @@ mod pins {
258276
rx_d1,
259277
};
260278

261-
(pins, mdio, mdc)
279+
(pins, mdio, mdc, pps)
262280
}
263281
}
264282

examples/ip.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ fn main() -> ! {
4343

4444
defmt::info!("Enabling ethernet...");
4545

46-
let (eth_pins, _mdio, _mdc) = common::setup_pins(gpio);
46+
let (eth_pins, _mdio, _mdc, _) = common::setup_pins(gpio);
4747

4848
let mut rx_ring: [RxRingEntry; 2] = Default::default();
4949
let mut tx_ring: [TxRingEntry; 2] = Default::default();

examples/pktgen.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ fn main() -> ! {
4040
setup_systick(&mut cp.SYST);
4141

4242
defmt::info!("Enabling ethernet...");
43-
let (eth_pins, mdio, mdc) = common::setup_pins(gpio);
43+
let (eth_pins, mdio, mdc, _) = common::setup_pins(gpio);
4444

4545
let mut rx_ring: [RxRingEntry; 2] = Default::default();
4646
let mut tx_ring: [TxRingEntry; 2] = Default::default();

examples/rtic-echo.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,7 @@ mod app {
7878
let mono = Systick::new(core.SYST, clocks.hclk().raw());
7979

8080
defmt::info!("Setting up pins");
81-
let (pins, mdio, mdc) = crate::common::setup_pins(gpio);
81+
let (pins, mdio, mdc, _) = crate::common::setup_pins(gpio);
8282

8383
defmt::info!("Configuring ethernet");
8484

examples/rtic-timestamp.rs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -79,13 +79,15 @@ mod app {
7979
let mono = Systick::new(core.SYST, clocks.hclk().raw());
8080

8181
defmt::info!("Setting up pins");
82-
let (pins, mdio, mdc) = crate::common::setup_pins(gpio);
82+
let (pins, mdio, mdc, pps) = crate::common::setup_pins(gpio);
8383

8484
defmt::info!("Configuring ethernet");
8585

86-
let Parts { dma, mac, ptp } =
86+
let Parts { dma, mac, mut ptp } =
8787
stm32_eth::new_with_mii(ethernet, rx_ring, tx_ring, clocks, pins, mdio, mdc).unwrap();
8888

89+
ptp.enable_pps(pps);
90+
8991
defmt::info!("Enabling interrupts");
9092
dma.enable_interrupt();
9193

src/ptp/mod.rs

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,9 @@ pub use timestamp::Timestamp;
1010
mod subseconds;
1111
pub use subseconds::{Subseconds, NANOS_PER_SECOND, SUBSECONDS_PER_SECOND, SUBSECONDS_TO_SECONDS};
1212

13+
mod pps_pin;
14+
pub use pps_pin::PPSPin;
15+
1316
/// Access to the IEEE 1508v2 PTP peripheral present on the ethernet peripheral.
1417
///
1518
/// On STM32FXXX's, the PTP peripheral has/uses the following important parts:
@@ -191,6 +194,14 @@ impl EthernetPTP {
191194
}
192195
}
193196
}
197+
198+
/// Enable the PPS output on the provided pin.
199+
pub fn enable_pps<P>(&mut self, pin: P) -> P::Output
200+
where
201+
P: PPSPin,
202+
{
203+
pin.enable()
204+
}
194205
}
195206

196207
/// Setting and configuring target time interrupts on the STM32F107 does not
@@ -230,6 +241,22 @@ impl EthernetPTP {
230241
}
231242
is_tsint
232243
}
244+
245+
/// Configure the PPS output frequency.
246+
///
247+
/// The PPS output frequency becomes `2 ^ pps_freq`. `pps_freq` is
248+
/// clamped to `[0..31]`.
249+
pub fn set_pps_freq(&mut self, pps_freq: u8) {
250+
let pps_freq = pps_freq.max(31);
251+
252+
// SAFETY: we atomically write to the PTPPPSCR register, which is
253+
// not read or written to anywhere else. The SVD files are incorrectly
254+
// saying that the bits in this register are read-only.
255+
unsafe {
256+
let ptpppscr = self.eth_ptp.ptpppscr.as_ptr() as *mut u32;
257+
core::ptr::write_volatile(ptpppscr, pps_freq as u32);
258+
}
259+
}
233260
}
234261

235262
#[cfg(all(test, not(target_os = "none")))]

src/ptp/pps_pin.rs

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
/// Pins that can be used as PPS output
2+
///
3+
/// SAFETY: only pins that are capable of being a PPS output according
4+
/// to the datasheets of respective parts may implement this trait.
5+
pub unsafe trait PPSPin {
6+
/// The output type of this pin, in which it acts as a PPS output.
7+
type Output;
8+
9+
/// Enable the PPS output.
10+
fn enable(self) -> Self::Output;
11+
}
12+
13+
#[allow(unused_macros)]
14+
macro_rules! impl_pps_pin {
15+
($([$name:ty, $output:ty]),*) => {
16+
$(
17+
unsafe impl super::PPSPin for $name {
18+
type Output = $output;
19+
20+
fn enable(self) -> Self::Output {
21+
self.into_alternate()
22+
}
23+
}
24+
)*
25+
};
26+
}
27+
28+
#[cfg(feature = "stm32f4xx-hal")]
29+
mod impl_pps_pin {
30+
use crate::hal::gpio::{Alternate, Output, PushPull, PB5, PG8};
31+
32+
impl_pps_pin!([PG8<Output<PushPull>>, PG8<Alternate<11>>], [PB5<Output<PushPull>>, PB5<Alternate<11>>]);
33+
}
34+
35+
#[cfg(feature = "stm32f7xx-hal")]
36+
mod impl_pps_pin {
37+
use crate::hal::gpio::{Alternate, Output, PushPull, PB5, PG8};
38+
39+
impl_pps_pin!([PG8<Output<PushPull>>, PG8<Alternate<11>>], [PB5<Output<PushPull>>, PB5<Alternate<11>>]);
40+
}
41+
42+
#[cfg(feature = "stm32f1xx-hal")]
43+
mod impl_pps_pin {
44+
use crate::hal::gpio::{Alternate, Output, PushPull, PB5};
45+
46+
unsafe impl super::PPSPin for PB5<Output<PushPull>> {
47+
type Output = PB5<Alternate<PushPull>>;
48+
49+
fn enable(self) -> Self::Output {
50+
// Within this critical section, modifying the `CRL` register can
51+
// only be unsound if this critical section preempts other code
52+
// that is modifying the same register
53+
cortex_m::interrupt::free(|_| {
54+
// SAFETY: this is sound as long as the API of the HAL and structure of the CRL
55+
// struct does not change. In case the size of the `CRL` struct is changed, compilation
56+
// will fail as `mem::transmute` can only convert between types of the same size.
57+
//
58+
// This guards us from unsound behaviour introduced by point releases of the f1 hal
59+
let cr: &mut _ = &mut unsafe { core::mem::transmute(()) };
60+
// The speed can only be changed on output pins
61+
self.into_alternate_push_pull(cr)
62+
})
63+
}
64+
}
65+
}

src/setup.rs

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -305,10 +305,7 @@ macro_rules! impl_pins {
305305
};
306306
}
307307

308-
#[cfg(all(
309-
feature = "device-selected",
310-
any(feature = "stm32f4xx-hal", feature = "stm32f7xx-hal")
311-
))]
308+
#[cfg(any(feature = "stm32f4xx-hal", feature = "stm32f7xx-hal"))]
312309
impl_pins!(
313310
RmiiRefClk: [
314311
PA1<Input>,

0 commit comments

Comments
 (0)