1 /*
2 * Copyright (c) 2006-2022, RT-Thread Development Team
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 *
6 * Change Logs:
7 * Date Author Notes
8 * 2022-02-16 Tuber first version
9 */
10
11 #include <rtthread.h>
12 #include <rtdevice.h>
13 #include "board.h"
14 #include <netif/ethernetif.h>
15 #include "drv_eth.h"
16
17 #ifdef BSP_USING_ETH
18
19 static struct eth_device eth_device;
20
21 //DMA接收内存区,必须4字节对齐
22 __align(4) UINT8 eth_dma_tx_buf[ETH_BUF_SIZE];
23 __align(4) UINT8 eth_dma_rx_buf[ETH_BUF_SIZE];
24
25 UINT16 eth_rx_len = 0; //接收状态和长度
26 UINT8 eth_rx_buf[ETH_BUF_SIZE]; //中间缓冲区
27
28 UINT8 eth_mac_addr[] = { 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF };
29
eth_init(rt_device_t dev)30 static rt_err_t eth_init(rt_device_t dev)
31 {
32 return RT_EOK;
33 }
34
eth_open(rt_device_t dev,rt_uint16_t oflag)35 static rt_err_t eth_open(rt_device_t dev, rt_uint16_t oflag)
36 {
37 return RT_EOK;
38 }
39
eth_close(rt_device_t dev)40 static rt_err_t eth_close(rt_device_t dev)
41 {
42 return RT_EOK;
43 }
44
eth_read(rt_device_t dev,rt_off_t pos,void * buffer,rt_size_t size)45 static rt_ssize_t eth_read(rt_device_t dev, rt_off_t pos, void *buffer, rt_size_t size)
46 {
47 rt_set_errno(-RT_ENOSYS);
48 return 0;
49 }
50
eth_write(rt_device_t dev,rt_off_t pos,const void * buffer,rt_size_t size)51 static rt_ssize_t eth_write(rt_device_t dev, rt_off_t pos, const void *buffer, rt_size_t size)
52 {
53 rt_set_errno(-RT_ENOSYS);
54 return 0;
55 }
56
eth_control(rt_device_t dev,int cmd,void * args)57 static rt_err_t eth_control(rt_device_t dev, int cmd, void *args)
58 {
59 switch (cmd)
60 {
61 case NIOCTL_GADDR:
62 /* get mac address */
63 if (args) rt_memcpy(args, eth_mac_addr, 6);
64 else return -RT_ERROR;
65 break;
66 default :
67 break;
68 }
69
70 return RT_EOK;
71 }
72
eth_tx(rt_device_t dev,struct pbuf * p)73 rt_err_t eth_tx(rt_device_t dev, struct pbuf *p)
74 {
75 //判断eth是否处于发送状态
76 if ((R8_ETH_ECON1 & RB_ETH_ECON1_TXRTS) != 0x00)
77 {
78 return ERR_INPROGRESS;
79 }
80
81 //确定缓冲区是否足够
82 if (p->tot_len > sizeof(eth_dma_tx_buf))
83 {
84 return ERR_MEM;
85 }
86
87 //拷贝数据到dma缓冲区
88 rt_memcpy(eth_dma_tx_buf, p->payload, p->tot_len);
89
90 //设置数据长度
91 R16_ETH_ETXLN = p->tot_len;
92
93 //开始发送
94 R8_ETH_ECON1 |= RB_ETH_ECON1_TXRTS;
95
96 return ERR_OK;
97 }
98
eth_rx(rt_device_t dev)99 struct pbuf *eth_rx(rt_device_t dev)
100 {
101 struct pbuf *p = NULL;
102
103 //检查是否有数据
104 if (eth_rx_len == 0)
105 {
106 return NULL;
107 }
108
109 p = pbuf_alloc(PBUF_RAW, eth_rx_len, PBUF_POOL);
110 if (p == NULL)
111 {
112 rt_kprintf("eth_rx: pbuf_alloc failed\n");
113 eth_rx_len = 0;
114 return NULL;
115 }
116
117 //拷贝数据到pbuf
118 rt_memcpy((uint8_t *)((uint8_t *)p->payload), (uint8_t *)((uint8_t *)eth_rx_buf), eth_rx_len);
119 //恢复状态
120 eth_rx_len = 0;
121
122 return p;
123 }
124
read_eth_link_status()125 int read_eth_link_status()
126 {
127 R8_ETH_MIREGADR = 0x01;//状态寄存器
128 R8_ETH_MISTAT |= 0x00; //读MII寄存器
129
130 //获取link状态
131 if ((R16_ETH_MIRD & 0x04) != 0)
132 {
133 return 1; //已插入
134 }
135
136 return 0;
137 }
138
ETH_IRQHandler(void)139 void ETH_IRQHandler(void) /* 以太网中断 */
140 {
141 rt_interrupt_enter();
142
143 //接收到数据包
144 if ((R8_ETH_EIR & RB_ETH_EIR_RXIF) != 0)
145 {
146 //判断缓存区是否有数据
147 if (eth_rx_len == 0)
148 {
149 rt_memcpy(eth_rx_buf, eth_dma_rx_buf, R16_ETH_ERXLN);
150 eth_rx_len = R16_ETH_ERXLN;
151 //通知拿数据
152 eth_device_ready(ð_device);
153 }
154
155 R8_ETH_EIR |= RB_ETH_EIR_RXIF; //清除中断
156 }
157
158 //接收错误
159 if ((R8_ETH_EIR & RB_ETH_EIE_RXERIE) != 0)
160 {
161 R8_ETH_EIR |= RB_ETH_EIE_RXERIE; //清除中断
162 }
163
164 //发送完成
165 if ((R8_ETH_EIR & RB_ETH_EIR_TXIF) != 0)
166 {
167 R8_ETH_EIR |= RB_ETH_EIR_TXIF; //清除中断
168 }
169
170 //发送错误
171 if ((R8_ETH_EIR & RB_ETH_EIE_TXERIE) != 0)
172 {
173 R8_ETH_EIR |= RB_ETH_EIE_TXERIE; //清除中断
174 }
175
176 //Link 变化标志
177 if ((R8_ETH_EIR & RB_ETH_EIR_LINKIF) != 0)
178 {
179 //获取连接状态
180 if (read_eth_link_status())
181 {
182 eth_device_linkchange(ð_device, RT_TRUE);
183 rt_kprintf("eth1: link is up\n");
184 }
185 else
186 {
187 eth_device_linkchange(ð_device, RT_FALSE);
188 rt_kprintf("eth1: link is down\n");
189 }
190
191 R8_ETH_EIR |= RB_ETH_EIR_LINKIF; //清除中断
192 }
193
194 rt_interrupt_leave();
195 }
196
rt_hw_eth_init(void)197 int rt_hw_eth_init(void)
198 {
199 //使能ETH引脚
200 R16_PIN_ANALOG_IE |= RB_PIN_ETH_IE;
201
202 //进入安全访问模式
203 R8_SAFE_ACCESS_SIG = 0x57;
204 R8_SAFE_ACCESS_SIG = 0xA8;
205 //打开以太网时钟
206 R8_SLP_CLK_OFF1 &= (~RB_SLP_CLK_ETH);
207 //打开以太网电源
208 R8_SLP_POWER_CTRL &= (~RB_SLP_ETH_PWR_DN);
209 //退出安全访问模式
210 R8_SAFE_ACCESS_SIG = 0x00;
211
212 //开启以太网中断
213 R8_ETH_EIE |= RB_ETH_EIE_INTIE;
214 //启用以太网接收中断
215 R8_ETH_EIE |= RB_ETH_EIE_RXIE;
216 //R8_ETH_EIE |= RB_ETH_EIE_RXERIE;
217 //启用以太网发送中断
218 R8_ETH_EIE |= RB_ETH_EIR_TXIF;
219 R8_ETH_EIE |= RB_ETH_EIR_TXERIF;
220 //启用Link变化中断
221 R8_ETH_EIE |= RB_ETH_EIE_LINKIE;
222 //启用内置的50欧姆阻抗匹配电阻
223 R8_ETH_EIE |= RB_ETH_EIE_R_EN50;
224
225 //配置接收过滤模式
226 R8_ETH_ERXFCON = RB_ETH_ERXFCON_ANDOR | RB_ETH_ERXFCON_CRCEN;
227
228 //设置发送dma
229 R16_ETH_ETXST = (uint32_t)eth_dma_tx_buf;
230 //设置接收dma
231 R16_ETH_ERXST = (uint32_t)eth_dma_rx_buf;
232 //设置最大接收长度
233 R16_ETH_MAMXFL = sizeof(eth_dma_rx_buf);
234
235 //使能MAC层接收
236 R8_ETH_MACON1 |= RB_ETH_MACON1_MARXEN;
237 //开启硬件CRC
238 R8_ETH_MACON2 |= RB_ETH_MACON2_TXCRCEN;
239 //所有短包填充0至60字节,再4字节 CRC
240 R8_ETH_MACON2 |= 0x20;
241 //使能接收
242 R8_ETH_ECON1 |= RB_ETH_ECON1_RXEN;
243
244 //开启中断
245 NVIC_EnableIRQ(ETH_IRQn);
246
247 //设置回调函数
248 eth_device.parent.init = eth_init;
249 eth_device.parent.open = eth_open;
250 eth_device.parent.close = eth_close;
251 eth_device.parent.read = eth_read;
252 eth_device.parent.write = eth_write;
253 eth_device.parent.control = eth_control;
254 eth_device.parent.user_data = RT_NULL;
255 eth_device.eth_rx = eth_rx;
256 eth_device.eth_tx = eth_tx;
257
258 return eth_device_init(&(eth_device), "e0");
259 }
260 INIT_DEVICE_EXPORT(rt_hw_eth_init);
261 #endif /* BSP_USING_ETH */
262