#![deny(warnings)]
#![no_main]
#![no_std]
extern crate cortex_m_rt as rt;
use core::sync::atomic::{AtomicU32, Ordering};
use rt::{entry, exception};
extern crate cortex_m;
#[macro_use]
mod utilities;
use log::info;
use stm32h7xx_hal::rcc::CoreClocks;
use stm32h7xx_hal::{ethernet, ethernet::PHY};
use stm32h7xx_hal::{prelude::*, stm32, stm32::interrupt};
fn systick_init(syst: &mut 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();
}
static TIME: AtomicU32 = AtomicU32::new(0);
const MAC_ADDRESS: [u8; 6] = [0x02, 0x00, 0x11, 0x22, 0x33, 0x44];
#[link_section = ".sram3.eth"]
static mut DES_RING: ethernet::DesRing<4, 4> = ethernet::DesRing::new();
#[entry]
fn main() -> ! {
utilities::logger::init();
let dp = stm32::Peripherals::take().unwrap();
let mut cp = stm32::CorePeripherals::take().unwrap();
info!("Setup PWR... ");
let pwr = dp.PWR.constrain();
let pwrcfg = example_power!(pwr).freeze();
info!("Setup RCC... ");
dp.RCC.ahb2enr.modify(|_, w| w.sram3en().set_bit());
let rcc = dp.RCC.constrain();
let ccdr = rcc
.sys_ck(200.MHz())
.hclk(200.MHz())
.pll1_r_ck(100.MHz()) .freeze(pwrcfg, &dp.SYSCFG);
let delay = cp.SYST.delay(ccdr.clocks);
cp.SCB.enable_icache();
cp.DWT.enable_cycle_counter();
let gpioa = dp.GPIOA.split(ccdr.peripheral.GPIOA);
let gpiob = dp.GPIOB.split(ccdr.peripheral.GPIOB);
let gpioc = dp.GPIOC.split(ccdr.peripheral.GPIOC);
let gpiog = dp.GPIOG.split(ccdr.peripheral.GPIOG);
let mut link_led = gpiob.pb0.into_push_pull_output(); 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 = gpiog.pg11.into_alternate();
let rmii_txd0 = gpiog.pg13.into_alternate();
let rmii_txd1 = gpiob.pb13.into_alternate();
assert_eq!(ccdr.clocks.hclk().raw(), 200_000_000); assert_eq!(ccdr.clocks.pclk1().raw(), 100_000_000); assert_eq!(ccdr.clocks.pclk2().raw(), 100_000_000); assert_eq!(ccdr.clocks.pclk4().raw(), 100_000_000);
let mac_addr = smoltcp::wire::EthernetAddress::from_bytes(&MAC_ADDRESS);
let (_eth_dma, eth_mac) = unsafe {
ethernet::new(
dp.ETHERNET_MAC,
dp.ETHERNET_MTL,
dp.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,
)
};
let mut lan8742a = ethernet::phy::LAN8742A::new(eth_mac.set_phy_addr(0));
lan8742a.phy_reset();
lan8742a.phy_init();
unsafe {
ethernet::enable_interrupt();
cp.NVIC.set_priority(stm32::Interrupt::ETH, 196); cortex_m::peripheral::NVIC::unmask(stm32::Interrupt::ETH);
}
systick_init(&mut delay.free(), ccdr.clocks);
unsafe {
cp.SCB.shpr[15 - 4].write(128);
}
let mut eth_up = false;
loop {
let _time = TIME.load(Ordering::Relaxed);
let eth_last = eth_up;
eth_up = lan8742a.poll_link();
match eth_up {
true => link_led.set_low(),
_ => link_led.set_high(),
}
if eth_up != eth_last {
match eth_up {
true => info!("Ethernet UP"),
_ => info!("Ethernet DOWN"),
}
}
}
}
#[interrupt]
fn ETH() {
unsafe { ethernet::interrupt_handler() }
}
#[exception]
fn SysTick() {
TIME.fetch_add(1, Ordering::Relaxed);
}
#[exception]
unsafe fn HardFault(ef: &cortex_m_rt::ExceptionFrame) -> ! {
panic!("HardFault at {:#?}", ef);
}
#[exception]
unsafe fn DefaultHandler(irqn: i16) {
panic!("Unhandled exception (IRQn = {})", irqn);
}