Skip to content

Commit

Permalink
Merge branch 'stm32-rs:master' into ptp
Browse files Browse the repository at this point in the history
  • Loading branch information
HarishgunaS authored Oct 2, 2023
2 parents ec81090 + 600969f commit 8e4fb54
Show file tree
Hide file tree
Showing 9 changed files with 357 additions and 44 deletions.
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
# Changelog

## Unreleased

* remove unused `bitflags` dependency
* bors bot replaced with GH merge queue
* Update `smoltcp` dependency to `0.9.0`
* MSRV increased to 1.65.0
* add `IntoAf` trait to restrict `into_alternate` [#346]
* sdmmc: Introduce `write_blocks` [#453]

## [v0.14.0] 2023-03-22

Expand Down
5 changes: 4 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,6 @@ synopsys-usb-otg = { version = "^0.3.0", features = [
embedded-display-controller = { version = "^0.1.0", optional = true }
log = { version = "0.4.14", optional = true } # see also the dev-dependencies section
fdcan = { version = "0.2", optional = true }
bitflags = { version = "2.0.0" }
embedded-storage = "0.3"
futures = { version = "0.3", default-features = false, features = ["async-await"], optional = true }

Expand Down Expand Up @@ -243,6 +242,10 @@ required-features = ["rt", "stm32h747cm7", "ethernet"]
name = "ethernet-rtic-stm32h735g-dk"
required-features = ["rt", "stm32h735", "ethernet"]

[[example]]
name = "ethernet-rtic-nucleo-h723zg"
required-features = ["rt", "stm32h735", "ethernet"]

[[example]]
name = "ethernet-nucleo-h743zi2"
required-features = ["rt", "revision_v", "stm32h743v", "ethernet"]
Expand Down
235 changes: 235 additions & 0 deletions examples/ethernet-rtic-nucleo-h723zg.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,235 @@
//! Demo for Nucleo-H723ZG eval board using the Real Time for the Masses
//! (RTIC) framework.
//!
//! This demo responds to pings on 192.168.1.99 (IP address hardcoded below)
//!
//! We use the SysTick timer to create a 1ms timebase for use with smoltcp.
//!
//! The ethernet ring buffers are placed in AXI SRAM, where they can be
//! accessed by both the core and the Ethernet DMA.
//!
//! Run like
//!
//! `cargo flash --example ethernet-rtic-nucleo-h723zg --features=ethernet,stm32h735 --chip=STM32H723ZGTx`
#![deny(warnings)]
#![no_main]
#![no_std]

#[macro_use]
#[allow(unused)]
mod utilities;

use core::sync::atomic::AtomicU32;

use smoltcp::iface::{Config, Interface, SocketSet, SocketStorage};
use smoltcp::time::Instant;
use smoltcp::wire::{HardwareAddress, IpAddress, IpCidr};

use stm32h7xx_hal::{ethernet, rcc::CoreClocks, stm32};

/// Configure SYSTICK for 1ms timebase
fn systick_init(mut syst: stm32::SYST, clocks: CoreClocks) {
let c_ck_mhz = clocks.c_ck().to_MHz();

let syst_calib = 0x3E8;

syst.set_clock_source(cortex_m::peripheral::syst::SystClkSource::Core);
syst.set_reload((syst_calib * c_ck_mhz) - 1);
syst.enable_interrupt();
syst.enable_counter();
}

/// TIME is an atomic u32 that counts milliseconds.
static TIME: AtomicU32 = AtomicU32::new(0);

/// Locally administered MAC address
const MAC_ADDRESS: [u8; 6] = [0x02, 0x00, 0x11, 0x22, 0x33, 0x44];

/// Ethernet descriptor rings are a global singleton
#[link_section = ".axisram.eth"]
static mut DES_RING: ethernet::DesRing<4, 4> = ethernet::DesRing::new();

Check failure on line 50 in examples/ethernet-rtic-nucleo-h723zg.rs

View workflow job for this annotation

GitHub Actions / check (stable, stm32h735)

failed to resolve: could not find `DesRing` in `ethernet`

Check failure on line 50 in examples/ethernet-rtic-nucleo-h723zg.rs

View workflow job for this annotation

GitHub Actions / check (stable, stm32h735)

cannot find type `DesRing` in module `ethernet`

/// Net storage with static initialisation - another global singleton
pub struct NetStorageStatic<'a> {
socket_storage: [SocketStorage<'a>; 8],
}

static mut STORE: NetStorageStatic = NetStorageStatic {
socket_storage: [SocketStorage::EMPTY; 8],
};

pub struct Net<'a> {
iface: Interface,
ethdev: ethernet::EthernetDMA<4, 4>,

Check failure on line 63 in examples/ethernet-rtic-nucleo-h723zg.rs

View workflow job for this annotation

GitHub Actions / check (stable, stm32h735)

missing lifetime specifiers

Check failure on line 63 in examples/ethernet-rtic-nucleo-h723zg.rs

View workflow job for this annotation

GitHub Actions / check (stable, stm32h735)

struct takes 0 generic arguments but 2 generic arguments were supplied
sockets: SocketSet<'a>,
}
impl<'a> Net<'a> {
pub fn new(
store: &'a mut NetStorageStatic<'a>,
mut ethdev: ethernet::EthernetDMA<4, 4>,

Check failure on line 69 in examples/ethernet-rtic-nucleo-h723zg.rs

View workflow job for this annotation

GitHub Actions / check (stable, stm32h735)

struct takes 0 generic arguments but 2 generic arguments were supplied
ethernet_addr: HardwareAddress,
) -> Self {
let config = Config::new(ethernet_addr);

let mut iface = Interface::new(config, &mut ethdev, Instant::ZERO);
// Set IP address
iface.update_ip_addrs(|addrs| {
let _ = addrs.push(IpCidr::new(IpAddress::v4(192, 168, 1, 99), 0));
});

let sockets = SocketSet::new(&mut store.socket_storage[..]);

Net::<'a> {
iface,
ethdev,
sockets,
}
}

/// Polls on the ethernet interface. You should refer to the smoltcp
/// documentation for poll() to understand how to call poll efficiently
pub fn poll(&mut self, now: i64) {
let timestamp = Instant::from_millis(now);

self.iface
.poll(timestamp, &mut self.ethdev, &mut self.sockets);
}
}

#[rtic::app(device = stm32h7xx_hal::stm32, peripherals = true)]
mod app {
use stm32h7xx_hal::{ethernet, ethernet::PHY, gpio, prelude::*};

use super::*;
use core::sync::atomic::Ordering;

#[shared]
struct SharedResources {}
#[local]
struct LocalResources {
net: Net<'static>,
lan8742a: ethernet::phy::LAN8742A<ethernet::EthernetMAC>,
link_led: gpio::gpioe::PE1<gpio::Output<gpio::PushPull>>,
}

#[init]
fn init(
mut ctx: init::Context,
) -> (SharedResources, LocalResources, init::Monotonics) {
utilities::logger::init();
// Initialise power...
let pwr = ctx.device.PWR.constrain();
let pwrcfg = pwr.ldo().freeze(); // nucleo-h723zg board doesn't have SMPS

// Initialise clocks...
let rcc = ctx.device.RCC.constrain();
let ccdr = rcc
.sys_ck(200.MHz())
.hclk(200.MHz())
.freeze(pwrcfg, &ctx.device.SYSCFG);

// Initialise system...
ctx.core.SCB.invalidate_icache();
ctx.core.SCB.enable_icache();
// TODO: ETH DMA coherence issues
// ctx.core.SCB.enable_dcache(&mut ctx.core.CPUID);
ctx.core.DWT.enable_cycle_counter();

// Initialise IO...
let gpioa = ctx.device.GPIOA.split(ccdr.peripheral.GPIOA);
let gpioc = ctx.device.GPIOC.split(ccdr.peripheral.GPIOC);
let gpioe = ctx.device.GPIOE.split(ccdr.peripheral.GPIOE);
let gpiob = ctx.device.GPIOB.split(ccdr.peripheral.GPIOB);
let mut link_led = gpioe.pe1.into_push_pull_output(); // USR LED1
link_led.set_high();

let rmii_ref_clk = gpioa.pa1.into_alternate();
let rmii_mdio = gpioa.pa2.into_alternate();
let rmii_mdc = gpioc.pc1.into_alternate();
let rmii_crs_dv = gpioa.pa7.into_alternate();
let rmii_rxd0 = gpioc.pc4.into_alternate();
let rmii_rxd1 = gpioc.pc5.into_alternate();
let rmii_tx_en = gpiob.pb11.into_alternate();
let rmii_txd0 = gpiob.pb12.into_alternate();
let rmii_txd1 = gpiob.pb13.into_alternate();

// Initialise ethernet...
assert_eq!(ccdr.clocks.hclk().raw(), 200_000_000); // HCLK 200MHz
assert_eq!(ccdr.clocks.pclk1().raw(), 100_000_000); // PCLK 100MHz
assert_eq!(ccdr.clocks.pclk2().raw(), 100_000_000); // PCLK 100MHz
assert_eq!(ccdr.clocks.pclk4().raw(), 100_000_000); // PCLK 100MHz

let mac_addr = smoltcp::wire::EthernetAddress::from_bytes(&MAC_ADDRESS);
let (eth_dma, eth_mac) = unsafe {
ethernet::new(
ctx.device.ETHERNET_MAC,
ctx.device.ETHERNET_MTL,
ctx.device.ETHERNET_DMA,
(
rmii_ref_clk,
rmii_mdio,
rmii_mdc,
rmii_crs_dv,
rmii_rxd0,
rmii_rxd1,
rmii_tx_en,
rmii_txd0,
rmii_txd1,
),
&mut DES_RING,
mac_addr,
ccdr.peripheral.ETH1MAC,
&ccdr.clocks,
)
};

// Initialise ethernet PHY...
let mut lan8742a = ethernet::phy::LAN8742A::new(eth_mac);
lan8742a.phy_reset();
lan8742a.phy_init();
// The eth_dma should not be used until the PHY reports the link is up

unsafe { ethernet::enable_interrupt() };

Check failure on line 192 in examples/ethernet-rtic-nucleo-h723zg.rs

View workflow job for this annotation

GitHub Actions / check (stable, stm32h735)

cannot find function `enable_interrupt` in module `ethernet`

// unsafe: mutable reference to static storage, we only do this once
let store = unsafe { &mut STORE };
let net = Net::new(store, eth_dma, mac_addr.into());

// 1ms tick
systick_init(ctx.core.SYST, ccdr.clocks);

(
SharedResources {},
LocalResources {
net,
lan8742a,
link_led,
},
init::Monotonics(),
)
}

#[idle(local = [lan8742a, link_led])]
fn idle(ctx: idle::Context) -> ! {
loop {
// Ethernet
match ctx.local.lan8742a.poll_link() {
true => ctx.local.link_led.set_low(),
_ => ctx.local.link_led.set_high(),
}
}
}

#[task(binds = ETH, local = [net])]
fn ethernet_event(ctx: ethernet_event::Context) {
unsafe { ethernet::interrupt_handler() }

Check failure on line 225 in examples/ethernet-rtic-nucleo-h723zg.rs

View workflow job for this annotation

GitHub Actions / check (stable, stm32h735)

cannot find function `interrupt_handler` in module `ethernet`

let time = TIME.load(Ordering::Relaxed);
ctx.local.net.poll(time as i64);
}

#[task(binds = SysTick, priority=15)]
fn systick_tick(_: systick_tick::Context) {
TIME.fetch_add(1, Ordering::Relaxed);
}
}
60 changes: 24 additions & 36 deletions examples/sdmmc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -144,57 +144,45 @@ fn main() -> ! {
info!("----------------------");
info!("");

// Read test
let mut buffer = [0u8; 5120];

cp.DWT.enable_cycle_counter();
let start = pac::DWT::cycle_count();

for i in 0..10 {
// Read 10 blocks
sdmmc.read_blocks(10 * i, &mut buffer).unwrap();
}

// Write single block test
let write_buffer = [0x34; 512];
let start = pac::DWT::cycle_count();
sdmmc.write_block(0, &write_buffer).unwrap();
let end = pac::DWT::cycle_count();
let duration = (end - start) as f32 / ccdr.clocks.c_ck().raw() as f32;
info!("Wrote single block at {} bytes/s", 512.0 / duration);

info!("Read 10 blocks at {} bytes/s", 5120. / duration);
info!("");

let write_buffer = [0x34; 512];
// Write multiple blocks test
let write_buffer = [0x34; 512 * 16];
let start = pac::DWT::cycle_count();
sdmmc.write_blocks(0, &write_buffer).unwrap();
let end = pac::DWT::cycle_count();
let duration = (end - start) as f32 / ccdr.clocks.c_ck().raw() as f32;
info!("Wrote 16 blocks at {} bytes/s", (512.0 * 16.0) / duration);

for i in 0..10 {
if let Err(err) = sdmmc.write_block(i, &write_buffer) {
info!("Failed to write block {}: {:?}", i, err);
}
}

// Read single block test
let mut buffer = [0u8; 512];
let start = pac::DWT::cycle_count();
sdmmc.read_block(0, &mut buffer).unwrap();
let end = pac::DWT::cycle_count();
let duration = (end - start) as f32 / ccdr.clocks.c_ck().raw() as f32;
info!("Read single block at {} bytes/s", 512.0 / duration);

info!("Wrote 10 blocks at {} bytes/s", 5120. / duration);
info!("");
// Read multiple blocks test
let mut buffer = [0u8; 512 * 16];
let start = pac::DWT::cycle_count();
sdmmc.read_blocks(0, &mut buffer).unwrap();
let end = pac::DWT::cycle_count();
let duration = (end - start) as f32 / ccdr.clocks.c_ck().raw() as f32;
info!("Read 16 blocks at {} bytes/s", (512.0 * 16.0) / duration);

info!("Verification test...");
// Write 10 blocks
for i in 0..10 {
if let Err(err) = sdmmc.write_block(i, &write_buffer) {
info!("Failed to write block {}: {:?}", i, err);
} else {
info!("Wrote block {}", i);
}

// Read back
sdmmc.read_blocks(0, &mut buffer).unwrap();
}

// Check the read
for byte in buffer.iter() {
assert_eq!(*byte, 0x34);
}
info!("Verified 10 blocks");
info!("");
info!("Verified all blocks");

info!("Done!");

Expand Down
2 changes: 1 addition & 1 deletion src/sai/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
//! ## Examples using the Electro Smith Daisy Seed Board (AK4556 codec)
//!
//! - [SAI with DMA](https://github.com/stm32-rs/stm32h7xx-hal/blob/master/examples/sai_dma_passthru.rs)
//! - [SAI with I2C](https://github.com/stm32-rs/stm32h7xx-hal/blob/master/examples/sai-i2s-passthru.rs)
//! - [SAI with I2S](https://github.com/stm32-rs/stm32h7xx-hal/blob/master/examples/sai-i2s-passthru.rs)

use core::marker::PhantomData;

Expand Down
Loading

0 comments on commit 8e4fb54

Please sign in to comment.