libopencm3
A free/libre/open-source firmware library for various ARM Cortex-M3 microcontrollers.
mac_stm32fxx7.c
Go to the documentation of this file.
1/** @defgroup ethernet_mac_stm32fxx7_file MAC STM32Fxx7
2 *
3 * @ingroup ETH
4 *
5 * @brief <b>Ethernet MAC STM32Fxx7 Drivers</b>
6 *
7 * @version 1.0.0
8 * @author @htmlonly &copy; @endhtmlonly 2013 Frantisek Burian <BuFran@seznam.cz>
9 *
10 * @date 1 September 2013
11 *
12 *
13 * LGPL License Terms @ref lgpl_license
14 */
15/*
16 * This file is part of the libopencm3 project.
17 *
18 * Copyright (C) 2013 Frantisek Burian <BuFran@seznam.cz>
19 *
20 * This library is free software: you can redistribute it and/or modify
21 * it under the terms of the GNU Lesser General Public License as published by
22 * the Free Software Foundation, either version 3 of the License, or
23 * (at your option) any later version.
24 *
25 * This library is distributed in the hope that it will be useful,
26 * but WITHOUT ANY WARRANTY; without even the implied warranty of
27 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
28 * GNU Lesser General Public License for more details.
29 *
30 * You should have received a copy of the GNU Lesser General Public License
31 * along with this library. If not, see <http://www.gnu.org/licenses/>.
32 */
33
34#include <string.h>
38#include <libopencm3/cm3/nvic.h>
39
40/**@{*/
41
42uint32_t TxBD;
43uint32_t RxBD;
44
45/*---------------------------------------------------------------------------*/
46/** @brief Set MAC to the PHY
47 *
48 * @param[in] mac uint8_t* Desired MAC
49 */
50void eth_set_mac(const uint8_t *mac)
51{
52 ETH_MACAHR(0) = ((uint32_t)mac[5] << 8) | (uint32_t)mac[4] |
54 ETH_MACALR(0) = ((uint32_t)mac[3] << 24) | ((uint32_t)mac[2] << 16) |
55 ((uint32_t)mac[1] << 8) | mac[0];
56}
57
58/*---------------------------------------------------------------------------*/
59/** @brief Initialize buffers and descriptors.
60 *
61 * @param[in] buf uint8_t* Memory area for the descriptors and data buffers
62 * @param[in] nTx uint32_t Count of transmit descriptors (equal to count of buffers)
63 * @param[in] nRx uint32_t Count of receive descriptors (equal to count of buffers)
64 * @param[in] cTx uint32_t Bytes in each transmit buffer, must be a
65 * multiple of 4
66 * @param[in] cRx uint32_t Bytes in each receive buffer, must be a
67 * multiple of 4
68 * @param[in] isext bool true if extended descriptors should be used
69 *
70 * Note, the space passed via buf pointer must be large enough to
71 * hold all the buffers and one descriptor per buffer.
72 */
73void eth_desc_init(uint8_t *buf, uint32_t nTx, uint32_t nRx, uint32_t cTx,
74 uint32_t cRx, bool isext)
75{
76 uint32_t bd = (uint32_t)buf;
77 uint32_t sz = isext ? ETH_DES_EXT_SIZE : ETH_DES_STD_SIZE;
78
79 memset(buf, 0, nTx * (cTx + sz) + nRx * (cRx + sz));
80
81 /* enable / disable extended frames */
82 if (isext) {
84 } else {
85 ETH_DMABMR &= ~ETH_DMABMR_EDFE;
86 }
87
88 TxBD = bd;
89 while (--nTx > 0) {
91 ETH_DES2(bd) = bd + sz;
92 ETH_DES3(bd) = bd + sz + cTx;
93 bd = ETH_DES3(bd);
94 }
95
97 ETH_DES2(bd) = bd + sz;
98 ETH_DES3(bd) = TxBD;
99 bd += sz + cTx;
100
101 RxBD = bd;
102 while (--nRx > 0) {
104 ETH_DES1(bd) = ETH_RDES1_RCH | cRx;
105 ETH_DES2(bd) = bd + sz;
106 ETH_DES3(bd) = bd + sz + cRx;
107 bd = ETH_DES3(bd);
108 }
109
111 ETH_DES1(bd) = ETH_RDES1_RCH | cRx;
112 ETH_DES2(bd) = bd + sz;
113 ETH_DES3(bd) = RxBD;
114
115 ETH_DMARDLAR = (uint32_t) RxBD;
116 ETH_DMATDLAR = (uint32_t) TxBD;
117}
118
119/*---------------------------------------------------------------------------*/
120/** @brief Transmit packet
121 *
122 * @param[in] ppkt uint8_t* Pointer to the beginning of the packet
123 * @param[in] n uint32_t Size of the packet
124 * @returns bool true, if success
125 */
126bool eth_tx(uint8_t *ppkt, uint32_t n)
127{
128 if (ETH_DES0(TxBD) & ETH_TDES0_OWN) {
129 return false;
130 }
131
132 memcpy((void *)ETH_DES2(TxBD), ppkt, n);
133
136 TxBD = ETH_DES3(TxBD);
137
140 ETH_DMATPDR = 0;
141 }
142
143 return true;
144}
145
146/*---------------------------------------------------------------------------*/
147/** @brief Receive packet
148 *
149 * @param[inout] ppkt uint8_t* Pointer to the data buffer where to store data
150 * @param[inout] len uint32_t* Pointer to the variable with the packet length
151 * @param[in] maxlen uint32_t Maximum length of the packet
152 * @returns bool true, if the buffer contains readed packet data
153 */
154bool eth_rx(uint8_t *ppkt, uint32_t *len, uint32_t maxlen)
155{
156 bool fs = false;
157 bool ls = false;
158 bool overrun = false;
159 uint32_t l = 0;
160
161 while (!(ETH_DES0(RxBD) & ETH_RDES0_OWN) && !ls) {
163
164 fs |= ETH_DES0(RxBD) & ETH_RDES0_FS;
165 ls |= ETH_DES0(RxBD) & ETH_RDES0_LS;
166 /* frame buffer overrun ?*/
167 overrun |= fs && (maxlen < l);
168
169 if (fs && !overrun) {
170 memcpy(ppkt, (void *)ETH_DES2(RxBD), l);
171 ppkt += l;
172 *len += l;
173 maxlen -= l;
174 }
175
177 RxBD = ETH_DES3(RxBD);
178 }
179
182 ETH_DMARPDR = 0;
183 }
184
185 return fs && ls && !overrun;
186}
187
188/*---------------------------------------------------------------------------*/
189/** @brief Start the Ethernet DMA processing
190 */
191void eth_start(void)
192{
196
199}
200
201/*---------------------------------------------------------------------------*/
202/** @brief Initialize ethernet
203 *
204 * This function will initialize ethernet, set up clocks, and initialize DMA.
205 *
206 * @param[in] phy phy id
207 * @param[in] clock enum eth_clk Core clock speed
208 */
209void eth_init(uint8_t phy, enum eth_clk clock)
210{
211 ETH_MACMIIAR = clock;
212 phy_reset(phy);
213
217 ETH_MACHTHR = 0; /* pass all frames */
218 ETH_MACHTLR = 0;
219 ETH_MACFCR = (0x100 << ETH_MACFCR_PT_SHIFT);
220 ETH_MACVLANTR = 0;
226}
227
228/*---------------------------------------------------------------------------*/
229/** @brief Enable the Ethernet IRQ
230 *
231 * @param[in] reason uint32_t Which irq will be enabled
232 */
233void eth_irq_enable(uint32_t reason)
234{
235 ETH_DMAIER |= reason;
236}
237
238/*---------------------------------------------------------------------------*/
239/** @brief Disable the Ethernet IRQ
240 *
241 * @param[in] reason uint32_t Which irq will be disabled
242 */
243void eth_irq_disable(uint32_t reason)
244{
245 ETH_DMAIER &= ~reason;
246}
247
248/*---------------------------------------------------------------------------*/
249/** @brief Check if IRQ is pending
250 *
251 * @param[in] reason uint32_t Which irq type has to be tested
252 * @returns bool true, if IRQ is pending
253 */
254bool eth_irq_is_pending(uint32_t reason)
255{
256 return (ETH_DMASR & reason) != 0;
257}
258
259/*---------------------------------------------------------------------------*/
260/** @brief Check if IRQ is pending, and acknowledge it
261 *
262 * @param[in] reason uint32_t Which irq type has to be tested
263 * @returns bool true, if IRQ is pending
264 */
265bool eth_irq_ack_pending(uint32_t reason)
266{
267 reason &= ETH_DMASR;
268 ETH_DMASR = reason;
269 return reason != 0;
270}
271
272/*---------------------------------------------------------------------------*/
273/** @brief Enable checksum offload feature
274 *
275 * This function will enable the Checksum offload feature for all of the
276 * transmit descriptors. Note to use this feature, descriptors must be in
277 * extended format.
278 */
280{
281 uint32_t tab = TxBD;
282 do {
284 tab = ETH_DES3(tab);
285 }
286 while (tab != TxBD);
287
289}
290
291/*---------------------------------------------------------------------------*/
292/** @brief Process pending SMI transaction and wait to be done.
293 */
294static void eth_smi_transact(void)
295{
296 /* Begin transaction. */
298
299 /* Wait for not busy. */
301}
302
303/*---------------------------------------------------------------------------*/
304/** @brief Write 16-bit register to the PHY
305 *
306 * @param[in] phy uint8_t ID of the PHY (defaults to 1)
307 * @param[in] reg uint8_t Register address
308 * @param[in] data uint16_t Data to write
309 */
310void eth_smi_write(uint8_t phy, uint8_t reg, uint16_t data)
311{
312 /* Write operation MW=1*/
313 ETH_MACMIIAR = (ETH_MACMIIAR & ETH_MACMIIAR_CR) | /* save clocks */
314 (phy << ETH_MACMIIAR_PA_SHIFT) |
315 (reg << ETH_MACMIIAR_MR_SHIFT) |
317
319
321}
322
323/*---------------------------------------------------------------------------*/
324/** @brief Read the 16-bit register from the PHY
325 *
326 * @param[in] phy uint8_t ID of the PHY (defaults to 1)
327 * @param[in] reg uint8_t Register address
328 * @returns uint16_t Readed data
329 */
330uint16_t eth_smi_read(uint8_t phy, uint8_t reg)
331{
332 /* Read operation MW=0*/
333 ETH_MACMIIAR = (ETH_MACMIIAR & ETH_MACMIIAR_CR) | /* save clocks */
334 (phy << ETH_MACMIIAR_PA_SHIFT) |
335 (reg << ETH_MACMIIAR_MR_SHIFT);
336
338
339 return (uint16_t)(ETH_MACMIIDR & ETH_MACMIIDR_MD);
340}
341
342/*---------------------------------------------------------------------------*/
343/** @brief Process the bit-operation on PHY register
344 *
345 * @param[in] phy uint8_t ID of the PHY (defaults to 1)
346 * @param[in] reg uint8_t Register address
347 * @param[in] bits uint16_t Bits that have to be set (or'ed)
348 * @param[in] mask uint16_t Bits that have to be clear (and'ed)
349 */
350void eth_smi_bit_op(uint8_t phy, uint8_t reg, uint16_t bits, uint16_t mask)
351{
352 uint16_t val = eth_smi_read(phy, reg);
353 eth_smi_write(phy, reg, (val & mask) | bits);
354}
355
356/*---------------------------------------------------------------------------*/
357/** @brief Clear bits in the register
358 *
359 * @param[in] phy uint8_t ID of the PHY (defaults to 1)
360 * @param[in] reg uint8_t Register address
361 * @param[in] clearbits uint16_t Bits that have to be cleared
362 */
363void eth_smi_bit_clear(uint8_t phy, uint8_t reg, uint16_t clearbits)
364{
365 uint16_t val = eth_smi_read(phy, reg);
366 eth_smi_write(phy, reg, val & (uint16_t)~(clearbits));
367}
368
369/*---------------------------------------------------------------------------*/
370/** @brief Set bits in the register
371 *
372 * @param[in] phy uint8_t ID of the PHY (defaults to 1)
373 * @param[in] reg uint8_t Register address
374 * @param[in] setbits uint16_t Bits that have to be set (or'ed)
375 */
376void eth_smi_bit_set(uint8_t phy, uint8_t reg, uint16_t setbits)
377{
378 uint16_t val = eth_smi_read(phy, reg);
379 eth_smi_write(phy, reg, val | setbits);
380}
381
382/*---------------------------------------------------------------------------*/
383
384/**@}*/
#define ETH_MACCR
Definition: mac_stm32fxx7.h:51
#define ETH_MACMIIAR_CR
#define ETH_DES2(base)
#define ETH_DMABMR_EDFE
#define ETH_MACCR_APCS
#define ETH_MACMIIDR_MD
#define ETH_DMARDLAR
#define ETH_MACA0HR_MACA0H
#define ETH_MACFFR_PM
#define ETH_DES1(base)
#define ETH_TDES0_OWN
#define ETH_MACFCR
Definition: mac_stm32fxx7.h:57
#define ETH_DMASR_TBUS
#define ETH_MACCR_CSTF
#define ETH_DES_EXT_SIZE
#define ETH_RDES0_FS
#define ETH_DMABMR_PBL_SHIFT
#define ETH_DMABMR
Definition: mac_stm32fxx7.h:97
#define ETH_MACMIIAR
Definition: mac_stm32fxx7.h:55
#define ETH_MACMIIAR_MB
#define ETH_DMASR_RBUS
#define ETH_DMAOMR_ST
#define ETH_DMAOMR_TSF
#define ETH_DMABMR_RDP_SHIFT
#define ETH_DMAOMR_DFRF
#define ETH_DMATPDR
Definition: mac_stm32fxx7.h:98
#define ETH_MACAHR(i)
Definition: mac_stm32fxx7.h:66
#define ETH_RDES1_RCH
#define ETH_DMAOMR_OSF
#define ETH_DMAOMR_FTF
#define ETH_RDES0_OWN
#define ETH_DMAOMR_RSF
#define ETH_DMABMR_FB
#define ETH_TDES0_CIC_IPPLPH
#define ETH_MACMIIDR
Definition: mac_stm32fxx7.h:56
#define ETH_DMARPDR
Definition: mac_stm32fxx7.h:99
#define ETH_MACMIIAR_MR_SHIFT
#define ETH_MACCR_RE
#define ETH_MACFFR_RA
#define ETH_DES3(base)
#define ETH_MACVLANTR
Definition: mac_stm32fxx7.h:58
#define ETH_MACCR_DM
#define ETH_MACCR_TE
#define ETH_RDES0_LS
#define ETH_DMASR
#define ETH_RDES0_FL
#define ETH_DMABMR_USP
#define ETH_DES0(base)
#define ETH_MACMIIAR_PA_SHIFT
#define ETH_DMAOMR_FEF
#define ETH_MACFCR_PT_SHIFT
#define ETH_DMAOMR
#define ETH_DMATDLAR
#define ETH_RDES0_FL_SHIFT
#define ETH_MACALR(i)
Definition: mac_stm32fxx7.h:68
#define ETH_TDES0_LS
#define ETH_DMAIER
#define ETH_DMABMR_AAB
#define ETH_MACCR_RD
eth_clk
#define ETH_MACCR_IPCO
#define ETH_DMAOMR_DTCEFD
#define ETH_MACFFR
Definition: mac_stm32fxx7.h:52
#define ETH_TDES0_TCH
#define ETH_MACHTHR
Definition: mac_stm32fxx7.h:53
#define ETH_DMAOMR_SR
#define ETH_DES_STD_SIZE
#define ETH_MACCR_FES
#define ETH_TDES0_FS
#define ETH_MACHTLR
Definition: mac_stm32fxx7.h:54
#define ETH_TDES1_TBS1
#define ETH_DMABMR_PM_2_1
#define ETH_MACMIIAR_MW
static void eth_smi_transact(void)
Process pending SMI transaction and wait to be done.
void eth_irq_enable(uint32_t reason)
Enable the Ethernet IRQ.
bool eth_irq_ack_pending(uint32_t reason)
Check if IRQ is pending, and acknowledge it.
bool eth_tx(uint8_t *ppkt, uint32_t n)
Transmit packet.
void eth_enable_checksum_offload(void)
Enable checksum offload feature.
void eth_desc_init(uint8_t *buf, uint32_t nTx, uint32_t nRx, uint32_t cTx, uint32_t cRx, bool isext)
Initialize buffers and descriptors.
Definition: mac_stm32fxx7.c:73
void eth_irq_disable(uint32_t reason)
Disable the Ethernet IRQ.
void eth_smi_write(uint8_t phy, uint8_t reg, uint16_t data)
Write 16-bit register to the PHY.
bool eth_rx(uint8_t *ppkt, uint32_t *len, uint32_t maxlen)
Receive packet.
uint16_t eth_smi_read(uint8_t phy, uint8_t reg)
Read the 16-bit register from the PHY.
void eth_init(uint8_t phy, enum eth_clk clock)
Initialize ethernet.
uint32_t RxBD
Definition: mac_stm32fxx7.c:43
void eth_smi_bit_clear(uint8_t phy, uint8_t reg, uint16_t clearbits)
Clear bits in the register.
bool eth_irq_is_pending(uint32_t reason)
Check if IRQ is pending.
void eth_set_mac(const uint8_t *mac)
Set MAC to the PHY.
Definition: mac_stm32fxx7.c:50
uint32_t TxBD
Definition: mac_stm32fxx7.c:42
void eth_start(void)
Start the Ethernet DMA processing.
void eth_smi_bit_set(uint8_t phy, uint8_t reg, uint16_t setbits)
Set bits in the register.
void eth_smi_bit_op(uint8_t phy, uint8_t reg, uint16_t bits, uint16_t mask)
Process the bit-operation on PHY register.
void phy_reset(uint8_t phy)
Reset the PHY.
Definition: phy.c:57