Compare commits
9 Commits
embassy-ne
...
net-wiznet
Author | SHA1 | Date | |
---|---|---|---|
630443a4d6 | |||
035800bfbd | |||
c7803bb8f4 | |||
d496a1213c | |||
241488ef1c | |||
88b2cdd6a0 | |||
6906cc9c25 | |||
cb211f88d3 | |||
3f262a2603 |
@ -1,14 +1,14 @@
|
|||||||
//! [`embassy-net`](https://crates.io/crates/embassy-net) driver for WIZnet ethernet chips.
|
|
||||||
#![no_std]
|
#![no_std]
|
||||||
#![feature(async_fn_in_trait)]
|
#![feature(async_fn_in_trait)]
|
||||||
|
#![doc = include_str!("../README.md")]
|
||||||
|
|
||||||
pub mod chip;
|
pub mod chip;
|
||||||
mod device;
|
mod device;
|
||||||
|
|
||||||
use embassy_futures::select::{select, Either};
|
use embassy_futures::select::{select3, Either3};
|
||||||
use embassy_net_driver_channel as ch;
|
use embassy_net_driver_channel as ch;
|
||||||
use embassy_net_driver_channel::driver::LinkState;
|
use embassy_net_driver_channel::driver::LinkState;
|
||||||
use embassy_time::Timer;
|
use embassy_time::{Duration, Ticker, Timer};
|
||||||
use embedded_hal::digital::OutputPin;
|
use embedded_hal::digital::OutputPin;
|
||||||
use embedded_hal_async::digital::Wait;
|
use embedded_hal_async::digital::Wait;
|
||||||
use embedded_hal_async::spi::SpiDevice;
|
use embedded_hal_async::spi::SpiDevice;
|
||||||
@ -49,35 +49,37 @@ pub struct Runner<'d, C: Chip, SPI: SpiDevice, INT: Wait, RST: OutputPin> {
|
|||||||
impl<'d, C: Chip, SPI: SpiDevice, INT: Wait, RST: OutputPin> Runner<'d, C, SPI, INT, RST> {
|
impl<'d, C: Chip, SPI: SpiDevice, INT: Wait, RST: OutputPin> Runner<'d, C, SPI, INT, RST> {
|
||||||
pub async fn run(mut self) -> ! {
|
pub async fn run(mut self) -> ! {
|
||||||
let (state_chan, mut rx_chan, mut tx_chan) = self.ch.split();
|
let (state_chan, mut rx_chan, mut tx_chan) = self.ch.split();
|
||||||
|
let mut tick = Ticker::every(Duration::from_millis(500));
|
||||||
loop {
|
loop {
|
||||||
if self.mac.is_link_up().await {
|
match select3(
|
||||||
state_chan.set_link_state(LinkState::Up);
|
|
||||||
loop {
|
|
||||||
match select(
|
|
||||||
async {
|
async {
|
||||||
self.int.wait_for_low().await.ok();
|
self.int.wait_for_low().await.ok();
|
||||||
rx_chan.rx_buf().await
|
rx_chan.rx_buf().await
|
||||||
},
|
},
|
||||||
tx_chan.tx_buf(),
|
tx_chan.tx_buf(),
|
||||||
|
tick.next(),
|
||||||
)
|
)
|
||||||
.await
|
.await
|
||||||
{
|
{
|
||||||
Either::First(p) => {
|
Either3::First(p) => {
|
||||||
if let Ok(n) = self.mac.read_frame(p).await {
|
if let Ok(n) = self.mac.read_frame(p).await {
|
||||||
rx_chan.rx_done(n);
|
rx_chan.rx_done(n);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Either::Second(p) => {
|
Either3::Second(p) => {
|
||||||
self.mac.write_frame(p).await.ok();
|
self.mac.write_frame(p).await.ok();
|
||||||
tx_chan.tx_done();
|
tx_chan.tx_done();
|
||||||
}
|
}
|
||||||
}
|
Either3::Third(()) => {
|
||||||
}
|
if self.mac.is_link_up().await {
|
||||||
|
state_chan.set_link_state(LinkState::Up);
|
||||||
} else {
|
} else {
|
||||||
state_chan.set_link_state(LinkState::Down);
|
state_chan.set_link_state(LinkState::Down);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Create a Wiznet ethernet chip driver for [`embassy-net`](https://crates.io/crates/embassy-net).
|
/// Create a Wiznet ethernet chip driver for [`embassy-net`](https://crates.io/crates/embassy-net).
|
||||||
|
@ -10,16 +10,39 @@ use crate::gpio::sealed::Pin as _;
|
|||||||
use crate::gpio::{AnyPin, Pin as GpioPin};
|
use crate::gpio::{AnyPin, Pin as GpioPin};
|
||||||
use crate::{pac, peripherals, RegExt};
|
use crate::{pac, peripherals, RegExt};
|
||||||
|
|
||||||
|
/// The configuration of a PWM slice.
|
||||||
|
/// Note the period in clock cycles of a slice can be computed as:
|
||||||
|
/// `(top + 1) * (phase_correct ? 1 : 2) * divider`
|
||||||
#[non_exhaustive]
|
#[non_exhaustive]
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct Config {
|
pub struct Config {
|
||||||
|
/// Inverts the PWM output signal on channel A.
|
||||||
pub invert_a: bool,
|
pub invert_a: bool,
|
||||||
|
/// Inverts the PWM output signal on channel B.
|
||||||
pub invert_b: bool,
|
pub invert_b: bool,
|
||||||
|
/// Enables phase-correct mode for PWM operation.
|
||||||
|
/// In phase-correct mode, the PWM signal is generated in such a way that
|
||||||
|
/// the pulse is always centered regardless of the duty cycle.
|
||||||
|
/// The output frequency is halved when phase-correct mode is enabled.
|
||||||
pub phase_correct: bool,
|
pub phase_correct: bool,
|
||||||
|
/// Enables the PWM slice, allowing it to generate an output.
|
||||||
pub enable: bool,
|
pub enable: bool,
|
||||||
|
/// A fractional clock divider, represented as a fixed-point number with
|
||||||
|
/// 8 integer bits and 4 fractional bits. It allows precise control over
|
||||||
|
/// the PWM output frequency by gating the PWM counter increment.
|
||||||
|
/// A higher value will result in a slower output frequency.
|
||||||
pub divider: fixed::FixedU16<fixed::types::extra::U4>,
|
pub divider: fixed::FixedU16<fixed::types::extra::U4>,
|
||||||
|
/// The output on channel A goes high when `compare_a` is higher than the
|
||||||
|
/// counter. A compare of 0 will produce an always low output, while a
|
||||||
|
/// compare of `top + 1` will produce an always high output.
|
||||||
pub compare_a: u16,
|
pub compare_a: u16,
|
||||||
|
/// The output on channel B goes high when `compare_b` is higher than the
|
||||||
|
/// counter. A compare of 0 will produce an always low output, while a
|
||||||
|
/// compare of `top + 1` will produce an always high output.
|
||||||
pub compare_b: u16,
|
pub compare_b: u16,
|
||||||
|
/// The point at which the counter wraps, representing the maximum possible
|
||||||
|
/// period. The counter will either wrap to 0 or reverse depending on the
|
||||||
|
/// setting of `phase_correct`.
|
||||||
pub top: u16,
|
pub top: u16,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -173,6 +196,9 @@ impl<'d, T: Channel> Pwm<'d, T> {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Advances a slice’s output phase by one count while it is running
|
||||||
|
/// by inserting a pulse into the clock enable. The counter
|
||||||
|
/// will not count faster than once per cycle.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn phase_advance(&mut self) {
|
pub fn phase_advance(&mut self) {
|
||||||
let p = self.inner.regs();
|
let p = self.inner.regs();
|
||||||
@ -180,6 +206,9 @@ impl<'d, T: Channel> Pwm<'d, T> {
|
|||||||
while p.csr().read().ph_adv() {}
|
while p.csr().read().ph_adv() {}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Retards a slice’s output phase by one count while it is running
|
||||||
|
/// by deleting a pulse from the clock enable. The counter will not
|
||||||
|
/// count backward when clock enable is permenantly low.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn phase_retard(&mut self) {
|
pub fn phase_retard(&mut self) {
|
||||||
let p = self.inner.regs();
|
let p = self.inner.regs();
|
||||||
|
@ -2,7 +2,7 @@ pub use crate::pac::rcc::vals::{
|
|||||||
Hpre as AHBPrescaler, Pllm as PllPreDiv, Plln as PllMul, Pllp, Pllq, Pllr, Pllsrc as PllSource,
|
Hpre as AHBPrescaler, Pllm as PllPreDiv, Plln as PllMul, Pllp, Pllq, Pllr, Pllsrc as PllSource,
|
||||||
Ppre as APBPrescaler, Sw as Sysclk,
|
Ppre as APBPrescaler, Sw as Sysclk,
|
||||||
};
|
};
|
||||||
use crate::pac::{FLASH, PWR, RCC};
|
use crate::pac::{FLASH, RCC};
|
||||||
use crate::rcc::{set_freqs, Clocks};
|
use crate::rcc::{set_freqs, Clocks};
|
||||||
use crate::time::Hertz;
|
use crate::time::Hertz;
|
||||||
|
|
||||||
@ -101,11 +101,17 @@ impl Default for Config {
|
|||||||
|
|
||||||
pub(crate) unsafe fn init(config: Config) {
|
pub(crate) unsafe fn init(config: Config) {
|
||||||
// always enable overdrive for now. Make it configurable in the future.
|
// always enable overdrive for now. Make it configurable in the future.
|
||||||
|
#[cfg(not(any(
|
||||||
|
stm32f401, stm32f410, stm32f411, stm32f412, stm32f413, stm32f423, stm32f405, stm32f407, stm32f415, stm32f417
|
||||||
|
)))]
|
||||||
|
{
|
||||||
|
use crate::pac::PWR;
|
||||||
PWR.cr1().modify(|w| w.set_oden(true));
|
PWR.cr1().modify(|w| w.set_oden(true));
|
||||||
while !PWR.csr1().read().odrdy() {}
|
while !PWR.csr1().read().odrdy() {}
|
||||||
|
|
||||||
PWR.cr1().modify(|w| w.set_odswen(true));
|
PWR.cr1().modify(|w| w.set_odswen(true));
|
||||||
while !PWR.csr1().read().odswrdy() {}
|
while !PWR.csr1().read().odswrdy() {}
|
||||||
|
}
|
||||||
|
|
||||||
// Configure HSI
|
// Configure HSI
|
||||||
let hsi = match config.hsi {
|
let hsi = match config.hsi {
|
||||||
|
@ -1,7 +1,12 @@
|
|||||||
MEMORY
|
MEMORY
|
||||||
{
|
{
|
||||||
/* NOTE 1 K = 1 KiBi = 1024 bytes */
|
/* NOTE 1 K = 1 KiBi = 1024 bytes */
|
||||||
/* These values correspond to the NRF52840 with Softdevices S140 7.0.1 */
|
|
||||||
FLASH : ORIGIN = 0x00000000, LENGTH = 1024K
|
FLASH : ORIGIN = 0x00000000, LENGTH = 1024K
|
||||||
RAM : ORIGIN = 0x20000000, LENGTH = 256K
|
RAM : ORIGIN = 0x20000000, LENGTH = 256K
|
||||||
|
|
||||||
|
/* These values correspond to the NRF52840 with Softdevices S140 7.3.0 */
|
||||||
|
/*
|
||||||
|
FLASH : ORIGIN = 0x00027000, LENGTH = 868K
|
||||||
|
RAM : ORIGIN = 0x20020000, LENGTH = 128K
|
||||||
|
*/
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,12 @@
|
|||||||
MEMORY
|
MEMORY
|
||||||
{
|
{
|
||||||
/* NOTE 1 K = 1 KiBi = 1024 bytes */
|
/* NOTE 1 K = 1 KiBi = 1024 bytes */
|
||||||
/* These values correspond to the NRF52840 with Softdevices S140 7.0.1 */
|
|
||||||
FLASH : ORIGIN = 0x00000000, LENGTH = 1024K
|
FLASH : ORIGIN = 0x00000000, LENGTH = 1024K
|
||||||
RAM : ORIGIN = 0x20000000, LENGTH = 256K
|
RAM : ORIGIN = 0x20000000, LENGTH = 256K
|
||||||
|
|
||||||
|
/* These values correspond to the NRF52840 with Softdevices S140 7.3.0 */
|
||||||
|
/*
|
||||||
|
FLASH : ORIGIN = 0x00027000, LENGTH = 868K
|
||||||
|
RAM : ORIGIN = 0x20020000, LENGTH = 128K
|
||||||
|
*/
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user