embox

Форк
0
/
stm32cube_eth.c 
276 строк · 7.3 Кб
1
/**
2
 * @file
3
 * @brief
4
 *
5
 * @author  Anton Kozlov
6
 * @date    07.08.2014
7
 */
8

9
#include <errno.h>
10
#include <string.h>
11
#include <stdio.h>
12
#include <util/math.h>
13
#include <kernel/irq.h>
14
#include <hal/reg.h>
15
#include <net/netdevice.h>
16
#include <net/inetdevice.h>
17
#include <net/l0/net_entry.h>
18
#include <net/l2/ethernet.h>
19
#include <net/l3/arp.h>
20
#include <net/util/show_packet.h>
21
#include <drivers/net/stm32cube_eth.h>
22
#include <util/log.h>
23
#include <embox/unit.h>
24
#include <arm/cpu_cache.h>
25

26
EMBOX_UNIT_INIT(stm32eth_init);
27

28
#define STM32ETH_IRQ   OPTION_GET(NUMBER, irq)
29

30
static ETH_HandleTypeDef stm32_eth_handler;
31

32
static ETH_DMADescTypeDef DMARxDscrTab[ETH_RXBUFNB] \
33
	__attribute__ ((aligned (4))) SRAM_DEVICE_MEM_SECTION;
34

35
static uint8_t Rx_Buff[ETH_RXBUFNB][ETH_RX_BUF_SIZE] \
36
	 __attribute__ ((aligned (4))) SRAM_NOCACHE_SECTION;
37

38
#if ETH_TXBUFNB == 0
39
#undef  ETH_TXBUFNB
40
#define ETH_TXBUFNB 4
41
#define TX_NO_BUFF  1
42
#endif
43

44
#ifdef TX_NO_BUFF
45

46
#undef TX_NO_BUFF
47
#define TX_NO_BUFF  0
48

49
#else /* TX_NO_BUFF */
50
static uint8_t Tx_Buff[ETH_TXBUFNB][ETH_TX_BUF_SIZE] \
51
	__attribute__ ((aligned (4))) SRAM_NOCACHE_SECTION;
52

53
#endif /* TX_NO_BUFF */
54

55
static ETH_DMADescTypeDef DMATxDscrTab[ETH_TXBUFNB] \
56
	__attribute__ ((aligned (4))) SRAM_DEVICE_MEM_SECTION;
57

58
static void low_level_init(unsigned char mac[6]) {
59
	memset(&stm32_eth_handler, 0, sizeof(stm32_eth_handler));
60

61
	stm32_eth_handler.Instance = (ETH_TypeDef *) ETH_BASE;
62
	/* Fill ETH_InitStructure parametrs */
63
	stm32_eth_handler.Init.MACAddr = mac;
64
	stm32_eth_handler.Init.AutoNegotiation = ETH_AUTONEGOTIATION_DISABLE;
65
	stm32_eth_handler.Init.Speed = ETH_SPEED_100M;
66
	stm32_eth_handler.Init.DuplexMode = ETH_MODE_FULLDUPLEX;
67
	stm32_eth_handler.Init.MediaInterface = ETH_MEDIA_INTERFACE_RMII;
68
	stm32_eth_handler.Init.ChecksumMode = ETH_CHECKSUM_BY_SOFTWARE;
69
	stm32_eth_handler.Init.PhyAddress = PHY_ADDRESS;
70
	stm32_eth_handler.Init.RxMode = ETH_RXINTERRUPT_MODE;
71

72

73
	if (HAL_OK != HAL_ETH_Init(&stm32_eth_handler)) {
74
		log_error("HAL_ETH_Init error\n");
75
	}
76

77
	if (stm32_eth_handler.State == HAL_ETH_STATE_READY) {
78
		log_info("STATE_READY sp %d duplex %d\n",
79
			stm32_eth_handler.Init.Speed, stm32_eth_handler.Init.DuplexMode);
80
	}
81

82
	/*(#)Initialize Ethernet DMA Descriptors in chain mode and point to allocated buffers:*/
83
	HAL_ETH_DMATxDescListInit(&stm32_eth_handler, DMATxDscrTab, &Tx_Buff[0][0],
84
			ETH_TXBUFNB); /*for Transmission process*/
85
	if (HAL_OK != HAL_ETH_DMARxDescListInit(&stm32_eth_handler,
86
			DMARxDscrTab, &Rx_Buff[0][0],
87
			ETH_RXBUFNB)) { /*for Reception process*/
88
		log_error("HAL_ETH_DMARxDescListInit error\n");
89
	}
90

91
	/* (#)Enable MAC and DMA transmission and reception: */
92
	HAL_ETH_Start(&stm32_eth_handler);
93

94
}
95

