Skip to content

Commit 6189a14

Browse files
committed
examples: set up MPU for all examples
It seems that (part of) the problem in #105 could, in fact, be caching. To prevent the examples from doing the same, we can set up the MPU to make all RAM regions non-cacheable.
1 parent 13e2991 commit 6189a14

11 files changed

Lines changed: 99 additions & 18 deletions

File tree

examples/arp.rs

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -35,17 +35,18 @@ fn main() -> ! {
3535
let p = Peripherals::take().unwrap();
3636
let mut cp = CorePeripherals::take().unwrap();
3737

38-
let (clocks, gpio, ethernet) = common::setup_peripherals(p);
38+
let mut rx_ring: [RxRingEntry; 2] = Default::default();
39+
let mut tx_ring: [TxRingEntry; 2] = Default::default();
40+
41+
let (clocks, gpio, ethernet) =
42+
common::setup_peripherals_and_cache(p, cp.MPU, &rx_ring, &tx_ring);
3943

4044
setup_systick(&mut cp.SYST);
4145

4246
defmt::info!("Enabling ethernet...");
4347

4448
let (eth_pins, mdio, mdc, _) = common::setup_pins(gpio);
4549

46-
let mut rx_ring: [RxRingEntry; 2] = Default::default();
47-
let mut tx_ring: [TxRingEntry; 2] = Default::default();
48-
4950
let Parts {
5051
mut dma,
5152
mac,

examples/async-rtic-timestamp.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,8 @@ mod app {
8181
let rx_ring = cx.local.rx_ring;
8282
let tx_ring = cx.local.tx_ring;
8383

84-
let (clocks, gpio, ethernet) = crate::common::setup_peripherals(p);
84+
let (clocks, gpio, ethernet) =
85+
crate::common::setup_peripherals_and_cache(p, cx.core.MPU, rx_ring, tx_ring);
8586

8687
defmt::info!("Setting up pins");
8788
let (pins, mdio, mdc, pps) = crate::common::setup_pins(gpio);

examples/common.rs

Lines changed: 70 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,9 @@ use defmt_rtt as _;
1010
use panic_probe as _;
1111

1212
use stm32_eth::{
13+
dma::{RxRingEntry, TxRingEntry},
1314
hal::{gpio::GpioExt, rcc::Clocks},
15+
stm32::MPU,
1416
PartsIn,
1517
};
1618

@@ -25,12 +27,79 @@ use stm32_eth::hal::rcc::RccExt;
2527
#[allow(unused)]
2628
fn main() {}
2729

30+
/// Mark RAM as non-cachable. Also validate that the RX ring
31+
/// and TX ring are within them.
32+
///
33+
/// On cores without cache (e.g. M33), this function is a no-op. For cores
34+
/// with a cache (e.g. M7), this is necessary to ensure that the data read
35+
/// by the ethernet DMA is the data that the core actually wrote.
36+
fn mpu_mark_noncachable(mpu: MPU, rx_ring: &[RxRingEntry], tx_ring: &[TxRingEntry]) {
37+
let start = 0x20000000u32;
38+
let len = 32u32 * 1024;
39+
let range = start as usize..(start as usize + len as usize);
40+
41+
let rx_start = rx_ring.as_ptr();
42+
let rx_first_addr = rx_start.addr();
43+
let rx_last_addr = unsafe { rx_start.add(rx_ring.len() + 1) }.addr() - 1;
44+
assert!(
45+
range.contains(&rx_first_addr),
46+
"RX ring starts before non-cacheable region"
47+
);
48+
49+
assert!(
50+
range.contains(&rx_last_addr),
51+
"RX ring ends after non-cacheable region"
52+
);
53+
54+
let tx_start = tx_ring.as_ptr();
55+
let tx_first_addr = tx_start.addr();
56+
let tx_last_addr = unsafe { rx_start.add(tx_ring.len() + 1) }.addr() - 1;
57+
assert!(
58+
range.contains(&tx_first_addr),
59+
"TX ring starts before non-cacheable region"
60+
);
61+
62+
assert!(
63+
range.contains(&tx_last_addr),
64+
"TX ring ends after non-cacheable region"
65+
);
66+
67+
let size_field = len.trailing_zeros() - 1;
68+
69+
unsafe {
70+
mpu.ctrl.write(0);
71+
let region = 0;
72+
mpu.rnr.write(region);
73+
mpu.rbar.write(start | 1 << 4 | region);
74+
75+
mpu.rasr.write(
76+
(1 << 28) // XN
77+
| (0b011 << 24) // AP = full access
78+
| (0b001 << 19) // TEX = 001 \
79+
| (0 << 17) // C = 0 } -> Normal, Non-cacheable
80+
| (0 << 16) // B = 0 /
81+
| (size_field << 1) // SIZE
82+
| (1 << 0), // ENABLE
83+
);
84+
}
85+
86+
cortex_m::asm::dsb();
87+
cortex_m::asm::isb();
88+
}
89+
2890
/// Setup the clocks and return clocks and a GPIO struct that
2991
/// can be used to set up all of the pins.
3092
///
3193
/// This configures HCLK to be at least 25 MHz, which is the minimum required
3294
/// for ethernet operation to be valid.
33-
pub fn setup_peripherals(p: stm32_eth::stm32::Peripherals) -> (Clocks, Gpio, PartsIn) {
95+
pub fn setup_peripherals_and_cache(
96+
p: stm32_eth::stm32::Peripherals,
97+
mpu: MPU,
98+
rx_ring: &[RxRingEntry],
99+
tx_ring: &[TxRingEntry],
100+
) -> (Clocks, Gpio, PartsIn) {
101+
mpu_mark_noncachable(mpu, rx_ring, tx_ring);
102+
34103
let ethernet = PartsIn {
35104
dma: p.ETHERNET_DMA,
36105
mac: p.ETHERNET_MAC,

examples/ip.rs

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -38,16 +38,18 @@ fn main() -> ! {
3838
let p = Peripherals::take().unwrap();
3939
let mut cp = CorePeripherals::take().unwrap();
4040

41-
let (clocks, gpio, ethernet) = common::setup_peripherals(p);
41+
let mut rx_ring: [RxRingEntry; 2] = Default::default();
42+
let mut tx_ring: [TxRingEntry; 2] = Default::default();
43+
44+
let (clocks, gpio, ethernet) =
45+
common::setup_peripherals_and_cache(p, cp.MPU, &rx_ring, &tx_ring);
4246

4347
setup_systick(&mut cp.SYST);
4448

4549
defmt::info!("Enabling ethernet...");
4650

4751
let (eth_pins, _mdio, _mdc, _) = common::setup_pins(gpio);
4852

49-
let mut rx_ring: [RxRingEntry; 2] = Default::default();
50-
let mut tx_ring: [TxRingEntry; 2] = Default::default();
5153
let Parts {
5254
mut dma,
5355
mac: _,

examples/pktgen.rs

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -35,15 +35,17 @@ fn main() -> ! {
3535
let p = Peripherals::take().unwrap();
3636
let mut cp = CorePeripherals::take().unwrap();
3737

38-
let (clocks, gpio, ethernet) = common::setup_peripherals(p);
38+
let mut rx_ring: [RxRingEntry; 2] = Default::default();
39+
let mut tx_ring: [TxRingEntry; 2] = Default::default();
40+
41+
let (clocks, gpio, ethernet) =
42+
common::setup_peripherals_and_cache(p, cp.MPU, &rx_ring, &tx_ring);
3943

4044
setup_systick(&mut cp.SYST);
4145

4246
defmt::info!("Enabling ethernet...");
4347
let (eth_pins, mdio, mdc, _) = common::setup_pins(gpio);
4448

45-
let mut rx_ring: [RxRingEntry; 2] = Default::default();
46-
let mut tx_ring: [TxRingEntry; 2] = Default::default();
4749
let Parts {
4850
mut dma,
4951
mac,

examples/rtic-echo.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,8 @@ mod app {
7272
let rx_ring = cx.local.rx_ring;
7373
let tx_ring = cx.local.tx_ring;
7474

75-
let (clocks, gpio, ethernet) = crate::common::setup_peripherals(p);
75+
let (clocks, gpio, ethernet) =
76+
crate::common::setup_peripherals_and_cache(p, core.MPU, rx_ring, tx_ring);
7677
let mono = Systick::new(core.SYST, clocks.hclk().raw());
7778

7879
let (rx_storage, tx_storage, socket_storage) = (

examples/rtic-timestamp.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,8 @@ mod app {
7777
let rx_ring = cx.local.rx_ring;
7878
let tx_ring = cx.local.tx_ring;
7979

80-
let (clocks, gpio, ethernet) = crate::common::setup_peripherals(p);
80+
let (clocks, gpio, ethernet) =
81+
crate::common::setup_peripherals_and_cache(p, core.MPU, rx_ring, tx_ring);
8182
let mono = Systick::new(core.SYST, clocks.hclk().raw());
8283

8384
defmt::info!("Setting up pins");

examples/smoltcp-timesync/client.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -112,7 +112,8 @@ mod app {
112112
let tx_payload_storage = cx.local.tx_payload_storage;
113113
let sockets = cx.local.sockets;
114114

115-
let (clocks, gpio, ethernet) = crate::common::setup_peripherals(p);
115+
let (clocks, gpio, ethernet) =
116+
crate::common::setup_peripherals_and_cache(p, core.MPU, rx_ring, tx_ring);
116117
let mono = Systick::new(core.SYST, clocks.hclk().raw());
117118

118119
defmt::info!("Setting up pins");

examples/smoltcp-timesync/server.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,8 @@ mod app {
8181
let tx_payload_storage = cx.local.tx_payload_storage;
8282
let sockets = cx.local.sockets;
8383

84-
let (clocks, gpio, ethernet) = crate::common::setup_peripherals(p);
84+
let (clocks, gpio, ethernet) =
85+
crate::common::setup_peripherals_and_cache(p, core.MPU, rx_ring, tx_ring);
8586
let mono = Systick::new(core.SYST, clocks.hclk().raw());
8687

8788
defmt::info!("Setting up pins");

examples/timesync/client.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -123,7 +123,8 @@ mod app {
123123
let rx_ring = cx.local.rx_ring;
124124
let tx_ring = cx.local.tx_ring;
125125

126-
let (clocks, gpio, ethernet) = crate::common::setup_peripherals(p);
126+
let (clocks, gpio, ethernet) =
127+
crate::common::setup_peripherals_and_cache(p, core.MPU, rx_ring, tx_ring);
127128
let mono = Systick::new(core.SYST, clocks.hclk().raw());
128129

129130
defmt::info!("Setting up pins");

0 commit comments

Comments
 (0)