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,36 +49,38 @@ 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