96
static struct sk_buff *low_level_input(void) {
97
	struct sk_buff *skb;
98
	int len;
99
	uint8_t *buffer;
100

101
	/* get received frame */
102
	if (HAL_ETH_GetReceivedFrame_IT(&stm32_eth_handler) != HAL_OK) {
103
		return NULL;
104
	}
105

106
	/* Obtain the size of the packet and put it into the "len" variable. */
107
	len = stm32_eth_handler.RxFrameInfos.length;
108
	buffer = (uint8_t *) stm32_eth_handler.RxFrameInfos.buffer;
109

110
	skb = NULL;
111

112
	/* We allocate a pbuf chain of pbufs from the Lwip buffer pool */
113
	skb = skb_alloc(len);
114

115
	/* copy received frame to pbuf chain */
116
	if (skb != NULL) {
117
		memcpy(skb->mac.raw, buffer, len);
118
	} else {
119
		log_error("skb_alloc failed\n");
120
	}
121

122
	{
123
		uint32_t i = 0;
124
		__IO ETH_DMADescTypeDef *dmarxdesc;
125

126
		/* Release descriptors to DMA */
127
		dmarxdesc = stm32_eth_handler.RxFrameInfos.FSRxDesc;
128

129
		/* Set Own bit in Rx descriptors: gives the buffers back to DMA */
130
		for (i = 0; i < stm32_eth_handler.RxFrameInfos.SegCount; i++) {
131
			dmarxdesc->Status |= ETH_DMARXDESC_OWN;
132
			dmarxdesc = (ETH_DMADescTypeDef *)(dmarxdesc->Buffer2NextDescAddr);
133
		}
134

135
		/* Clear Segment_Count */
136
		stm32_eth_handler.RxFrameInfos.SegCount = 0;
137

138
		/* When Rx Buffer unavailable flag is set: clear it and resume reception */
139
		if ((stm32_eth_handler.Instance->DMASR & ETH_DMASR_RBUS) != (uint32_t)RESET) {
140
			/* Clear RBUS ETHERNET DMA flag */
141
			stm32_eth_handler.Instance->DMASR = ETH_DMASR_RBUS;
142
			/* Resume DMA reception */
143
			stm32_eth_handler.Instance->DMARPDR = 0;
144
		}
145
	}
146

147
	return skb;
148
}
149

150

151
static int stm32eth_xmit(struct net_device *dev, struct sk_buff *skb);
152
static int stm32eth_open(struct net_device *dev);
153
static int stm32eth_set_mac(struct net_device *dev, const void *addr);
154
static const struct net_driver stm32eth_ops = {
155
		.xmit = stm32eth_xmit,
156
		.start = stm32eth_open,
157
		.set_macaddr = stm32eth_set_mac,
158
};
159

160
static int stm32eth_open(struct net_device *dev) {
161
	low_level_init(dev->dev_addr);
162

163
	return 0;
164
}
165

166
static int stm32eth_set_mac(struct net_device *dev, const void *addr) {
167
	ETH_TypeDef *regs = (ETH_TypeDef *) ETH_BASE;
168

169
	memcpy(dev->dev_addr, addr, ETH_ALEN);
170

171
	regs->MACA0HR = ((uint32_t) dev->dev_addr[5] << 8) |
172
	                ((uint32_t) dev->dev_addr[4] << 0);
173

174
	regs->MACA0LR = ((uint32_t) dev->dev_addr[3] << 24) |
175
	                ((uint32_t) dev->dev_addr[2] << 16) |
176
	                ((uint32_t) dev->dev_addr[1] << 8)  |
177
	                ((uint32_t) dev->dev_addr[0] << 0);
178

179
	return ENOERR;
180
}
181

