1use smoltcp::{
26 self,
27 phy::{self, DeviceCapabilities},
28 time::Instant,
29 wire::EthernetAddress,
30};
31use stm32h7xx_hal::stm32;
32
33use crate::ETH_PHY_ADDR;
34use crate::{StationManagement, PHY};
35
36const ETH_BUF_SIZE: usize = 1536;
39const ETH_NUM_TD: usize = 4;
40const ETH_NUM_RD: usize = 4;
41
42#[allow(dead_code)]
43mod cr_consts {
44 pub const ETH_MACMIIAR_CR_HCLK_DIV_42: u8 = 0;
46 pub const ETH_MACMIIAR_CR_HCLK_DIV_62: u8 = 1;
48 pub const ETH_MACMIIAR_CR_HCLK_DIV_16: u8 = 2;
50 pub const ETH_MACMIIAR_CR_HCLK_DIV_26: u8 = 3;
52 pub const ETH_MACMIIAR_CR_HCLK_DIV_102: u8 = 4;
54 pub const ETH_MACMIIAR_CR_HCLK_DIV_124: u8 = 5;
56}
57use self::cr_consts::*;
58
59const CLOCK_RANGE: u8 = ETH_MACMIIAR_CR_HCLK_DIV_102;
62
63#[allow(dead_code)]
65mod emac_consts {
66 pub const EMAC_DES3_OWN: u32 = 0x8000_0000;
67 pub const EMAC_DES3_CTXT: u32 = 0x4000_0000;
68 pub const EMAC_DES3_FD: u32 = 0x2000_0000;
69 pub const EMAC_DES3_LD: u32 = 0x1000_0000;
70 pub const EMAC_DES3_ES: u32 = 0x0000_8000;
71 pub const EMAC_TDES2_IOC: u32 = 0x8000_0000;
72 pub const EMAC_RDES3_IOC: u32 = 0x4000_0000;
73 pub const EMAC_RDES3_PL: u32 = 0x0000_7FFF;
74 pub const EMAC_RDES3_BUF1V: u32 = 0x0100_0000;
75 pub const EMAC_TDES2_B1L: u32 = 0x0000_3FFF;
76 pub const EMAC_DES0_BUF1AP: u32 = 0xFFFF_FFFF;
77}
78use self::emac_consts::*;
79
80#[derive(Copy, Clone)]
91#[repr(C, packed)]
92struct TDes {
93 tdes0: u32,
94 tdes1: u32,
95 tdes2: u32,
96 tdes3: u32,
97}
98
99impl TDes {
100 pub fn init(&mut self) {
102 self.tdes0 = 0;
103 self.tdes1 = 0;
104 self.tdes2 = 0;
105 self.tdes3 = 0; }
107
108 pub fn available(&self) -> bool {
110 self.tdes3 & EMAC_DES3_OWN == 0
111 }
112}
113
114#[repr(C, packed)]
116struct TDesRing {
117 td: [TDes; ETH_NUM_TD],
118 tbuf: [[u32; ETH_BUF_SIZE / 4]; ETH_NUM_TD],
119 tdidx: usize,
120}
121
122impl TDesRing {
123 const fn new() -> Self {
124 Self {
125 td: [TDes {
126 tdes0: 0,
127 tdes1: 0,
128 tdes2: 0,
129 tdes3: 0,
130 }; ETH_NUM_TD],
131 tbuf: [[0; ETH_BUF_SIZE / 4]; ETH_NUM_TD],
132 tdidx: 0,
133 }
134 }
135
136 pub fn init(&mut self) {
142 for td in self.td.iter_mut() {
143 td.init();
144 }
145 self.tdidx = 0;
146
147 cortex_m::interrupt::free(|_cs| unsafe {
148 let dma = &*stm32::ETHERNET_DMA::ptr();
149
150 dma.dmactx_dlar
151 .write(|w| w.bits(&self.td as *const _ as u32));
152
153 dma.dmactx_rlr
154 .write(|w| w.tdrl().bits(self.td.len() as u16 - 1));
155
156 dma.dmactx_dtpr
157 .write(|w| w.bits(&self.td[0] as *const _ as u32));
158 });
159 }
160
161 pub fn available(&self) -> bool {
163 self.td[self.tdidx].available()
164 }
165
166 pub fn release(&mut self) {
168 let x = self.tdidx;
169 assert!(self.td[x].tdes3 & EMAC_DES3_OWN == 0); let address = unsafe { self.tbuf[x].as_ptr() as u32 };
174
175 self.td[x].tdes0 = address; self.td[x].tdes1 = 0; assert!(self.td[x].tdes2 & !EMAC_TDES2_B1L == 0); assert!(self.td[x].tdes2 & EMAC_TDES2_B1L > 0); self.td[x].tdes3 = 0;
181 self.td[x].tdes3 |= EMAC_DES3_FD; self.td[x].tdes3 |= EMAC_DES3_LD; self.td[x].tdes3 |= EMAC_DES3_OWN; let x = (x + 1) % ETH_NUM_TD;
187 cortex_m::interrupt::free(|_cs| unsafe {
188 let dma = &*stm32::ETHERNET_DMA::ptr();
189
190 cortex_m::asm::dsb();
193
194 dma.dmactx_dtpr
195 .write(|w| w.bits(&(self.td[x]) as *const _ as u32));
196 });
197
198 self.tdidx = x;
199 }
200
201 pub unsafe fn buf_as_slice_mut(&mut self, length: usize) -> &mut [u8] {
203 let x = self.tdidx;
204
205 self.td[x].tdes0 = self.tbuf[x].as_ptr() as u32; let len = core::cmp::min(length, ETH_BUF_SIZE);
210 self.td[x].tdes2 = (length as u32) & EMAC_TDES2_B1L;
211
212 let addr = self.tbuf[x].as_ptr() as *mut _;
214 core::slice::from_raw_parts_mut(addr, len)
215 }
216}
217
218#[derive(Copy, Clone)]
229#[repr(C, packed)]
230struct RDes {
231 rdes0: u32,
232 rdes1: u32,
233 rdes2: u32,
234 rdes3: u32,
235}
236
237impl RDes {
238 pub fn init(&mut self) {
240 self.rdes0 = 0;
241 self.rdes1 = 0;
242 self.rdes2 = 0;
243 self.rdes3 = 0; }
245
246 pub fn valid(&self) -> bool {
248 self.rdes3
253 & (EMAC_DES3_FD | EMAC_DES3_LD | EMAC_DES3_ES | EMAC_DES3_CTXT)
254 == (EMAC_DES3_FD | EMAC_DES3_LD)
255 }
256
257 pub fn available(&self) -> bool {
259 self.rdes3 & EMAC_DES3_OWN == 0 }
261}
262
263#[repr(C, packed)]
265struct RDesRing {
266 rd: [RDes; ETH_NUM_RD],
267 rbuf: [[u32; ETH_BUF_SIZE / 4]; ETH_NUM_RD],
268 rdidx: usize,
269}
270
271impl RDesRing {
272 const fn new() -> Self {
273 Self {
274 rd: [RDes {
275 rdes0: 0,
276 rdes1: 0,
277 rdes2: 0,
278 rdes3: 0,
279 }; ETH_NUM_RD],
280 rbuf: [[0; ETH_BUF_SIZE / 4]; ETH_NUM_RD],
281 rdidx: 0,
282 }
283 }
284
285 pub fn init(&mut self) {
291 for rd in self.rd.iter_mut() {
292 rd.init();
293 }
294 self.rdidx = 0;
295
296 cortex_m::interrupt::free(|_cs| unsafe {
298 let dma = &*stm32::ETHERNET_DMA::ptr();
299
300 dma.dmacrx_dlar
301 .write(|w| w.bits(&self.rd as *const _ as u32));
302
303 dma.dmacrx_rlr
304 .write(|w| w.rdrl().bits(self.rd.len() as u16 - 1));
305 });
306
307 while self.available() {
309 self.release()
310 }
311 }
312
313 pub fn available(&self) -> bool {
315 self.rd[self.rdidx].available()
316 }
317
318 pub fn valid(&self) -> bool {
320 self.rd[self.rdidx].valid()
321 }
322
323 pub fn release(&mut self) {
325 let x = self.rdidx;
326 assert!(self.rd[x].rdes3 & EMAC_DES3_OWN == 0); let address = unsafe { self.rbuf[x].as_ptr() as u32 };
331
332 self.rd[x].rdes0 = address; self.rd[x].rdes1 = 0; self.rd[x].rdes2 = 0; self.rd[x].rdes3 = 0;
337 self.rd[x].rdes3 |= EMAC_DES3_OWN; self.rd[x].rdes3 |= EMAC_RDES3_BUF1V; self.rd[x].rdes3 |= EMAC_RDES3_IOC; cortex_m::interrupt::free(|_cs| unsafe {
343 let dma = &*stm32::ETHERNET_DMA::ptr();
344
345 cortex_m::asm::dsb();
348
349 dma.dmacrx_dtpr
350 .write(|w| w.bits(&(self.rd[x]) as *const _ as u32));
351 });
352
353 self.rdidx = (x + 1) % ETH_NUM_RD;
355 }
356
357 #[allow(clippy::mut_from_ref)]
364 pub unsafe fn buf_as_slice_mut(&self) -> &mut [u8] {
365 let x = self.rdidx;
366
367 let addr = self.rbuf[x].as_ptr() as *mut u8;
369 let len = (self.rd[x].rdes3 & EMAC_RDES3_PL) as usize;
370
371 let len = core::cmp::min(len, ETH_BUF_SIZE);
372 core::slice::from_raw_parts_mut(addr, len)
373 }
374}
375
376pub struct DesRing {
377 tx: TDesRing,
378 rx: RDesRing,
379}
380impl DesRing {
381 pub const fn new() -> DesRing {
382 DesRing {
383 tx: TDesRing::new(),
384 rx: RDesRing::new(),
385 }
386 }
387}
388
389pub struct EthernetDMA<'a> {
393 ring: &'a mut DesRing,
394 eth_dma: stm32::ETHERNET_DMA,
395}
396
397pub struct EthernetMAC {
401 eth_mac: stm32::ETHERNET_MAC,
402}
403
404pub unsafe fn ethernet_init(
418 eth_mac: stm32::ETHERNET_MAC,
419 eth_mtl: stm32::ETHERNET_MTL,
420 eth_dma: stm32::ETHERNET_DMA,
421 ring: &mut DesRing,
422 mac_addr: EthernetAddress,
423) -> (EthernetDMA, EthernetMAC) {
424 {
426 let rcc = &*stm32::RCC::ptr();
427 let syscfg = &*stm32::SYSCFG::ptr();
428
429 rcc.apb4enr.modify(|_, w| w.syscfgen().set_bit());
430 rcc.ahb1enr.modify(|_, w| {
431 w.eth1macen()
432 .set_bit()
433 .eth1txen()
434 .set_bit()
435 .eth1rxen()
436 .set_bit()
437 });
438 syscfg.pmcr.modify(|_, w| w.epis().bits(0b100)); }
440
441 cortex_m::interrupt::free(|_cs| {
446 eth_dma.dmamr.modify(|_, w| w.swr().set_bit());
448 while eth_dma.dmamr.read().swr().bit_is_set() {}
449
450 eth_mac
452 .mac1ustcr
453 .modify(|_, w| w.tic_1us_cntr().bits(200 - 1));
454
455 eth_mac.maccr.modify(|_, w| {
457 w.arpen()
458 .clear_bit()
459 .ipc()
460 .set_bit()
461 .ipg()
462 .bits(0b000) .ecrsfd()
464 .clear_bit()
465 .dcrs()
466 .clear_bit()
467 .bl()
468 .bits(0b00) .prelen()
470 .bits(0b00) .cst()
473 .set_bit()
474 .fes()
476 .set_bit()
477 .dm()
479 .set_bit()
480 .acs()
482 .set_bit()
483 .dr()
485 .set_bit()
486 });
487 eth_mac.macecr.modify(|_, w| {
488 w.eipgen()
489 .clear_bit()
490 .usp()
491 .clear_bit()
492 .spen()
493 .clear_bit()
494 .dcrcc()
495 .clear_bit()
496 });
497 eth_mac.maca0lr.write(|w| {
499 w.addrlo().bits(
500 u32::from(mac_addr.0[0])
501 | (u32::from(mac_addr.0[1]) << 8)
502 | (u32::from(mac_addr.0[2]) << 16)
503 | (u32::from(mac_addr.0[3]) << 24),
504 )
505 });
506 eth_mac.maca0hr.write(
507 |w| {
508 w.addrhi().bits(
509 u16::from(mac_addr.0[4]) | (u16::from(mac_addr.0[5]) << 8),
510 )
511 }, );
514 eth_mac.macpfr.modify(|_, w| {
516 w.dntu()
517 .clear_bit()
518 .ipfe()
519 .clear_bit()
520 .vtfe()
521 .clear_bit()
522 .hpf()
523 .clear_bit()
524 .saf()
525 .clear_bit()
526 .saif()
527 .clear_bit()
528 .pcf()
529 .bits(0b00)
530 .dbf()
531 .clear_bit()
532 .pm()
533 .clear_bit()
534 .daif()
535 .clear_bit()
536 .hmc()
537 .clear_bit()
538 .huc()
539 .clear_bit()
540 .ra()
542 .set_bit()
543 .pr()
545 .clear_bit()
546 });
547 eth_mac.macwtr.write(|w| w.pwe().clear_bit());
548 eth_mac.macqtx_fcr.modify(|_, w| {
550 w.pt().bits(0x100)
552 });
553 eth_mac.macrx_fcr.modify(|_, w| w);
554 eth_mtl.mtlrx_qomr.modify(|_, w| {
555 w
556 .rsf()
558 .set_bit()
559 .dis_tcp_ef()
561 .clear_bit()
562 .fep()
564 .clear_bit()
565 .fup()
567 .clear_bit()
568 });
569 eth_mtl.mtltx_qomr.modify(|_, w| {
570 w
571 .tsf()
573 .set_bit()
574 });
575
576 eth_dma.dmamr.modify(|_, w| {
578 w.intm()
579 .bits(0b00)
580 .pr()
582 .bits(0b000)
583 .txpr()
584 .clear_bit()
585 .da()
586 .clear_bit()
587 });
588 eth_dma.dmasbmr.modify(|_, w| {
590 w.aal()
592 .set_bit()
593 .fb()
595 .set_bit()
596 });
597 eth_dma
598 .dmaccr
599 .modify(|_, w| w.dsl().bits(0).pblx8().clear_bit().mss().bits(536));
600 eth_dma.dmactx_cr.modify(|_, w| {
601 w
602 .txpbl()
604 .bits(32)
605 .tse()
606 .clear_bit()
607 .osf()
609 .clear_bit()
610 });
611
612 eth_dma.dmacrx_cr.modify(|_, w| {
613 w
614 .rbsz()
616 .bits(ETH_BUF_SIZE as u16)
617 .rxpbl()
619 .bits(32)
620 .rpf()
622 .clear_bit()
623 });
624
625 ring.tx.init();
627 ring.rx.init();
628
629 cortex_m::asm::dsb();
631
632 eth_mac.maccr.modify(|_, w| {
634 w.re()
635 .bit(true) .te()
637 .bit(true) });
639 eth_mtl.mtltx_qomr.modify(|_, w| w.ftq().set_bit());
640
641 eth_dma.dmactx_cr.modify(|_, w| w.st().set_bit());
643 eth_dma.dmacrx_cr.modify(|_, w| w.sr().set_bit());
644
645 eth_dma
646 .dmacsr
647 .modify(|_, w| w.tps().set_bit().rps().set_bit());
648 });
649
650 let mut mac = EthernetMAC { eth_mac };
652 mac.phy_reset();
653 mac.phy_init(); let dma = EthernetDMA { ring, eth_dma };
656
657 (dma, mac)
658}
659
660impl StationManagement for EthernetMAC {
664 fn smi_read(&mut self, reg: u8) -> u16 {
666 while self.eth_mac.macmdioar.read().mb().bit_is_set() {}
667 self.eth_mac.macmdioar.modify(|_, w| unsafe {
668 w.pa()
669 .bits(ETH_PHY_ADDR)
670 .rda()
671 .bits(reg)
672 .goc()
673 .bits(0b11) .cr()
675 .bits(CLOCK_RANGE)
676 .mb()
677 .set_bit()
678 });
679 while self.eth_mac.macmdioar.read().mb().bit_is_set() {}
680 self.eth_mac.macmdiodr.read().md().bits()
681 }
682
683 fn smi_write(&mut self, reg: u8, val: u16) {
685 while self.eth_mac.macmdioar.read().mb().bit_is_set() {}
686 self.eth_mac
687 .macmdiodr
688 .write(|w| unsafe { w.md().bits(val) });
689 self.eth_mac.macmdioar.modify(|_, w| unsafe {
690 w.pa()
691 .bits(ETH_PHY_ADDR)
692 .rda()
693 .bits(reg)
694 .goc()
695 .bits(0b01) .cr()
697 .bits(CLOCK_RANGE)
698 .mb()
699 .set_bit()
700 });
701 while self.eth_mac.macmdioar.read().mb().bit_is_set() {}
702 }
703}
704
705pub struct TxToken<'a>(&'a mut TDesRing);
707
708impl<'a> phy::TxToken for TxToken<'a> {
709 fn consume<R, F>(
710 self,
711 _timestamp: Instant,
712 len: usize,
713 f: F,
714 ) -> smoltcp::Result<R>
715 where
716 F: FnOnce(&mut [u8]) -> smoltcp::Result<R>,
717 {
718 assert!(len <= ETH_BUF_SIZE);
719
720 let result = f(unsafe { self.0.buf_as_slice_mut(len) });
721 self.0.release();
722 result
723 }
724}
725
726pub struct RxToken<'a>(&'a mut RDesRing);
728
729impl<'a> phy::RxToken for RxToken<'a> {
730 fn consume<R, F>(self, _timestamp: Instant, f: F) -> smoltcp::Result<R>
731 where
732 F: FnOnce(&mut [u8]) -> smoltcp::Result<R>,
733 {
734 let result = f(unsafe { self.0.buf_as_slice_mut() });
735 self.0.release();
736 result
737 }
738}
739
740impl<'a> phy::Device<'a> for EthernetDMA<'_> {
742 type RxToken = RxToken<'a>;
743 type TxToken = TxToken<'a>;
744
745 fn capabilities(&self) -> DeviceCapabilities {
746 let mut caps = DeviceCapabilities::default();
747 caps.max_transmission_unit = 1514;
750 caps.max_burst_size = Some(core::cmp::min(ETH_NUM_TD, ETH_NUM_RD));
751 caps
752 }
753
754 fn receive(&mut self) -> Option<(RxToken, TxToken)> {
755 while self.ring.rx.available() && !self.ring.rx.valid() {
757 warn!("Releasing invalid descriptor!");
758 self.ring.rx.release()
759 }
760
761 if self.ring.rx.available() && self.ring.tx.available() {
762 Some((RxToken(&mut self.ring.rx), TxToken(&mut self.ring.tx)))
763 } else {
764 None
765 }
766 }
767
768 fn transmit(&mut self) -> Option<TxToken> {
769 if self.ring.tx.available() {
770 Some(TxToken(&mut self.ring.tx))
771 } else {
772 None
773 }
774 }
775}
776
777impl EthernetDMA<'_> {
778 pub fn number_packets_dropped(&self) -> u32 {
781 self.eth_dma.dmacmfcr.read().mfc().bits() as u32
782 }
783}
784
785pub unsafe fn interrupt_handler() {
786 let eth_dma = &*stm32::ETHERNET_DMA::ptr();
787 eth_dma
788 .dmacsr
789 .write(|w| w.nis().set_bit().ri().set_bit().ti().set_bit());
790}
791
792pub unsafe fn enable_interrupt() {
793 let eth_dma = &*stm32::ETHERNET_DMA::ptr();
794 eth_dma
795 .dmacier
796 .modify(|_, w| w.nie().set_bit().rie().set_bit().tie().set_bit());
797}