lwip-eth for Seeed Arch Max.

Fork of lwip-eth-arch-max-dev by Yihui Xiong

Committer:
yihui
Date:
Mon Mar 02 08:18:45 2015 +0000
Revision:
25:aa213004ce08
Child:
26:5fa145f66aa0
add STM32F407 target, unfinished. can't output packets

Who changed what in which revision?

UserRevisionLine numberNew contents of line
yihui 25:aa213004ce08 1
yihui 25:aa213004ce08 2 #include "stm32f4xx_hal.h"
yihui 25:aa213004ce08 3 #include "lwip/opt.h"
yihui 25:aa213004ce08 4
yihui 25:aa213004ce08 5 #include "lwip/timers.h"
yihui 25:aa213004ce08 6 #include "netif/etharp.h"
yihui 25:aa213004ce08 7 #include "lwip/tcpip.h"
yihui 25:aa213004ce08 8 #include <string.h>
yihui 25:aa213004ce08 9 #include "cmsis_os.h"
yihui 25:aa213004ce08 10
yihui 25:aa213004ce08 11 #define RECV_TASK_PRI (osPriorityHigh)
yihui 25:aa213004ce08 12 #define PHY_TASK_PRI (osPriorityLow)
yihui 25:aa213004ce08 13 #define PHY_TASK_WAIT (200)
yihui 25:aa213004ce08 14
yihui 25:aa213004ce08 15
yihui 25:aa213004ce08 16 #if defined (__ICCARM__) /*!< IAR Compiler */
yihui 25:aa213004ce08 17 #pragma data_alignment=4
yihui 25:aa213004ce08 18 #endif
yihui 25:aa213004ce08 19 __ALIGN_BEGIN ETH_DMADescTypeDef DMARxDscrTab[ETH_RXBUFNB] __ALIGN_END; /* Ethernet Rx MA Descriptor */
yihui 25:aa213004ce08 20
yihui 25:aa213004ce08 21 #if defined (__ICCARM__) /*!< IAR Compiler */
yihui 25:aa213004ce08 22 #pragma data_alignment=4
yihui 25:aa213004ce08 23 #endif
yihui 25:aa213004ce08 24 __ALIGN_BEGIN ETH_DMADescTypeDef DMATxDscrTab[ETH_TXBUFNB] __ALIGN_END; /* Ethernet Tx DMA Descriptor */
yihui 25:aa213004ce08 25
yihui 25:aa213004ce08 26 #if defined (__ICCARM__) /*!< IAR Compiler */
yihui 25:aa213004ce08 27 #pragma data_alignment=4
yihui 25:aa213004ce08 28 #endif
yihui 25:aa213004ce08 29 __ALIGN_BEGIN uint8_t Rx_Buff[ETH_RXBUFNB][ETH_RX_BUF_SIZE] __ALIGN_END; /* Ethernet Receive Buffer */
yihui 25:aa213004ce08 30
yihui 25:aa213004ce08 31 #if defined (__ICCARM__) /*!< IAR Compiler */
yihui 25:aa213004ce08 32 #pragma data_alignment=4
yihui 25:aa213004ce08 33 #endif
yihui 25:aa213004ce08 34 __ALIGN_BEGIN uint8_t Tx_Buff[ETH_TXBUFNB][ETH_TX_BUF_SIZE] __ALIGN_END; /* Ethernet Transmit Buffer */
yihui 25:aa213004ce08 35
yihui 25:aa213004ce08 36
yihui 25:aa213004ce08 37
yihui 25:aa213004ce08 38 ETH_HandleTypeDef heth;
yihui 25:aa213004ce08 39
yihui 25:aa213004ce08 40 static sys_sem_t rx_ready_sem; /* receive ready semaphore */
yihui 25:aa213004ce08 41 static sys_mutex_t tx_lock_mutex;
yihui 25:aa213004ce08 42
yihui 25:aa213004ce08 43 static int tx_int_count = 0;
yihui 25:aa213004ce08 44
yihui 25:aa213004ce08 45 /* function */
yihui 25:aa213004ce08 46 static void stm32f4_rx_task(void *arg);
yihui 25:aa213004ce08 47 static void stm32f4_phy_task(void *arg);
yihui 25:aa213004ce08 48 static err_t stm32f4_etharp_output(struct netif *netif, struct pbuf *q, ip_addr_t *ipaddr);
yihui 25:aa213004ce08 49 static err_t stm32f4_low_level_output(struct netif *netif, struct pbuf *p);
yihui 25:aa213004ce08 50
yihui 25:aa213004ce08 51
yihui 25:aa213004ce08 52 void HAL_ETH_MspInit(ETH_HandleTypeDef* heth)
yihui 25:aa213004ce08 53 {
yihui 25:aa213004ce08 54 GPIO_InitTypeDef GPIO_InitStruct;
yihui 25:aa213004ce08 55 if (heth->Instance == ETH) {
yihui 25:aa213004ce08 56 /* Peripheral clock enable */
yihui 25:aa213004ce08 57 __ETH_CLK_ENABLE();
yihui 25:aa213004ce08 58
yihui 25:aa213004ce08 59 __GPIOA_CLK_ENABLE();
yihui 25:aa213004ce08 60 __GPIOB_CLK_ENABLE();
yihui 25:aa213004ce08 61 __GPIOC_CLK_ENABLE();
yihui 25:aa213004ce08 62
yihui 25:aa213004ce08 63 // __DMA1_CLK_ENABLE();
yihui 25:aa213004ce08 64 // __DMA2_CLK_ENABLE();
yihui 25:aa213004ce08 65
yihui 25:aa213004ce08 66 /**ETH GPIO Configuration
yihui 25:aa213004ce08 67 PC1 ------> ETH_MDC
yihui 25:aa213004ce08 68 PA1 ------> ETH_REF_CLK
yihui 25:aa213004ce08 69 PA2 ------> ETH_MDIO
yihui 25:aa213004ce08 70 PA7 ------> ETH_CRS_DV
yihui 25:aa213004ce08 71 PC4 ------> ETH_RXD0
yihui 25:aa213004ce08 72 PC5 ------> ETH_RXD1
yihui 25:aa213004ce08 73 PB11 ------> ETH_TX_EN
yihui 25:aa213004ce08 74 PB12 ------> ETH_TXD0
yihui 25:aa213004ce08 75 PB13 ------> ETH_TXD1
yihui 25:aa213004ce08 76 */
yihui 25:aa213004ce08 77 GPIO_InitStruct.Pin = GPIO_PIN_1 | GPIO_PIN_4 | GPIO_PIN_5;
yihui 25:aa213004ce08 78 GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
yihui 25:aa213004ce08 79 GPIO_InitStruct.Pull = GPIO_NOPULL;
yihui 25:aa213004ce08 80 GPIO_InitStruct.Speed = GPIO_SPEED_LOW;
yihui 25:aa213004ce08 81 GPIO_InitStruct.Alternate = GPIO_AF11_ETH;
yihui 25:aa213004ce08 82 HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);
yihui 25:aa213004ce08 83
yihui 25:aa213004ce08 84 GPIO_InitStruct.Pin = GPIO_PIN_1 | GPIO_PIN_2 | GPIO_PIN_7;
yihui 25:aa213004ce08 85 GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
yihui 25:aa213004ce08 86 GPIO_InitStruct.Pull = GPIO_NOPULL;
yihui 25:aa213004ce08 87 GPIO_InitStruct.Speed = GPIO_SPEED_LOW;
yihui 25:aa213004ce08 88 GPIO_InitStruct.Alternate = GPIO_AF11_ETH;
yihui 25:aa213004ce08 89 HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
yihui 25:aa213004ce08 90
yihui 25:aa213004ce08 91 GPIO_InitStruct.Pin = GPIO_PIN_11 | GPIO_PIN_12 | GPIO_PIN_13;
yihui 25:aa213004ce08 92 GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
yihui 25:aa213004ce08 93 GPIO_InitStruct.Pull = GPIO_NOPULL;
yihui 25:aa213004ce08 94 GPIO_InitStruct.Speed = GPIO_SPEED_LOW;
yihui 25:aa213004ce08 95 GPIO_InitStruct.Alternate = GPIO_AF11_ETH;
yihui 25:aa213004ce08 96 HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
yihui 25:aa213004ce08 97
yihui 25:aa213004ce08 98 /* Peripheral interrupt init*/
yihui 25:aa213004ce08 99 /* Sets the priority grouping field */
yihui 25:aa213004ce08 100 HAL_NVIC_SetPriorityGrouping(NVIC_PRIORITYGROUP_4);
yihui 25:aa213004ce08 101 HAL_NVIC_SetPriority(ETH_IRQn, 0, 0);
yihui 25:aa213004ce08 102 HAL_NVIC_EnableIRQ(ETH_IRQn);
yihui 25:aa213004ce08 103 }
yihui 25:aa213004ce08 104 }
yihui 25:aa213004ce08 105
yihui 25:aa213004ce08 106 void HAL_ETH_MspDeInit(ETH_HandleTypeDef* heth)
yihui 25:aa213004ce08 107 {
yihui 25:aa213004ce08 108 if (heth->Instance == ETH) {
yihui 25:aa213004ce08 109 /* Peripheral clock disable */
yihui 25:aa213004ce08 110 __ETH_CLK_DISABLE();
yihui 25:aa213004ce08 111
yihui 25:aa213004ce08 112 /**ETH GPIO Configuration
yihui 25:aa213004ce08 113 PC1 ------> ETH_MDC
yihui 25:aa213004ce08 114 PA1 ------> ETH_REF_CLK
yihui 25:aa213004ce08 115 PA2 ------> ETH_MDIO
yihui 25:aa213004ce08 116 PA7 ------> ETH_CRS_DV
yihui 25:aa213004ce08 117 PC4 ------> ETH_RXD0
yihui 25:aa213004ce08 118 PC5 ------> ETH_RXD1
yihui 25:aa213004ce08 119 PB11 ------> ETH_TX_EN
yihui 25:aa213004ce08 120 PB12 ------> ETH_TXD0
yihui 25:aa213004ce08 121 PB13 ------> ETH_TXD1
yihui 25:aa213004ce08 122 */
yihui 25:aa213004ce08 123 HAL_GPIO_DeInit(GPIOC, GPIO_PIN_1 | GPIO_PIN_4 | GPIO_PIN_5);
yihui 25:aa213004ce08 124
yihui 25:aa213004ce08 125 HAL_GPIO_DeInit(GPIOA, GPIO_PIN_1 | GPIO_PIN_2 | GPIO_PIN_7);
yihui 25:aa213004ce08 126
yihui 25:aa213004ce08 127 HAL_GPIO_DeInit(GPIOB, GPIO_PIN_11 | GPIO_PIN_12 | GPIO_PIN_13);
yihui 25:aa213004ce08 128
yihui 25:aa213004ce08 129 /* Peripheral interrupt Deinit*/
yihui 25:aa213004ce08 130 HAL_NVIC_DisableIRQ(ETH_IRQn);
yihui 25:aa213004ce08 131 }
yihui 25:aa213004ce08 132 }
yihui 25:aa213004ce08 133
yihui 25:aa213004ce08 134 /**
yihui 25:aa213004ce08 135 * @brief Ethernet Rx Transfer completed callback
yihui 25:aa213004ce08 136 * @param heth: ETH handle
yihui 25:aa213004ce08 137 * @retval None
yihui 25:aa213004ce08 138 */
yihui 25:aa213004ce08 139 void HAL_ETH_RxCpltCallback(ETH_HandleTypeDef *heth)
yihui 25:aa213004ce08 140 {
yihui 25:aa213004ce08 141
yihui 25:aa213004ce08 142 sys_sem_signal(&rx_ready_sem);
yihui 25:aa213004ce08 143 }
yihui 25:aa213004ce08 144
yihui 25:aa213004ce08 145 void HAL_ETH_TxCpltCallback(ETH_HandleTypeDef *heth)
yihui 25:aa213004ce08 146 {
yihui 25:aa213004ce08 147
yihui 25:aa213004ce08 148 }
yihui 25:aa213004ce08 149
yihui 25:aa213004ce08 150 /**
yihui 25:aa213004ce08 151 * @brief Ethernet IRQ Handler
yihui 25:aa213004ce08 152 * @param None
yihui 25:aa213004ce08 153 * @retval None
yihui 25:aa213004ce08 154 */
yihui 25:aa213004ce08 155 void ETH_IRQHandler(void)
yihui 25:aa213004ce08 156 {
yihui 25:aa213004ce08 157 HAL_ETH_IRQHandler(&heth);
yihui 25:aa213004ce08 158 }
yihui 25:aa213004ce08 159
yihui 25:aa213004ce08 160
yihui 25:aa213004ce08 161
yihui 25:aa213004ce08 162 /**
yihui 25:aa213004ce08 163 * In this function, the hardware should be initialized.
yihui 25:aa213004ce08 164 * Called from ethernetif_init().
yihui 25:aa213004ce08 165 *
yihui 25:aa213004ce08 166 * @param netif the already initialized lwip network interface structure
yihui 25:aa213004ce08 167 * for this ethernetif
yihui 25:aa213004ce08 168 */
yihui 25:aa213004ce08 169 static void stm32f4_low_level_init(struct netif *netif)
yihui 25:aa213004ce08 170 {
yihui 25:aa213004ce08 171 uint32_t regvalue = 0;
yihui 25:aa213004ce08 172 HAL_StatusTypeDef hal_eth_init_status;
yihui 25:aa213004ce08 173
yihui 25:aa213004ce08 174 /* Init ETH */
yihui 25:aa213004ce08 175 uint8_t MACAddr[6];
yihui 25:aa213004ce08 176 heth.Instance = ETH;
yihui 25:aa213004ce08 177 heth.Init.AutoNegotiation = ETH_AUTONEGOTIATION_ENABLE;
yihui 25:aa213004ce08 178 heth.Init.Speed = ETH_SPEED_10M;
yihui 25:aa213004ce08 179 heth.Init.DuplexMode = ETH_MODE_FULLDUPLEX;
yihui 25:aa213004ce08 180 heth.Init.PhyAddress = 1;
yihui 25:aa213004ce08 181 MACAddr[0] = 0x00;
yihui 25:aa213004ce08 182 MACAddr[1] = 0x80;
yihui 25:aa213004ce08 183 MACAddr[2] = 0xE1;
yihui 25:aa213004ce08 184 MACAddr[3] = 0x00;
yihui 25:aa213004ce08 185 MACAddr[4] = 0x00;
yihui 25:aa213004ce08 186 MACAddr[5] = 0x00;
yihui 25:aa213004ce08 187 heth.Init.MACAddr = &MACAddr[0];
yihui 25:aa213004ce08 188 heth.Init.RxMode = ETH_RXINTERRUPT_MODE;
yihui 25:aa213004ce08 189 heth.Init.ChecksumMode = ETH_CHECKSUM_BY_HARDWARE;
yihui 25:aa213004ce08 190 heth.Init.MediaInterface = ETH_MEDIA_INTERFACE_RMII;
yihui 25:aa213004ce08 191 hal_eth_init_status = HAL_ETH_Init(&heth);
yihui 25:aa213004ce08 192
yihui 25:aa213004ce08 193 if (hal_eth_init_status == HAL_OK) {
yihui 25:aa213004ce08 194 /* Set netif link flag */
yihui 25:aa213004ce08 195 netif->flags |= NETIF_FLAG_LINK_UP;
yihui 25:aa213004ce08 196 }
yihui 25:aa213004ce08 197
yihui 25:aa213004ce08 198 /* Initialize Tx Descriptors list: Chain Mode */
yihui 25:aa213004ce08 199 HAL_ETH_DMATxDescListInit(&heth, DMATxDscrTab, &Tx_Buff[0][0], ETH_TXBUFNB);
yihui 25:aa213004ce08 200
yihui 25:aa213004ce08 201 /* Initialize Rx Descriptors list: Chain Mode */
yihui 25:aa213004ce08 202 HAL_ETH_DMARxDescListInit(&heth, DMARxDscrTab, &Rx_Buff[0][0], ETH_RXBUFNB);
yihui 25:aa213004ce08 203
yihui 25:aa213004ce08 204 #if LWIP_ARP || LWIP_ETHERNET
yihui 25:aa213004ce08 205 /* set MAC hardware address length */
yihui 25:aa213004ce08 206 netif->hwaddr_len = ETHARP_HWADDR_LEN;
yihui 25:aa213004ce08 207
yihui 25:aa213004ce08 208 /* set MAC hardware address */
yihui 25:aa213004ce08 209 netif->hwaddr[0] = heth.Init.MACAddr[0];
yihui 25:aa213004ce08 210 netif->hwaddr[1] = heth.Init.MACAddr[1];
yihui 25:aa213004ce08 211 netif->hwaddr[2] = heth.Init.MACAddr[2];
yihui 25:aa213004ce08 212 netif->hwaddr[3] = heth.Init.MACAddr[3];
yihui 25:aa213004ce08 213 netif->hwaddr[4] = heth.Init.MACAddr[4];
yihui 25:aa213004ce08 214 netif->hwaddr[5] = heth.Init.MACAddr[5];
yihui 25:aa213004ce08 215
yihui 25:aa213004ce08 216 /* maximum transfer unit */
yihui 25:aa213004ce08 217 netif->mtu = 1500;
yihui 25:aa213004ce08 218
yihui 25:aa213004ce08 219 /* device capabilities */
yihui 25:aa213004ce08 220 /* don't set NETIF_FLAG_ETHARP if this device is not an ethernet one */
yihui 25:aa213004ce08 221 netif->flags |= NETIF_FLAG_BROADCAST | NETIF_FLAG_ETHARP;
yihui 25:aa213004ce08 222
yihui 25:aa213004ce08 223 /* Enable MAC and DMA transmission and reception */
yihui 25:aa213004ce08 224 HAL_ETH_Start(&heth);
yihui 25:aa213004ce08 225
yihui 25:aa213004ce08 226 /**** Configure PHY to generate an interrupt when Eth Link state changes ****/
yihui 25:aa213004ce08 227 /* Read Register Configuration */
yihui 25:aa213004ce08 228 HAL_ETH_ReadPHYRegister(&heth, PHY_MICR, &regvalue);
yihui 25:aa213004ce08 229
yihui 25:aa213004ce08 230 regvalue |= (PHY_MICR_INT_EN | PHY_MICR_INT_OE);
yihui 25:aa213004ce08 231
yihui 25:aa213004ce08 232 /* Enable Interrupts */
yihui 25:aa213004ce08 233 HAL_ETH_WritePHYRegister(&heth, PHY_MICR, regvalue);
yihui 25:aa213004ce08 234
yihui 25:aa213004ce08 235 /* Read Register Configuration */
yihui 25:aa213004ce08 236 HAL_ETH_ReadPHYRegister(&heth, PHY_MISR, &regvalue);
yihui 25:aa213004ce08 237
yihui 25:aa213004ce08 238 regvalue |= PHY_MISR_LINK_INT_EN;
yihui 25:aa213004ce08 239
yihui 25:aa213004ce08 240 /* Enable Interrupt on change of link status */
yihui 25:aa213004ce08 241 HAL_ETH_WritePHYRegister(&heth, PHY_MISR, regvalue);
yihui 25:aa213004ce08 242 #endif
yihui 25:aa213004ce08 243 }
yihui 25:aa213004ce08 244
yihui 25:aa213004ce08 245 /**
yihui 25:aa213004ce08 246 * This function should do the actual transmission of the packet. The packet is
yihui 25:aa213004ce08 247 * contained in the pbuf that is passed to the function. This pbuf
yihui 25:aa213004ce08 248 * might be chained.
yihui 25:aa213004ce08 249 *
yihui 25:aa213004ce08 250 * @param netif the lwip network interface structure for this ethernetif
yihui 25:aa213004ce08 251 * @param p the MAC packet to send (e.g. IP packet including MAC addresses and type)
yihui 25:aa213004ce08 252 * @return ERR_OK if the packet could be sent
yihui 25:aa213004ce08 253 * an err_t value if the packet couldn't be sent
yihui 25:aa213004ce08 254 *
yihui 25:aa213004ce08 255 * @note Returning ERR_MEM here if a DMA queue of your MAC is full can lead to
yihui 25:aa213004ce08 256 * strange results. You might consider waiting for space in the DMA queue
yihui 25:aa213004ce08 257 * to become availale since the stack doesn't retry to send a packet
yihui 25:aa213004ce08 258 * dropped because of memory failure (except for the TCP timers).
yihui 25:aa213004ce08 259 */
yihui 25:aa213004ce08 260
yihui 25:aa213004ce08 261 static err_t stm32f4_low_level_output(struct netif *netif, struct pbuf *p)
yihui 25:aa213004ce08 262 {
yihui 25:aa213004ce08 263 static int count = 0;
yihui 25:aa213004ce08 264
yihui 25:aa213004ce08 265 err_t errval;
yihui 25:aa213004ce08 266 struct pbuf *q;
yihui 25:aa213004ce08 267 uint8_t *buffer = (uint8_t*)(heth.TxDesc->Buffer1Addr);
yihui 25:aa213004ce08 268 __IO ETH_DMADescTypeDef *DmaTxDesc;
yihui 25:aa213004ce08 269 uint32_t framelength = 0;
yihui 25:aa213004ce08 270 uint32_t bufferoffset = 0;
yihui 25:aa213004ce08 271 uint32_t byteslefttocopy = 0;
yihui 25:aa213004ce08 272 uint32_t payloadoffset = 0;
yihui 25:aa213004ce08 273 DmaTxDesc = heth.TxDesc;
yihui 25:aa213004ce08 274 bufferoffset = 0;
yihui 25:aa213004ce08 275
yihui 25:aa213004ce08 276
yihui 25:aa213004ce08 277 sys_mutex_lock(&tx_lock_mutex);
yihui 25:aa213004ce08 278
yihui 25:aa213004ce08 279 /* copy frame from pbufs to driver buffers */
yihui 25:aa213004ce08 280 for (q = p; q != NULL; q = q->next) {
yihui 25:aa213004ce08 281 /* Is this buffer available? If not, goto error */
yihui 25:aa213004ce08 282 if ((DmaTxDesc->Status & ETH_DMATXDESC_OWN) != (uint32_t)RESET) {
yihui 25:aa213004ce08 283 errval = ERR_USE;
yihui 25:aa213004ce08 284 goto error;
yihui 25:aa213004ce08 285 }
yihui 25:aa213004ce08 286
yihui 25:aa213004ce08 287 /* Get bytes in current lwIP buffer */
yihui 25:aa213004ce08 288 byteslefttocopy = q->len;
yihui 25:aa213004ce08 289 payloadoffset = 0;
yihui 25:aa213004ce08 290
yihui 25:aa213004ce08 291 /* Check if the length of data to copy is bigger than Tx buffer size*/
yihui 25:aa213004ce08 292 while ((byteslefttocopy + bufferoffset) > ETH_TX_BUF_SIZE) {
yihui 25:aa213004ce08 293 /* Copy data to Tx buffer*/
yihui 25:aa213004ce08 294 memcpy((uint8_t*)((uint8_t*)buffer + bufferoffset), (uint8_t*)((uint8_t*)q->payload + payloadoffset), (ETH_TX_BUF_SIZE - bufferoffset));
yihui 25:aa213004ce08 295
yihui 25:aa213004ce08 296 /* Point to next descriptor */
yihui 25:aa213004ce08 297 DmaTxDesc = (ETH_DMADescTypeDef*)(DmaTxDesc->Buffer2NextDescAddr);
yihui 25:aa213004ce08 298
yihui 25:aa213004ce08 299 /* Check if the buffer is available */
yihui 25:aa213004ce08 300 if ((DmaTxDesc->Status & ETH_DMATXDESC_OWN) != (uint32_t)RESET) {
yihui 25:aa213004ce08 301 errval = ERR_USE;
yihui 25:aa213004ce08 302 goto error;
yihui 25:aa213004ce08 303 }
yihui 25:aa213004ce08 304
yihui 25:aa213004ce08 305 buffer = (uint8_t*)(DmaTxDesc->Buffer1Addr);
yihui 25:aa213004ce08 306
yihui 25:aa213004ce08 307 byteslefttocopy = byteslefttocopy - (ETH_TX_BUF_SIZE - bufferoffset);
yihui 25:aa213004ce08 308 payloadoffset = payloadoffset + (ETH_TX_BUF_SIZE - bufferoffset);
yihui 25:aa213004ce08 309 framelength = framelength + (ETH_TX_BUF_SIZE - bufferoffset);
yihui 25:aa213004ce08 310 bufferoffset = 0;
yihui 25:aa213004ce08 311 }
yihui 25:aa213004ce08 312
yihui 25:aa213004ce08 313 /* Copy the remaining bytes */
yihui 25:aa213004ce08 314 memcpy((uint8_t*)((uint8_t*)buffer + bufferoffset), (uint8_t*)((uint8_t*)q->payload + payloadoffset), byteslefttocopy);
yihui 25:aa213004ce08 315 bufferoffset = bufferoffset + byteslefttocopy;
yihui 25:aa213004ce08 316 framelength = framelength + byteslefttocopy;
yihui 25:aa213004ce08 317 }
yihui 25:aa213004ce08 318
yihui 25:aa213004ce08 319 /* Prepare transmit descriptors to give to DMA */
yihui 25:aa213004ce08 320 HAL_ETH_TransmitFrame(&heth, framelength);
yihui 25:aa213004ce08 321
yihui 25:aa213004ce08 322 errval = ERR_OK;
yihui 25:aa213004ce08 323
yihui 25:aa213004ce08 324 error:
yihui 25:aa213004ce08 325
yihui 25:aa213004ce08 326 /* When Transmit Underflow flag is set, clear it and issue a Transmit Poll Demand to resume transmission */
yihui 25:aa213004ce08 327 if ((heth.Instance->DMASR & ETH_DMASR_TUS) != (uint32_t)RESET) {
yihui 25:aa213004ce08 328 /* Clear TUS ETHERNET DMA flag */
yihui 25:aa213004ce08 329 heth.Instance->DMASR = ETH_DMASR_TUS;
yihui 25:aa213004ce08 330
yihui 25:aa213004ce08 331 /* Resume DMA transmission*/
yihui 25:aa213004ce08 332 heth.Instance->DMATPDR = 0;
yihui 25:aa213004ce08 333 }
yihui 25:aa213004ce08 334
yihui 25:aa213004ce08 335 sys_mutex_unlock(&tx_lock_mutex);
yihui 25:aa213004ce08 336
yihui 25:aa213004ce08 337 return errval;
yihui 25:aa213004ce08 338 }
yihui 25:aa213004ce08 339
yihui 25:aa213004ce08 340
yihui 25:aa213004ce08 341 /**
yihui 25:aa213004ce08 342 * Should allocate a pbuf and transfer the bytes of the incoming
yihui 25:aa213004ce08 343 * packet from the interface into the pbuf.
yihui 25:aa213004ce08 344 *
yihui 25:aa213004ce08 345 * @param netif the lwip network interface structure for this ethernetif
yihui 25:aa213004ce08 346 * @return a pbuf filled with the received packet (including MAC header)
yihui 25:aa213004ce08 347 * NULL on memory error
yihui 25:aa213004ce08 348 */
yihui 25:aa213004ce08 349 static struct pbuf * stm32f4_low_level_input(struct netif *netif)
yihui 25:aa213004ce08 350 {
yihui 25:aa213004ce08 351 struct pbuf *p = NULL;
yihui 25:aa213004ce08 352 struct pbuf *q;
yihui 25:aa213004ce08 353 uint16_t len = 0;
yihui 25:aa213004ce08 354 uint8_t *buffer;
yihui 25:aa213004ce08 355 __IO ETH_DMADescTypeDef *dmarxdesc;
yihui 25:aa213004ce08 356 uint32_t bufferoffset = 0;
yihui 25:aa213004ce08 357 uint32_t payloadoffset = 0;
yihui 25:aa213004ce08 358 uint32_t byteslefttocopy = 0;
yihui 25:aa213004ce08 359 uint32_t i = 0;
yihui 25:aa213004ce08 360
yihui 25:aa213004ce08 361
yihui 25:aa213004ce08 362 /* get received frame */
yihui 25:aa213004ce08 363 if (HAL_ETH_GetReceivedFrame(&heth) != HAL_OK)
yihui 25:aa213004ce08 364 return NULL;
yihui 25:aa213004ce08 365
yihui 25:aa213004ce08 366 /* Obtain the size of the packet and put it into the "len" variable. */
yihui 25:aa213004ce08 367 len = heth.RxFrameInfos.length;
yihui 25:aa213004ce08 368 buffer = (uint8_t*)heth.RxFrameInfos.buffer;
yihui 25:aa213004ce08 369
yihui 25:aa213004ce08 370 if (len > 0) {
yihui 25:aa213004ce08 371 /* We allocate a pbuf chain of pbufs from the Lwip buffer pool */
yihui 25:aa213004ce08 372 p = pbuf_alloc(PBUF_RAW, len, PBUF_POOL);
yihui 25:aa213004ce08 373 }
yihui 25:aa213004ce08 374
yihui 25:aa213004ce08 375 if (p != NULL) {
yihui 25:aa213004ce08 376 dmarxdesc = heth.RxFrameInfos.FSRxDesc;
yihui 25:aa213004ce08 377 bufferoffset = 0;
yihui 25:aa213004ce08 378 for (q = p; q != NULL; q = q->next) {
yihui 25:aa213004ce08 379 byteslefttocopy = q->len;
yihui 25:aa213004ce08 380 payloadoffset = 0;
yihui 25:aa213004ce08 381
yihui 25:aa213004ce08 382 /* Check if the length of bytes to copy in current pbuf is bigger than Rx buffer size*/
yihui 25:aa213004ce08 383 while ((byteslefttocopy + bufferoffset) > ETH_RX_BUF_SIZE) {
yihui 25:aa213004ce08 384 /* Copy data to pbuf */
yihui 25:aa213004ce08 385 memcpy((uint8_t*)((uint8_t*)q->payload + payloadoffset), (uint8_t*)((uint8_t*)buffer + bufferoffset), (ETH_RX_BUF_SIZE - bufferoffset));
yihui 25:aa213004ce08 386
yihui 25:aa213004ce08 387 /* Point to next descriptor */
yihui 25:aa213004ce08 388 dmarxdesc = (ETH_DMADescTypeDef*)(dmarxdesc->Buffer2NextDescAddr);
yihui 25:aa213004ce08 389 buffer = (uint8_t*)(dmarxdesc->Buffer1Addr);
yihui 25:aa213004ce08 390
yihui 25:aa213004ce08 391 byteslefttocopy = byteslefttocopy - (ETH_RX_BUF_SIZE - bufferoffset);
yihui 25:aa213004ce08 392 payloadoffset = payloadoffset + (ETH_RX_BUF_SIZE - bufferoffset);
yihui 25:aa213004ce08 393 bufferoffset = 0;
yihui 25:aa213004ce08 394 }
yihui 25:aa213004ce08 395 /* Copy remaining data in pbuf */
yihui 25:aa213004ce08 396 memcpy((uint8_t*)((uint8_t*)q->payload + payloadoffset), (uint8_t*)((uint8_t*)buffer + bufferoffset), byteslefttocopy);
yihui 25:aa213004ce08 397 bufferoffset = bufferoffset + byteslefttocopy;
yihui 25:aa213004ce08 398 }
yihui 25:aa213004ce08 399
yihui 25:aa213004ce08 400 /* Release descriptors to DMA */
yihui 25:aa213004ce08 401 /* Point to first descriptor */
yihui 25:aa213004ce08 402 dmarxdesc = heth.RxFrameInfos.FSRxDesc;
yihui 25:aa213004ce08 403 /* Set Own bit in Rx descriptors: gives the buffers back to DMA */
yihui 25:aa213004ce08 404 for (i = 0; i < heth.RxFrameInfos.SegCount; i++) {
yihui 25:aa213004ce08 405 dmarxdesc->Status |= ETH_DMARXDESC_OWN;
yihui 25:aa213004ce08 406 dmarxdesc = (ETH_DMADescTypeDef*)(dmarxdesc->Buffer2NextDescAddr);
yihui 25:aa213004ce08 407 }
yihui 25:aa213004ce08 408
yihui 25:aa213004ce08 409 /* Clear Segment_Count */
yihui 25:aa213004ce08 410 heth.RxFrameInfos.SegCount = 0;
yihui 25:aa213004ce08 411 }
yihui 25:aa213004ce08 412
yihui 25:aa213004ce08 413 /* When Rx Buffer unavailable flag is set: clear it and resume reception */
yihui 25:aa213004ce08 414 if ((heth.Instance->DMASR & ETH_DMASR_RBUS) != (uint32_t)RESET) {
yihui 25:aa213004ce08 415 /* Clear RBUS ETHERNET DMA flag */
yihui 25:aa213004ce08 416 heth.Instance->DMASR = ETH_DMASR_RBUS;
yihui 25:aa213004ce08 417 /* Resume DMA reception */
yihui 25:aa213004ce08 418 heth.Instance->DMARPDR = 0;
yihui 25:aa213004ce08 419 }
yihui 25:aa213004ce08 420 return p;
yihui 25:aa213004ce08 421 }
yihui 25:aa213004ce08 422
yihui 25:aa213004ce08 423 static void stm32f4_rx_task(void *arg)
yihui 25:aa213004ce08 424 {
yihui 25:aa213004ce08 425 struct netif *netif = (struct netif*)arg;
yihui 25:aa213004ce08 426 struct pbuf *p;
yihui 25:aa213004ce08 427
yihui 25:aa213004ce08 428 while (1) {
yihui 25:aa213004ce08 429 sys_arch_sem_wait(&rx_ready_sem, 0);
yihui 25:aa213004ce08 430 p = stm32f4_low_level_input(netif);
yihui 25:aa213004ce08 431 if (p != NULL) {
yihui 25:aa213004ce08 432 if (netif->input(p, netif) != ERR_OK) {
yihui 25:aa213004ce08 433 pbuf_free(p);
yihui 25:aa213004ce08 434 p = NULL;
yihui 25:aa213004ce08 435 }
yihui 25:aa213004ce08 436 }
yihui 25:aa213004ce08 437 }
yihui 25:aa213004ce08 438 }
yihui 25:aa213004ce08 439
yihui 25:aa213004ce08 440 static void stm32f4_phy_task(void *arg)
yihui 25:aa213004ce08 441 {
yihui 25:aa213004ce08 442 struct netif *netif = (struct netif*)arg;
yihui 25:aa213004ce08 443 uint32_t phy_status = 0;
yihui 25:aa213004ce08 444
yihui 25:aa213004ce08 445 while (1) {
yihui 25:aa213004ce08 446 uint32_t status;
yihui 25:aa213004ce08 447 if (HAL_ETH_ReadPHYRegister(&heth, PHY_SR, &status) == HAL_OK) {
yihui 25:aa213004ce08 448 if ((status & PHY_LINK_STATUS) && !(phy_status & PHY_LINK_STATUS)) {
yihui 25:aa213004ce08 449 tcpip_callback_with_block((tcpip_callback_fn)netif_set_link_up, (void*) netif, 1);
yihui 25:aa213004ce08 450 } else if (!(status & PHY_LINK_STATUS) && (phy_status & PHY_LINK_STATUS)) {
yihui 25:aa213004ce08 451 tcpip_callback_with_block((tcpip_callback_fn)netif_set_link_down, (void*) netif, 1);
yihui 25:aa213004ce08 452 }
yihui 25:aa213004ce08 453
yihui 25:aa213004ce08 454 phy_status = status;
yihui 25:aa213004ce08 455 }
yihui 25:aa213004ce08 456
yihui 25:aa213004ce08 457 osDelay(PHY_TASK_WAIT);
yihui 25:aa213004ce08 458 }
yihui 25:aa213004ce08 459 }
yihui 25:aa213004ce08 460
yihui 25:aa213004ce08 461 static err_t stm32f4_etharp_output(struct netif *netif, struct pbuf *q, ip_addr_t *ipaddr)
yihui 25:aa213004ce08 462 {
yihui 25:aa213004ce08 463 /* Only send packet is link is up */
yihui 25:aa213004ce08 464 if (netif->flags & NETIF_FLAG_LINK_UP) {
yihui 25:aa213004ce08 465 return etharp_output(netif, q, ipaddr);
yihui 25:aa213004ce08 466 }
yihui 25:aa213004ce08 467
yihui 25:aa213004ce08 468 return ERR_CONN;
yihui 25:aa213004ce08 469 }
yihui 25:aa213004ce08 470
yihui 25:aa213004ce08 471 err_t eth_arch_enetif_init(struct netif *netif)
yihui 25:aa213004ce08 472 {
yihui 25:aa213004ce08 473 /* set MAC hardware address */
yihui 25:aa213004ce08 474 // netif->hwaddr[0] = 01;
yihui 25:aa213004ce08 475 // netif->hwaddr[1] = 02;
yihui 25:aa213004ce08 476 // netif->hwaddr[2] = 03;
yihui 25:aa213004ce08 477 // netif->hwaddr[3] = 04;
yihui 25:aa213004ce08 478 // netif->hwaddr[4] = 05;
yihui 25:aa213004ce08 479 // netif->hwaddr[5] = 06;
yihui 25:aa213004ce08 480
yihui 25:aa213004ce08 481 netif->hwaddr_len = ETHARP_HWADDR_LEN;
yihui 25:aa213004ce08 482
yihui 25:aa213004ce08 483 /* maximum transfer unit */
yihui 25:aa213004ce08 484 netif->mtu = 1500;
yihui 25:aa213004ce08 485
yihui 25:aa213004ce08 486 /* device capabilities */
yihui 25:aa213004ce08 487 netif->flags = NETIF_FLAG_BROADCAST | NETIF_FLAG_ETHARP | NETIF_FLAG_ETHERNET | NETIF_FLAG_IGMP;
yihui 25:aa213004ce08 488
yihui 25:aa213004ce08 489 #if LWIP_NETIF_HOSTNAME
yihui 25:aa213004ce08 490 /* Initialize interface hostname */
yihui 25:aa213004ce08 491 netif->hostname = "lwip";
yihui 25:aa213004ce08 492 #endif /* LWIP_NETIF_HOSTNAME */
yihui 25:aa213004ce08 493
yihui 25:aa213004ce08 494 netif->name[0] = 'e';
yihui 25:aa213004ce08 495 netif->name[1] = 'n';
yihui 25:aa213004ce08 496
yihui 25:aa213004ce08 497 netif->output = stm32f4_etharp_output;
yihui 25:aa213004ce08 498 netif->linkoutput = stm32f4_low_level_output;
yihui 25:aa213004ce08 499
yihui 25:aa213004ce08 500 /* initialize the hardware */
yihui 25:aa213004ce08 501 stm32f4_low_level_init(netif);
yihui 25:aa213004ce08 502
yihui 25:aa213004ce08 503 /* semaphore */
yihui 25:aa213004ce08 504 sys_sem_new(&rx_ready_sem, 0);
yihui 25:aa213004ce08 505
yihui 25:aa213004ce08 506 sys_mutex_new(&tx_lock_mutex);
yihui 25:aa213004ce08 507
yihui 25:aa213004ce08 508 /* task */
yihui 25:aa213004ce08 509 sys_thread_new("stm32f4_recv_task", stm32f4_rx_task, netif, DEFAULT_THREAD_STACKSIZE, RECV_TASK_PRI);
yihui 25:aa213004ce08 510 sys_thread_new("stm32f4_phy_task", stm32f4_phy_task, netif, DEFAULT_THREAD_STACKSIZE, PHY_TASK_PRI);
yihui 25:aa213004ce08 511
yihui 25:aa213004ce08 512 return ERR_OK;
yihui 25:aa213004ce08 513 }
yihui 25:aa213004ce08 514
yihui 25:aa213004ce08 515 void eth_arch_enable_interrupts(void)
yihui 25:aa213004ce08 516 {
yihui 25:aa213004ce08 517 HAL_NVIC_SetPriorityGrouping(NVIC_PRIORITYGROUP_4);
yihui 25:aa213004ce08 518 HAL_NVIC_SetPriority(ETH_IRQn, 0, 0);
yihui 25:aa213004ce08 519 HAL_NVIC_EnableIRQ(ETH_IRQn);
yihui 25:aa213004ce08 520 }
yihui 25:aa213004ce08 521
yihui 25:aa213004ce08 522 void eth_arch_disable_interrupts(void)
yihui 25:aa213004ce08 523 {
yihui 25:aa213004ce08 524 NVIC_DisableIRQ(ETH_IRQn);
yihui 25:aa213004ce08 525 }
yihui 25:aa213004ce08 526
yihui 25:aa213004ce08 527