Skip to content

Commit

Permalink
Merge #235
Browse files Browse the repository at this point in the history
235: Add support for STM32H725/735 parts r=richardeoin a=richardeoin

Reference Manual is RM0468

Ref #163 

- [x] Updates to support STM32H725/735 parts
- [x] Successfully build examples
- [x] At least one example for these parts specifically - _examples/ethernet-rtic-stm32h735g-dk.rs_
- [x] Fix other breakages from stm32-rs/stm32-rs#554
- [x] Remove dependency on nightly PAC build

Co-authored-by: Richard Meadows <[email protected]>
  • Loading branch information
bors[bot] and richardeoin authored Oct 30, 2021
2 parents a7f06c1 + 4ddbc24 commit 0371abb
Show file tree
Hide file tree
Showing 33 changed files with 656 additions and 243 deletions.
2 changes: 2 additions & 0 deletions .github/bors.toml
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,13 @@ status = [
"ci (1.51.0, stm32h747cm7)",
"ci (1.51.0, stm32h7b3)",
"ci (1.51.0, stm32h7b0)",
"ci (1.51.0, stm32h735)",
"ci (stable, stm32h743)",
"ci (stable, stm32h753)",
"ci (stable, stm32h743v)",
"ci (stable, stm32h753v)",
"ci (stable, stm32h747cm7)",
"ci (stable, stm32h7b3)",
"ci (stable, stm32h7b0)",
"ci (stable, stm32h735)",
]
1 change: 1 addition & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ jobs:
- stm32h747cm7
- stm32h7b3
- stm32h7b0
- stm32h735
env: # Peripheral Feature flags
FLAGS: rt,quadspi,sdmmc,fmc,usb_hs,rtc,ethernet,ltdc,crc

