GadgetSeed  0.9.6
stm32f7xxx-disc_ether.c
[詳解]
1 /** @file
2  @brief STM32F7XXX Discovery Ether
3 
4  @date 2017.02.05
5  @author Takashi SHUDO
6 */
7 
8 #include "sysconfig.h"
9 #include "device.h"
10 #include "interrupt.h"
11 #include "str.h"
12 #include "tkprintf.h"
13 #include "device/ether_ioctl.h"
14 #include "task/event.h"
15 #include "task/syscall.h"
16 
17 #include "stm32f7xx_hal_conf.h"
18 #include "stm32f7xx_hal_eth.h"
19 
20 //#define DEBUGKBITS 0x01
21 #include "dkprintf.h"
22 
23 
24 /* LAN8742A PHY Address*/
25 #define LAN8742A_PHY_ADDRESS 0x00U
26 
27 #define RMII_TXD1_Pin GPIO_PIN_14
28 #define RMII_TXD1_GPIO_Port GPIOG
29 #define RMII_TXD0_Pin GPIO_PIN_13
30 #define RMII_TXD0_GPIO_Port GPIOG
31 #define RMII_TX_EN_Pin GPIO_PIN_11
32 #define RMII_TX_EN_GPIO_Port GPIOG
33 #define RMII_RXER_Pin GPIO_PIN_5
34 #define RMII_RXER_GPIO_Port GPIOD
35 #define RMII_MDC_Pin GPIO_PIN_1
36 #define RMII_MDC_GPIO_Port GPIOC
37 #define RMII_REF_CLK_Pin GPIO_PIN_1
38 #define RMII_REF_CLK_GPIO_Port GPIOA
39 #define RMII_RXD0_Pin GPIO_PIN_4
40 #define RMII_RXD0_GPIO_Port GPIOC
41 #define RMII_MDIO_Pin GPIO_PIN_2
42 #define RMII_MDIO_GPIO_Port GPIOA
43 #define RMII_RXD1_Pin GPIO_PIN_5
44 #define RMII_RXD1_GPIO_Port GPIOC
45 #define RMII_CRS_DV_Pin GPIO_PIN_7
46 #define RMII_CRS_DV_GPIO_Port GPIOA
47 
48 #ifndef GSC_ETHERDEV_DEFAULT_MACADDRESS // $gsc EtherデバイスデフォルトMACアドレス
49 static unsigned char macaddress[6] = { 0x02, 0x00, 0x00, 0x00, 0x00, 0x01 };
50 #else
51 static unsigned char macaddress[6] = {
52  (GSC_ETHERDEV_DEFAULT_MACADDRESS >> 40) & 0xff,
53  (GSC_ETHERDEV_DEFAULT_MACADDRESS >> 32) & 0xff,
54  (GSC_ETHERDEV_DEFAULT_MACADDRESS >> 24) & 0xff,
55  (GSC_ETHERDEV_DEFAULT_MACADDRESS >> 16) & 0xff,
56  (GSC_ETHERDEV_DEFAULT_MACADDRESS >> 8) & 0xff,
57  (GSC_ETHERDEV_DEFAULT_MACADDRESS >> 0) & 0xff
58 };
59 #endif
60 static unsigned char ether_event[ETH_RXBUFNB + 1];
61 static struct st_event interrupt_evtque;
62 static ETH_HandleTypeDef EthHandle;
63 static void *int_sp;
64 
65 ETH_DMADescTypeDef DMARxDscrTab[ETH_RXBUFNB] __attribute__((section(".RxDescripSection")));/* Ethernet Rx MA Descriptor */
66 ETH_DMADescTypeDef DMATxDscrTab[ETH_TXBUFNB] __attribute__((section(".TxDescripSection")));/* Ethernet Tx DMA Descriptor */
67 uint8_t Rx_Buff[ETH_RXBUFNB][ETH_RX_BUF_SIZE] __attribute__((section(".RxBUF")));/* Ethernet Receive Buffer */
68 uint8_t Tx_Buff[ETH_TXBUFNB][ETH_TX_BUF_SIZE] __attribute__((section(".TxBUF")));/* Ethernet Transmit Buffer */
69 
70 void HAL_ETH_RxCpltCallback(ETH_HandleTypeDef *heth)
71 {
72  event_wakeup_ISR(int_sp, &interrupt_evtque, 0);
73 }
74 
75 static void inthdr_ether(unsigned int intnum, void *sp)
76 {
77  DKFPRINTF(0x01, "\n");
78 
79  int_sp = sp;
80 
81  HAL_ETH_IRQHandler(&EthHandle);
82 }
83 
84 void HAL_ETH_MspInit(ETH_HandleTypeDef* heth)
85 {
86  DKFPRINTF(0x01, "\n");
87 
88  GPIO_InitTypeDef GPIO_InitStruct;
89  if(heth->Instance==ETH) {
90  __HAL_RCC_GPIOA_CLK_ENABLE();
91  __HAL_RCC_GPIOC_CLK_ENABLE();
92  __HAL_RCC_GPIOG_CLK_ENABLE();
93  __HAL_RCC_ETH_CLK_ENABLE();
94  GPIO_InitStruct.Pin = RMII_TXD1_Pin|RMII_TXD0_Pin|RMII_TX_EN_Pin;
95  GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
96  GPIO_InitStruct.Pull = GPIO_NOPULL;
97  GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
98  GPIO_InitStruct.Alternate = GPIO_AF11_ETH;
99  HAL_GPIO_Init(GPIOG, &GPIO_InitStruct);
100 
101  GPIO_InitStruct.Pin = RMII_MDC_Pin|RMII_RXD0_Pin|RMII_RXD1_Pin;
102  GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
103  GPIO_InitStruct.Pull = GPIO_NOPULL;
104  GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
105  GPIO_InitStruct.Alternate = GPIO_AF11_ETH;
106  HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);
107 
108  GPIO_InitStruct.Pin = RMII_REF_CLK_Pin|RMII_MDIO_Pin|RMII_CRS_DV_Pin;
109  GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
110  GPIO_InitStruct.Pull = GPIO_NOPULL;
111  GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
112  GPIO_InitStruct.Alternate = GPIO_AF11_ETH;
113  HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
114  }
115 }
116 
117 static int ether_register(struct st_device *dev, char *param)
118 {
119  eventqueue_register(&interrupt_evtque, "ether_int",
120  ether_event, sizeof(unsigned char), ETH_RXBUFNB + 1);
121 
122  register_interrupt(IRQ2VECT(ETH_IRQn), inthdr_ether);
123 
124  EthHandle.Instance = ETH;
125  EthHandle.Init.MACAddr = macaddress;
126  EthHandle.Init.AutoNegotiation = ETH_AUTONEGOTIATION_ENABLE;
127  EthHandle.Init.Speed = ETH_SPEED_100M;
128  EthHandle.Init.DuplexMode = ETH_MODE_FULLDUPLEX;
129  EthHandle.Init.MediaInterface = ETH_MEDIA_INTERFACE_RMII;
130  EthHandle.Init.RxMode = ETH_RXINTERRUPT_MODE;
131 #ifdef GSC_ETHERDEV_HARDWARE_CHECKSUM // $gsc Etherデバイスのハードウェアチェックサムを有効にする
132  EthHandle.Init.ChecksumMode = ETH_CHECKSUM_BY_HARDWARE;
133 #else
134  EthHandle.Init.ChecksumMode = ETH_CHECKSUM_BY_SOFTWARE;
135 #endif
136  EthHandle.Init.PhyAddress = LAN8742A_PHY_ADDRESS;
137 
138  /* configure ethernet peripheral (GPIOs, clocks, MAC, DMA) */
139  if(HAL_ETH_Init(&EthHandle) == HAL_OK) {
140  /* Set netif link flag */
141  }
142 
143  /* Initialize Tx Descriptors list: Chain Mode */
144  HAL_ETH_DMATxDescListInit(&EthHandle, DMATxDscrTab, &Tx_Buff[0][0], ETH_TXBUFNB);
145 
146  /* Initialize Rx Descriptors list: Chain Mode */
147  HAL_ETH_DMARxDescListInit(&EthHandle, DMARxDscrTab, &Rx_Buff[0][0], ETH_RXBUFNB);
148 
149  return 0;
150 }
151 
152 static int ether_open(struct st_device *dev)
153 {
154  DKFPRINTF(0x01, "\n");
155 
156  HAL_NVIC_SetPriority(ETH_IRQn, 0, 0);
157  HAL_NVIC_EnableIRQ(ETH_IRQn);
158 
159  HAL_ETH_Start(&EthHandle);
160 
161  return 0;
162 }
163 
164 static int ether_close(struct st_device *dev)
165 {
166  DKFPRINTF(0x01, "\n");
167 
168  HAL_ETH_Stop(&EthHandle);
169 
170  return 0;
171 }
172 
173 static int ether_read(struct st_device *dev, void *data, unsigned int size)
174 {
175  DKFPRINTF(0x01, "size = %d\n", size);
176 
177  int i;
178  unsigned short len = 0;
179  unsigned char *buffer;
180  volatile ETH_DMADescTypeDef *dmarxdesc;
181 
182  if(HAL_ETH_GetReceivedFrame_IT(&EthHandle) != HAL_OK) {
183  DKPRINTF(0x01, "ETH Receive Error?\n");
184  goto readend;
185  } else {
186  DKPRINTF(0x01, "ETH Receive OK\n");
187  }
188 
189  DKPRINTF(0x01, "SegCount = %d\n", (int)EthHandle.RxFrameInfos.SegCount);
190  DKPRINTF(0x01, "RxFrameInfos.buffer = %08X\n", (unsigned int)EthHandle.RxFrameInfos.buffer);
191 
192  /* Obtain the size of the packet and put it into the "len" variable. */
193  len = EthHandle.RxFrameInfos.length;
194  buffer = (uint8_t *)EthHandle.RxFrameInfos.buffer;
195 
196  memorycopy(data, buffer, len);
197 
198  /* Release descriptors to DMA */
199  /* Point to first descriptor */
200  dmarxdesc = EthHandle.RxFrameInfos.FSRxDesc;
201  /* Set Own bit in Rx descriptors: gives the buffers back to DMA */
202  for(i=0; i< EthHandle.RxFrameInfos.SegCount; i++) {
203  dmarxdesc->Status |= ETH_DMARXDESC_OWN;
204  dmarxdesc = (ETH_DMADescTypeDef *)(dmarxdesc->Buffer2NextDescAddr);
205  }
206 
207  /* Clear Segment_Count */
208  EthHandle.RxFrameInfos.SegCount = 0;
209 
210  /* When Rx Buffer unavailable flag is set: clear it and resume reception */
211  if((EthHandle.Instance->DMASR & ETH_DMASR_RBUS) != (uint32_t)RESET) {
212  /* Clear RBUS ETHERNET DMA flag */
213  EthHandle.Instance->DMASR = ETH_DMASR_RBUS;
214  /* Resume DMA reception */
215  EthHandle.Instance->DMARPDR = 0;
216  }
217 
218 readend:
219  return len;
220 }
221 
222 static int ether_write(struct st_device *dev, const void *data, unsigned int size)
223 {
224  DKFPRINTF(0x01, "size = %d\n", size);
225 
226  unsigned char *buffer = (unsigned char *)(EthHandle.TxDesc->Buffer1Addr);
227  int rtn = size;
228 
229  memorycopy(buffer, data, size);
230 
231  /* Prepare transmit descriptors to give to DMA */
232  HAL_ETH_TransmitFrame(&EthHandle, size);
233 
234  /* When Transmit Underflow flag is set, clear it and issue a Transmit Poll Demand to resume transmission */
235  if((EthHandle.Instance->DMASR & ETH_DMASR_TUS) != (uint32_t)RESET) {
236  /* Clear TUS ETHERNET DMA flag */
237  EthHandle.Instance->DMASR = ETH_DMASR_TUS;
238 
239  /* Resume DMA transmission*/
240  EthHandle.Instance->DMATPDR = 0;
241  }
242 
243  return rtn;
244 }
245 
246 static int ether_ioctl(struct st_device *dev, unsigned int com, unsigned int arg, void *param)
247 {
248  DKFPRINTF(0x01, "com = %ld arg = %ld\n", com, arg);
249 
250  switch(com) {
251  case IOCMD_ETHER_GET_MACADDR: // MACアドレス取得
252  {
253  unsigned char *mac = (unsigned char *)param;
254  int i;
255 
256  for(i=0; i<6; i++) {
257  mac[i] = macaddress[i];
258  }
259 
260  DKPRINTF(0x01, "MAC Addr %02X:%02X:%02X:%02X:%02X:%02X\n",
261  (int)mac[0], (int)mac[1], (int)mac[2],
262  (int)mac[3], (int)mac[4], (int)mac[5]);
263  }
264  break;
265 
266  case IOCMD_ETHER_SET_MACADDR: // MACアドレス設定
267  return -1; // [TODO]
268  break;
269 
271  break;
272 
273  case IOCMD_ETHER_LINK_UP:
274  HAL_ETH_Start(&EthHandle);
275  break;
276 
278  HAL_ETH_Stop(&EthHandle);
279  break;
280 
282  {
283  unsigned long phyreg;
284  int stat = 0;
285 
286  HAL_ETH_ReadPHYRegister(&EthHandle, PHY_BSR, &phyreg);
287  DKPRINTF(0x01, "PHY_BSR = %08X\n", phyreg);
288 
289  switch(phyreg & PHY_FULLDUPLEX_100M) {
290  case PHY_FULLDUPLEX_100M:
291  stat |= IORTN_BIT_ETHER_100M;
293  break;
294 
295  case PHY_HALFDUPLEX_100M:
296  stat |= IORTN_BIT_ETHER_100M;
297  break;
298 
299  case PHY_FULLDUPLEX_10M:
301  break;
302 
303  case PHY_HALFDUPLEX_10M:
304  break;
305 
306  default:
307  break;
308  }
309 
310  if((phyreg & PHY_LINKED_STATUS) != 0) {
311  stat |= IORTN_BIT_ETHER_LINK_UP;
312  }
313 
314  return stat;
315  }
316  break;
317 
318  default:
319  SYSERR_PRINT("Unknow command %08lX arg %08lX\n", com, arg);
320  break;
321  }
322 
323  return 0;
324 }
325 
326 static int ether_select(struct st_device *dev, unsigned int timeout)
327 {
328  DKFPRINTF(0x01, "timeout = %d\n", timeout);
329 
330  int rtn = 0;
331 
332  rtn = event_wait(&interrupt_evtque, 0, timeout);
333 
334  DKPRINTF(0x01, "%s return=%ld\n", __FUNCTION__, rtn);
335 
336  return rtn;
337 }
338 
339 
340 const struct st_device ether_device = {
342  .explan = "STM32F7xxx-Discovery Ether",
343  .register_dev = ether_register,
344  .open = ether_open,
345  .close = ether_close,
346  .read = ether_read,
347  .write = ether_write,
348  .ioctl = ether_ioctl,
349  .select = ether_select,
350 };
#define IOCMD_ETHER_CLEAR_BUF
バッファをクリアする
Definition: ether_ioctl.h:25
#define IOCMD_ETHER_GET_LINK_STATUS
リンク状態を取得する
Definition: ether_ioctl.h:28
#define IOCMD_ETHER_SET_MACADDR
MACアドレスを設定する
Definition: ether_ioctl.h:24
#define IORTN_BIT_ETHER_LINK_UP
リンクアップ状態
Definition: ether_ioctl.h:17
void eventqueue_register(struct st_event *evtque, const char *name, void *args, unsigned int size, int count)
イベントキューを登録する
Definition: syscall_api.c:339
#define DEF_DEV_NAME_ETHER
標準Etherデバイス名
Definition: ether_ioctl.h:15
文字列処理
void event_wakeup_ISR(void *sp, struct st_event *evtque, void *arg)
イベントキューにイベントを登録し、イベント待ちタスクを起動する
Definition: task.c:923
カーネル用機能限定printf
#define IORTN_BIT_ETHER_FULLDUPLEX
全二重状態
Definition: ether_ioctl.h:18
#define IOCMD_ETHER_LINK_DOWN
リンクダウンする
Definition: ether_ioctl.h:27
イベント
Definition: event.h:15
void * memorycopy(void *dest, const void *src, unsigned int count)
メモリコピー
Definition: str.c:760
システムコール
割り込みハンドラ
#define IOCMD_ETHER_GET_MACADDR
MACアドレスを取得する
Definition: ether_ioctl.h:23
#define IORTN_BIT_ETHER_100M
通信速度100Mbps
Definition: ether_ioctl.h:19
Etherドライバ ioctl 用マクロ定義
イベント待ちタスクキューの操作
デバイスドライバAPI
デバイスドライバ構造体
Definition: device.h:25
カーネル、ドライバ(非タスク)デバッグ用マクロ
#define IOCMD_ETHER_LINK_UP
リンクアップする
Definition: ether_ioctl.h:26
char name[MAX_DEVNAMELRN]
デバイス名文字列
Definition: device.h:26
unsigned int size
1イベントのサイズ
Definition: event.h:19
int event_wait(struct st_event *evtque, void *argp, unsigned int timeout)
タスクをイベント待ち状態にする
Definition: syscall_api.c:364