Onenet

Dependents:   K64F_eCompass_OneNET_JW

Committer:
robert_jw
Date:
Mon Jun 20 01:40:20 2016 +0000
Revision:
0:b2805b6888dc
ADS

Who changed what in which revision?

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