Expand Down
10 changes: 8 additions & 2 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,7 @@ revision_v = []
rm0433 = [] # aka. "single core" devices
rm0399 = [] # aka. "dual core" devices
rm0455 = [] # aka. "high memory integration" devices
rm0468 = [] # aka. "high speed" devices
dsi = []
cm4 = []
cm7 = []
Expand All @@ -104,6 +105,7 @@ stm32h747cm7 = ["stm32h7/stm32h747cm7", "device-selected", "revision_v", "rm0399
stm32h7b3 = ["stm32h7/stm32h7b3", "device-selected", "revision_v", "rm0455", "smps"]
stm32h7b0 = ["stm32h7/stm32h7b3", "device-selected", "revision_v", "rm0455", "smps"]
stm32h7a3 = ["stm32h7/stm32h7b3", "device-selected", "revision_v", "rm0455", "smps"]
stm32h735 = ["stm32h7/stm32h735", "device-selected", "revision_v", "rm0468", "smps"]
# Flags for examples
log-itm = []
log-rtt = []
Expand All @@ -129,15 +131,15 @@ required-features = ["rt"]

[[example]]
name = "rtic_timers"
required-features = ["rt"]
required-features = ["rt", "rm0433"]

[[example]]
name = "vos0"
required-features = ["revision_v", "rm0433"]

[[example]]
name = "fmc"
required-features = ["fmc"]
required-features = ["fmc", "rm0399"]

[[example]]
name = "qspi"
Expand All @@ -159,6 +161,10 @@ required-features = ["rt", "stm32h747cm7", "ethernet"]
name = "ethernet-rtic-stm32h747i-disco"
required-features = ["rt", "stm32h747cm7", "ethernet"]

[[example]]
name = "ethernet-rtic-stm32h735g-dk"
required-features = ["rt", "stm32h735", "ethernet"]

[[example]]
name = "ethernet-nucleo-h743zi2"
required-features = ["rt", "revision_v", "stm32h743v", "ethernet"]
Expand Down
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ Supported Configurations
* __stm32h7b3__
* __stm32h7b0__
* __stm32h7a3__
* __stm32h735__ (stm32h725, stm32h735)

#### Old revision STM32H742/743/750/753 parts

Expand Down
2 changes: 1 addition & 1 deletion examples/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ Examples

For these parts, the program needs to know more about the power supply
scheme in order to successfully transition from Run* mode to Run mode. For
en explaination of Run* mode, see RM0433 Rev 7 Section 6.6.1 "System/D3
an explaination of Run* mode, see RM0433 Rev 7 Section 6.6.1 "System/D3
domain modes".

For your own code, see the
Expand Down
230 changes: 230 additions & 0 deletions examples/ethernet-rtic-stm32h735g-dk.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,230 @@
//! Demo for STM32H735G-DK 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.
#![deny(warnings)]
#![no_main]
#![no_std]

use cortex_m;
use rtic::app;

#[macro_use]
#[allow(unused)]
mod utilities;
use log::info;

use smoltcp::iface::{
EthernetInterface, EthernetInterfaceBuilder, Neighbor, NeighborCache,
Route, Routes,
};
use smoltcp::socket::{SocketSet, SocketSetItem};
use smoltcp::time::Instant;
use smoltcp::wire::{EthernetAddress, IpAddress, IpCidr, Ipv6Cidr};

use gpio::Speed::*;
use stm32h7xx_hal::gpio;
use stm32h7xx_hal::hal::digital::v2::OutputPin;
use stm32h7xx_hal::rcc::CoreClocks;
use stm32h7xx_hal::{ethernet, ethernet::PHY};
use stm32h7xx_hal::{prelude::*, stm32};

use core::sync::atomic::{AtomicU32, Ordering};

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

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 = ethernet::DesRing::new();

/// Net storage with static initialisation - another global singleton
pub struct NetStorageStatic<'a> {
ip_addrs: [IpCidr; 1],
socket_set_entries: [Option<SocketSetItem<'a>>; 8],
neighbor_cache_storage: [Option<(IpAddress, Neighbor)>; 8],
routes_storage: [Option<(IpCidr, Route)>; 1],
}
static mut STORE: NetStorageStatic = NetStorageStatic {
// Garbage
ip_addrs: [IpCidr::Ipv6(Ipv6Cidr::SOLICITED_NODE_PREFIX)],
socket_set_entries: [None, None, None, None, None, None, None, None],
neighbor_cache_storage: [None; 8],
routes_storage: [None; 1],
};

pub struct Net<'a> {
iface: EthernetInterface<'a, ethernet::EthernetDMA<'a>>,
sockets: SocketSet<'a>,
}
impl<'a> Net<'a> {
pub fn new(
store: &'static mut NetStorageStatic<'a>,
ethdev: ethernet::EthernetDMA<'a>,
ethernet_addr: EthernetAddress,
) -> Self {
// Set IP address
store.ip_addrs =
[IpCidr::new(IpAddress::v4(192, 168, 1, 99).into(), 0)];

let neighbor_cache =
NeighborCache::new(&mut store.neighbor_cache_storage[..]);
let routes = Routes::new(&mut store.routes_storage[..]);

let iface = EthernetInterfaceBuilder::new(ethdev)
.ethernet_addr(ethernet_addr)
.neighbor_cache(neighbor_cache)
.ip_addrs(&mut store.ip_addrs[..])
.routes(routes)
.finalize();
let sockets = SocketSet::new(&mut store.socket_set_entries[..]);

return Net { iface, 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(&mut self.sockets, timestamp)
.map(|_| ())
.unwrap_or_else(|e| info!("Poll: {:?}", e));
}
}

#[app(device = stm32h7xx_hal::stm32, peripherals = true)]
const APP: () = {
struct Resources {
net: Net<'static>,
lan8742a: ethernet::phy::LAN8742A<ethernet::EthernetMAC>,
link_led: gpio::gpioc::PC3<gpio::Output<gpio::PushPull>>,
}

#[init]
fn init(mut ctx: init::Context) -> init::LateResources {
utilities::logger::init();
// Initialise power...
let pwr = ctx.device.PWR.constrain();
let pwrcfg = pwr.smps().freeze();

// 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 gpiob = ctx.device.GPIOB.split(ccdr.peripheral.GPIOB);
let mut link_led = gpioc.pc3.into_push_pull_output(); // USR LED1
link_led.set_high().ok();

let _rmii_ref_clk = gpioa.pa1.into_alternate_af11().set_speed(VeryHigh);
let _rmii_mdio = gpioa.pa2.into_alternate_af11().set_speed(VeryHigh);
let _rmii_mdc = gpioc.pc1.into_alternate_af11().set_speed(VeryHigh);
let _rmii_crs_dv = gpioa.pa7.into_alternate_af11().set_speed(VeryHigh);
let _rmii_rxd0 = gpioc.pc4.into_alternate_af11().set_speed(VeryHigh);
let _rmii_rxd1 = gpioc.pc5.into_alternate_af11().set_speed(VeryHigh);
let _rmii_tx_en = gpiob.pb11.into_alternate_af11().set_speed(VeryHigh);
let _rmii_txd0 = gpiob.pb12.into_alternate_af11().set_speed(VeryHigh);
let _rmii_txd1 = gpiob.pb13.into_alternate_af11().set_speed(VeryHigh);

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

let mac_addr = smoltcp::wire::EthernetAddress::from_bytes(&MAC_ADDRESS);
let (eth_dma, eth_mac) = unsafe {
ethernet::new_unchecked(
ctx.device.ETHERNET_MAC,
ctx.device.ETHERNET_MTL,
ctx.device.ETHERNET_DMA,
&mut DES_RING,
mac_addr.clone(),
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();
}

// 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);

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

init::LateResources {
net,
lan8742a,
link_led,
}
}

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

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

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

#[task(binds = SysTick, priority=15)]
fn systick_tick(_: systick_tick::Context) {
TIME.fetch_add(1, Ordering::Relaxed);
}
};
3 changes: 3 additions & 0 deletions examples/fmc.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
//! FMC Example
//!
//! Tested on a STM32H747I-DISCO
#![no_main]
#![no_std]

Expand Down
6 changes: 3 additions & 3 deletions examples/prec_kernel_clocks.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
mod utilities;

use cortex_m_rt::entry;
use stm32h7xx_hal::rcc::{rec, rec::I2c123ClkSel, ResetEnable};
use stm32h7xx_hal::rcc::{rec, rec::Spi123ClkSel, ResetEnable};
use stm32h7xx_hal::{pac, prelude::*};

fn enable_fdcan(rec: rec::Fdcan) {
Expand Down Expand Up @@ -34,8 +34,8 @@ fn main() -> ! {
.pll3_r_ck(4.mhz())
.freeze(pwrcfg, &dp.SYSCFG);

// Set group kernel clock to PLL3 R CK. Needs mutable ccdr
ccdr.peripheral.kernel_i2c123_clk_mux(I2c123ClkSel::PLL3_R);
// Set group kernel clock to PLL3 P CK. Needs mutable ccdr
ccdr.peripheral.kernel_spi123_clk_mux(Spi123ClkSel::PLL3_P);

// (now ccdr can be immutable)

Expand Down
7 changes: 3 additions & 4 deletions examples/rtic.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ extern crate rtic;
use stm32h7xx_hal::hal::digital::v2::ToggleableOutputPin;

use rtic::app;
use stm32h7xx_hal::gpio::{gpioc::PC13, gpioi::PI13};
use stm32h7xx_hal::gpio::gpioc::{PC13, PC3};
use stm32h7xx_hal::gpio::{Edge, ExtiPin, Floating, Input};
use stm32h7xx_hal::gpio::{Output, PushPull};
use stm32h7xx_hal::prelude::*;
Expand All @@ -23,7 +23,7 @@ use panic_halt as _;
const APP: () = {
struct Resources {
button: PC13<Input<Floating>>,
led: PI13<Output<PushPull>>,
led: PC3<Output<PushPull>>,
}

#[init]
Expand All @@ -37,7 +37,6 @@ const APP: () = {

// GPIO
let gpioc = ctx.device.GPIOC.split(ccdr.peripheral.GPIOC);
let gpioi = ctx.device.GPIOI.split(ccdr.peripheral.GPIOI);

// Button
let mut button = gpioc.pc13.into_floating_input();
Expand All @@ -47,7 +46,7 @@ const APP: () = {

init::LateResources {
button,
led: gpioi.pi13.into_push_pull_output(),
led: gpioc.pc3.into_push_pull_output(),
}
}

Expand Down
Loading

0 comments on commit 0371abb

Please sign in to comment.