unfinished, can't output packets
Fork of lwip-eth by
arch/TARGET_STM/stm32f4_emac.c@26:5fa145f66aa0, 2015-03-02 (annotated)
- Committer:
- yihui
- Date:
- Mon Mar 02 12:46:32 2015 +0000
- Revision:
- 26:5fa145f66aa0
- Parent:
- 25:aa213004ce08
- Child:
- 27:eb85c62f8db8
fix gpio speed (low -> high)
Who changed what in which revision?
User | Revision | Line number | New 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 | 26:5fa145f66aa0 | 80 | GPIO_InitStruct.Speed = GPIO_SPEED_HIGH; |
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 | 26:5fa145f66aa0 | 87 | GPIO_InitStruct.Speed = GPIO_SPEED_HIGH; |
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 | 26:5fa145f66aa0 | 94 | GPIO_InitStruct.Speed = GPIO_SPEED_HIGH; |
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, ®value); |
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, ®value); |
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 |