182

183
#if defined (TX_NO_BUFF) && TX_NO_BUFF == 0
184
static int stm32eth_xmit(struct net_device *dev, struct sk_buff *skb) {
185
	__IO ETH_DMADescTypeDef *dma_tx_desc;
186

187
	dma_tx_desc = stm32_eth_handler.TxDesc;
188
	/* Transmit skbuff directly without any buffer. */
189
	dma_tx_desc->Buffer1Addr = (uint32_t) skb->mac.raw;
190

191
	/* Prepare transmit descriptors to give to DMA */
192
	if (0 != HAL_ETH_TransmitFrame(&stm32_eth_handler, skb->len)) {
193
		log_error("HAL_ETH_TransmitFrame failed\n");
194
		return -1;
195
	}
196
	/* Wait until packet transmitted and descriptor released. */
197
	while (dma_tx_desc->Status & ETH_DMATXDESC_OWN)
198
		;
199
	skb_free(skb);
200

201
	return 0;
202
}
203
#else
204
static int stm32eth_xmit(struct net_device *dev, struct sk_buff *skb) {
205
	__IO ETH_DMADescTypeDef *dma_tx_desc;
206

207
	dma_tx_desc = stm32_eth_handler.TxDesc;
208
	memcpy((void *)dma_tx_desc->Buffer1Addr, skb->mac.raw, skb->len);
209

210
	/* Prepare transmit descriptors to give to DMA */
211
	if (0 != HAL_ETH_TransmitFrame(&stm32_eth_handler, skb->len)) {
212
		log_error("HAL_ETH_TransmitFrame failed\n");
213
		return -1;
214
	}
215
	skb_free(skb);
216

217
	return 0;
218
}
219
#endif
220

221
static irq_return_t stm32eth_interrupt(unsigned int irq_num, void *dev_id) {
222
	struct net_device *nic_p = dev_id;
223
	struct sk_buff *skb;
224
	ETH_HandleTypeDef *heth = &stm32_eth_handler;
225

226
	if (!nic_p) {
227
		return IRQ_NONE;
228
	}
229

230
	if (heth->Instance->DMASR & ETH_DMA_FLAG_FBE) {
231
		log_error("DMA error: DMASR = 0x%08x\n", heth->Instance->DMASR);
232
	}
233

234
	/* Frame received */
235
	if (__HAL_ETH_DMA_GET_FLAG(heth, ETH_DMA_FLAG_R)) {
236
		/* Receive complete callback */
237
		while (NULL != (skb = low_level_input())) {
238
			skb->dev = nic_p;
239

240
			show_packet(skb->mac.raw, skb->len, "rx");
241

242
			netif_rx(skb);
243
		}
244
		/* Clear the Eth DMA Rx IT pending bits */
245
		__HAL_ETH_DMA_CLEAR_IT(heth, ETH_DMA_IT_R);
246
	}
247
	__HAL_ETH_DMA_CLEAR_IT(heth, ETH_DMA_IT_NIS);
248

249
	return IRQ_HANDLED;
250
}
251

252
static struct net_device *stm32eth_netdev;
253
static int stm32eth_init(void) {
254
	int res;
255
	struct net_device *nic;
256

257
	nic = (struct net_device *) etherdev_alloc(0);
258
	if (nic == NULL) {
259
		return -ENOMEM;
260
	}
261

262
	nic->drv_ops = &stm32eth_ops;
263
	nic->irq = STM32ETH_IRQ;
264
	nic->base_addr = ETH_BASE;
265

266
	stm32eth_netdev = nic;
267

268
	res = irq_attach(nic->irq, stm32eth_interrupt, 0, stm32eth_netdev, "");
269
	if (res < 0) {
270
		return res;
271
	}
272

273
	return inetdev_register_dev(nic);
274
}
275

276
STATIC_IRQ_ATTACH(STM32ETH_IRQ, stm32eth_interrupt, stm32eth_netdev);
277

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.