1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
//! WIP. This module contains ethernet code for the H7, for use with its Synopsys ethernet
//! hardware.
//! With the `network` feature enabled, allows support for the [smoltcp stack](https://docs.rs/smoltcp/latest/smoltcp/).
//! See H743 RM, chapter 58.
//! https://www.keil.com/pack/doc/CMSIS/Driver/html/group__eth__interface__gr.html ?
use core::ops::Deref;
use critical_section::with;
use smoltcp::{
self,
phy::{self, Device, DeviceCapabilities, Medium},
time::Instant,
};
use crate::{
error::Result,
pac::{self, ETHERNET_DMA, ETHERNET_MAC, ETHERNET_MTL, RCC},
util::RccPeriph,
};
/// Configuration data for Ethernet
pub struct EthConfig {}
// impl Default for EthConfig {
// fn default() -> Self {
// Self {
// mode: SpiMode::mode0(),
// comm_mode: SpiCommMode::FullDuplex,
// slave_select: SlaveSelect::Software,
// data_size: DataSize::D8,
// fifo_reception_thresh: ReceptionThresh::D8,
// }
// }
// }
/// Represents an ethernet peripheral.
pub struct Eth<RDma, RMac, RMtl> {
pub regs_dma: RDma,
pub regs_mac: RMac,
pub regs_mtl: RMtl,
pub cfg: EthConfig,
}
impl<RDma, RMac, RMtl> Eth<RDma, RMac, RMtl>
where
RDma: Deref<Target = pac::ethernet_dma::RegisterBlock> + RccPeriph,
RMac: Deref<Target = pac::ethernet_mac::RegisterBlock> + RccPeriph,
RMtl: Deref<Target = pac::ethernet_mtl::RegisterBlock> + RccPeriph,
{
/// Initialize an ethernet peripheral, including configuration register writes, and enabling and resetting
/// its RCC peripheral clock.
pub fn new(regs: R, cfg: EthConfig) -> Self {
with(|_| {
let rcc = unsafe { &(*RCC::ptr()) };
R::en_reset(rcc);
});
Self { regs, cfg }
}
/// H743 RM, section 58.9.1: DMA initialization
pub fn init_dma(&mut self) -> Result<()> {
// Complete the following steps to initialize the DMA:
// 1. Provide a software reset to reset all MAC internal registers and logic (bit 0 of DMA
// mode register (ETH_DMAMR)).
self.regs_dma.dmamr.write(|w| w.swr().bit(true));
// 2. Wait for the completion of the reset process (poll bit 0 of the DMA mode register
// (ETH_DMAMR), which is cleared when the reset operation is completed).
// todo: Use DmaError instead?
bounded_loop!(
self.regs_dma.dmamr.read().swr().bit_is_set(),
Error::RegisterUnchanged
);
// 3. Program the following fields to initialize the System bus mode register
// (ETH_DMASBMR):
self.regs_dma.dmasbmr.modify(|_, w| {
// todo
// a)AAL
w.aal.bits(0);
// b) Fixed burst or undefined burst
w.aal.bits(0);
// c) Burst mode values in case of AHB bus interface.
w.aal.bits(0);
// d) If fixed length value is enabled, select the maximum burst length possible on the
// AXI Bus (bits [7:1])
w.aal.bits(0)
});
// 4. Create a transmit and a receive descriptor list. In addition, ensure that the receive
// descriptors are owned by the DMA (set bit 31 of TDES3/RDES3 descriptor). For more
// information on descriptors, refer to Section 58.10: Descriptors.
// Note:
// Descriptor address from start to end of the ring should not cross the 4GB boundary.
//
// 5.
// Program ETH_DMACTXRLR and ETH_DMACRXRLR registers (see Channel Tx
// descriptor ring length register (ETH_DMACTXRLR) and Channel Rx descriptor ring
// length register (ETH_DMACRXRLR)). The programmed ring length must be at least 4.
//
// 6. Initialize receive and transmit descriptor list address with the base address of transmit
// and receive descriptor (Channel Tx descriptor list address register
// (ETH_DMACTXDLAR), Channel Rx descriptor list address register
// (ETH_DMACRXDLAR)). In addition, program the transmit and receive tail pointer
// registers that inform the DMA about the available descriptors (see Channel Tx
// descriptor tail pointer register (ETH_DMACTXDTPR) and Channel Rx descriptor tail
// pointer register (ETH_DMACRXDTPR)).
//
// 7. Program ETH_DMACCR, ETH_DMACTXCR and ETH_DMACRXCR registers (see
// Channel control register (ETH_DMACCR) and Channel transmit control register
// (ETH_DMACTXCR)) to configure the parameters such as the maximum burst-length
// (PBL) initiated by the DMA, descriptor skip lengths, OSP for TxDMA, RBSZ for
// RxDMA.
//
// 8. Enable the interrupts by programming the ETH_DMACIER register (see Channel
// interrupt enable register (ETH_DMACIER)).
//
// 9. Start the Receive and Transmit DMAs by setting SR (bit 0) of Channel receive control
// register (ETH_DMACRXCR) and ST (bit 0) of the ETH_DMACTXCR (see Channel
// transmit control register (ETH_DMACTXCR)).
}
/// H743 RM, section 58.9.2: MTL initialization
pub fn init_mtl(&mut self) {
// Complete the following steps to initialize the MTL registers:
// 1. Program the following fields to initialize the operating mode in the ETH_MTLTXQOMR
// (see Tx queue operating mode Register (ETH_MTLTXQOMR)).
self.regs_mtl.mtltx_qomr.modify(|_, w| {
// a) Transmit Store And Forward (TSF) or Transmit Threshold Control (TTC) if the
// Threshold mode is used.
w.tsf().bits(0);
// b) Transmit Queue Enable (TXQEN) to value 2‘b10 to enable Transmit Queue 0.
w.txqen().bits(0);
// c) Transmit Queue Size (TQS).
w.tqs().bits(0)
});
// 2. Program the following fields to initialize the operating mode in the ETH_MTLRXQOMR
// register (see Rx queue operating mode register (ETH_MTLRXQOMR)):
self.regs_mtl.mtltx_qomr.modify(|_, w| {
// a) Receive Store and Forward (RSF) or RTC if Threshold mode is used.
w.rsf().bits(0);
// b) Flow Control Activation and De-activation thresholds for MTL Receive FIFO (RFA
// and RFD).
w.rfa().bits(0);
w.rfd().bits(0);
// c) Error Packet and undersized good Packet forwarding enable (FEP and FUP).
w.fep().bits(0);
w.fup().bits(0);
// d)Receive Queue Size (RQS).
w.rqs().bits(0)
});
}
/// H743 RM, section 58.9.3: MAC initialization
pub fn init_mac(&mut self) {}
}