lab practicals
arch/TARGET_Freescale/k64f_emac.c@33:9de8bd8ca1c8, 2016-05-26 (annotated)
- Committer:
- mbed_official
- Date:
- Thu May 26 09:00:26 2016 +0100
- Revision:
- 33:9de8bd8ca1c8
Synchronized with git revision 745ebbf4557f0f3964f73063c1d88ddbcda0ed22
Full URL: https://github.com/mbedmicro/mbed/commit/745ebbf4557f0f3964f73063c1d88ddbcda0ed22/
Synch - fix lwip-eth path
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
mbed_official | 33:9de8bd8ca1c8 | 1 | #include "lwip/opt.h" |
mbed_official | 33:9de8bd8ca1c8 | 2 | #include "lwip/sys.h" |
mbed_official | 33:9de8bd8ca1c8 | 3 | #include "lwip/def.h" |
mbed_official | 33:9de8bd8ca1c8 | 4 | #include "lwip/mem.h" |
mbed_official | 33:9de8bd8ca1c8 | 5 | #include "lwip/pbuf.h" |
mbed_official | 33:9de8bd8ca1c8 | 6 | #include "lwip/stats.h" |
mbed_official | 33:9de8bd8ca1c8 | 7 | #include "lwip/snmp.h" |
mbed_official | 33:9de8bd8ca1c8 | 8 | #include "lwip/tcpip.h" |
mbed_official | 33:9de8bd8ca1c8 | 9 | #include "netif/etharp.h" |
mbed_official | 33:9de8bd8ca1c8 | 10 | #include "netif/ppp_oe.h" |
mbed_official | 33:9de8bd8ca1c8 | 11 | |
mbed_official | 33:9de8bd8ca1c8 | 12 | #include "eth_arch.h" |
mbed_official | 33:9de8bd8ca1c8 | 13 | #include "sys_arch.h" |
mbed_official | 33:9de8bd8ca1c8 | 14 | |
mbed_official | 33:9de8bd8ca1c8 | 15 | #include "fsl_phy.h" |
mbed_official | 33:9de8bd8ca1c8 | 16 | #include "k64f_emac_config.h" |
mbed_official | 33:9de8bd8ca1c8 | 17 | #include <ctype.h> |
mbed_official | 33:9de8bd8ca1c8 | 18 | #include <stdio.h> |
mbed_official | 33:9de8bd8ca1c8 | 19 | #include <string.h> |
mbed_official | 33:9de8bd8ca1c8 | 20 | #include <stdlib.h> |
mbed_official | 33:9de8bd8ca1c8 | 21 | |
mbed_official | 33:9de8bd8ca1c8 | 22 | #include "mbed_interface.h" |
mbed_official | 33:9de8bd8ca1c8 | 23 | |
mbed_official | 33:9de8bd8ca1c8 | 24 | enet_handle_t g_handle; |
mbed_official | 33:9de8bd8ca1c8 | 25 | // TX Buffer descriptors |
mbed_official | 33:9de8bd8ca1c8 | 26 | uint8_t *tx_desc_start_addr; |
mbed_official | 33:9de8bd8ca1c8 | 27 | // RX Buffer descriptors |
mbed_official | 33:9de8bd8ca1c8 | 28 | uint8_t *rx_desc_start_addr; |
mbed_official | 33:9de8bd8ca1c8 | 29 | // RX packet buffer pointers |
mbed_official | 33:9de8bd8ca1c8 | 30 | struct pbuf *rx_buff[ENET_RX_RING_LEN]; |
mbed_official | 33:9de8bd8ca1c8 | 31 | // TX packet buffer pointers |
mbed_official | 33:9de8bd8ca1c8 | 32 | struct pbuf *tx_buff[ENET_RX_RING_LEN]; |
mbed_official | 33:9de8bd8ca1c8 | 33 | // RX packet payload pointers |
mbed_official | 33:9de8bd8ca1c8 | 34 | uint32_t *rx_ptr[ENET_RX_RING_LEN]; |
mbed_official | 33:9de8bd8ca1c8 | 35 | |
mbed_official | 33:9de8bd8ca1c8 | 36 | /******************************************************************************** |
mbed_official | 33:9de8bd8ca1c8 | 37 | * Internal data |
mbed_official | 33:9de8bd8ca1c8 | 38 | ********************************************************************************/ |
mbed_official | 33:9de8bd8ca1c8 | 39 | #define ENET_BuffSizeAlign(n) ENET_ALIGN(n, ENET_BUFF_ALIGNMENT) |
mbed_official | 33:9de8bd8ca1c8 | 40 | #define ENET_ALIGN(x,align) ((unsigned int)((x) + ((align)-1)) & (unsigned int)(~(unsigned int)((align)- 1))) |
mbed_official | 33:9de8bd8ca1c8 | 41 | extern void k64f_init_eth_hardware(void); |
mbed_official | 33:9de8bd8ca1c8 | 42 | |
mbed_official | 33:9de8bd8ca1c8 | 43 | /* K64F EMAC driver data structure */ |
mbed_official | 33:9de8bd8ca1c8 | 44 | struct k64f_enetdata { |
mbed_official | 33:9de8bd8ca1c8 | 45 | struct netif *netif; /**< Reference back to LWIP parent netif */ |
mbed_official | 33:9de8bd8ca1c8 | 46 | sys_sem_t RxReadySem; /**< RX packet ready semaphore */ |
mbed_official | 33:9de8bd8ca1c8 | 47 | sys_sem_t TxCleanSem; /**< TX cleanup thread wakeup semaphore */ |
mbed_official | 33:9de8bd8ca1c8 | 48 | sys_mutex_t TXLockMutex; /**< TX critical section mutex */ |
mbed_official | 33:9de8bd8ca1c8 | 49 | sys_sem_t xTXDCountSem; /**< TX free buffer counting semaphore */ |
mbed_official | 33:9de8bd8ca1c8 | 50 | uint8_t tx_consume_index, tx_produce_index; /**< TX buffers ring */ |
mbed_official | 33:9de8bd8ca1c8 | 51 | }; |
mbed_official | 33:9de8bd8ca1c8 | 52 | |
mbed_official | 33:9de8bd8ca1c8 | 53 | static struct k64f_enetdata k64f_enetdata; |
mbed_official | 33:9de8bd8ca1c8 | 54 | |
mbed_official | 33:9de8bd8ca1c8 | 55 | /** \brief Driver transmit and receive thread priorities |
mbed_official | 33:9de8bd8ca1c8 | 56 | * |
mbed_official | 33:9de8bd8ca1c8 | 57 | * Thread priorities for receive thread and TX cleanup thread. Alter |
mbed_official | 33:9de8bd8ca1c8 | 58 | * to prioritize receive or transmit bandwidth. In a heavily loaded |
mbed_official | 33:9de8bd8ca1c8 | 59 | * system or with LEIP_DEBUG enabled, the priorities might be better |
mbed_official | 33:9de8bd8ca1c8 | 60 | * the same. */ |
mbed_official | 33:9de8bd8ca1c8 | 61 | #define RX_PRIORITY (osPriorityNormal) |
mbed_official | 33:9de8bd8ca1c8 | 62 | #define TX_PRIORITY (osPriorityNormal) |
mbed_official | 33:9de8bd8ca1c8 | 63 | #define PHY_PRIORITY (osPriorityNormal) |
mbed_official | 33:9de8bd8ca1c8 | 64 | |
mbed_official | 33:9de8bd8ca1c8 | 65 | /******************************************************************************** |
mbed_official | 33:9de8bd8ca1c8 | 66 | * Buffer management |
mbed_official | 33:9de8bd8ca1c8 | 67 | ********************************************************************************/ |
mbed_official | 33:9de8bd8ca1c8 | 68 | /* |
mbed_official | 33:9de8bd8ca1c8 | 69 | * This function will queue a new receive buffer |
mbed_official | 33:9de8bd8ca1c8 | 70 | */ |
mbed_official | 33:9de8bd8ca1c8 | 71 | static void update_read_buffer(uint8_t *buf) |
mbed_official | 33:9de8bd8ca1c8 | 72 | { |
mbed_official | 33:9de8bd8ca1c8 | 73 | if (buf != NULL) { |
mbed_official | 33:9de8bd8ca1c8 | 74 | g_handle.rxBdCurrent->buffer = buf; |
mbed_official | 33:9de8bd8ca1c8 | 75 | } |
mbed_official | 33:9de8bd8ca1c8 | 76 | |
mbed_official | 33:9de8bd8ca1c8 | 77 | /* Clears status. */ |
mbed_official | 33:9de8bd8ca1c8 | 78 | g_handle.rxBdCurrent->control &= ENET_BUFFDESCRIPTOR_RX_WRAP_MASK; |
mbed_official | 33:9de8bd8ca1c8 | 79 | |
mbed_official | 33:9de8bd8ca1c8 | 80 | /* Sets the receive buffer descriptor with the empty flag. */ |
mbed_official | 33:9de8bd8ca1c8 | 81 | g_handle.rxBdCurrent->control |= ENET_BUFFDESCRIPTOR_RX_EMPTY_MASK; |
mbed_official | 33:9de8bd8ca1c8 | 82 | |
mbed_official | 33:9de8bd8ca1c8 | 83 | /* Increases the buffer descriptor to the next one. */ |
mbed_official | 33:9de8bd8ca1c8 | 84 | if (g_handle.rxBdCurrent->control & ENET_BUFFDESCRIPTOR_RX_WRAP_MASK) { |
mbed_official | 33:9de8bd8ca1c8 | 85 | g_handle.rxBdCurrent = g_handle.rxBdBase; |
mbed_official | 33:9de8bd8ca1c8 | 86 | g_handle.rxBdDirty = g_handle.rxBdBase; |
mbed_official | 33:9de8bd8ca1c8 | 87 | } else { |
mbed_official | 33:9de8bd8ca1c8 | 88 | g_handle.rxBdCurrent++; |
mbed_official | 33:9de8bd8ca1c8 | 89 | g_handle.rxBdDirty++; |
mbed_official | 33:9de8bd8ca1c8 | 90 | } |
mbed_official | 33:9de8bd8ca1c8 | 91 | |
mbed_official | 33:9de8bd8ca1c8 | 92 | /* Actives the receive buffer descriptor. */ |
mbed_official | 33:9de8bd8ca1c8 | 93 | ENET->RDAR = ENET_RDAR_RDAR_MASK; |
mbed_official | 33:9de8bd8ca1c8 | 94 | } |
mbed_official | 33:9de8bd8ca1c8 | 95 | |
mbed_official | 33:9de8bd8ca1c8 | 96 | /** \brief Free TX buffers that are complete |
mbed_official | 33:9de8bd8ca1c8 | 97 | * |
mbed_official | 33:9de8bd8ca1c8 | 98 | * \param[in] k64f_enet Pointer to driver data structure |
mbed_official | 33:9de8bd8ca1c8 | 99 | */ |
mbed_official | 33:9de8bd8ca1c8 | 100 | static void k64f_tx_reclaim(struct k64f_enetdata *k64f_enet) |
mbed_official | 33:9de8bd8ca1c8 | 101 | { |
mbed_official | 33:9de8bd8ca1c8 | 102 | uint8_t i = 0 ; |
mbed_official | 33:9de8bd8ca1c8 | 103 | |
mbed_official | 33:9de8bd8ca1c8 | 104 | /* Get exclusive access */ |
mbed_official | 33:9de8bd8ca1c8 | 105 | sys_mutex_lock(&k64f_enet->TXLockMutex); |
mbed_official | 33:9de8bd8ca1c8 | 106 | |
mbed_official | 33:9de8bd8ca1c8 | 107 | i = k64f_enet->tx_consume_index; |
mbed_official | 33:9de8bd8ca1c8 | 108 | // Traverse all descriptors, looking for the ones modified by the uDMA |
mbed_official | 33:9de8bd8ca1c8 | 109 | while((i != k64f_enet->tx_produce_index) && (!(g_handle.txBdDirty->control & ENET_BUFFDESCRIPTOR_TX_READY_MASK))) { |
mbed_official | 33:9de8bd8ca1c8 | 110 | pbuf_free(tx_buff[i]); |
mbed_official | 33:9de8bd8ca1c8 | 111 | if (g_handle.txBdDirty->control & ENET_BUFFDESCRIPTOR_TX_WRAP_MASK) |
mbed_official | 33:9de8bd8ca1c8 | 112 | g_handle.txBdDirty = g_handle.txBdBase; |
mbed_official | 33:9de8bd8ca1c8 | 113 | else |
mbed_official | 33:9de8bd8ca1c8 | 114 | g_handle.txBdDirty++; |
mbed_official | 33:9de8bd8ca1c8 | 115 | |
mbed_official | 33:9de8bd8ca1c8 | 116 | i = (i + 1) % ENET_TX_RING_LEN; |
mbed_official | 33:9de8bd8ca1c8 | 117 | } |
mbed_official | 33:9de8bd8ca1c8 | 118 | |
mbed_official | 33:9de8bd8ca1c8 | 119 | k64f_enet->tx_consume_index = i; |
mbed_official | 33:9de8bd8ca1c8 | 120 | /* Restore access */ |
mbed_official | 33:9de8bd8ca1c8 | 121 | sys_mutex_unlock(&k64f_enet->TXLockMutex); |
mbed_official | 33:9de8bd8ca1c8 | 122 | } |
mbed_official | 33:9de8bd8ca1c8 | 123 | |
mbed_official | 33:9de8bd8ca1c8 | 124 | /** \brief Ethernet receive interrupt handler |
mbed_official | 33:9de8bd8ca1c8 | 125 | * |
mbed_official | 33:9de8bd8ca1c8 | 126 | * This function handles the receive interrupt of K64F. |
mbed_official | 33:9de8bd8ca1c8 | 127 | */ |
mbed_official | 33:9de8bd8ca1c8 | 128 | void enet_mac_rx_isr() |
mbed_official | 33:9de8bd8ca1c8 | 129 | { |
mbed_official | 33:9de8bd8ca1c8 | 130 | sys_sem_signal(&k64f_enetdata.RxReadySem); |
mbed_official | 33:9de8bd8ca1c8 | 131 | } |
mbed_official | 33:9de8bd8ca1c8 | 132 | |
mbed_official | 33:9de8bd8ca1c8 | 133 | void enet_mac_tx_isr() |
mbed_official | 33:9de8bd8ca1c8 | 134 | { |
mbed_official | 33:9de8bd8ca1c8 | 135 | sys_sem_signal(&k64f_enetdata.TxCleanSem); |
mbed_official | 33:9de8bd8ca1c8 | 136 | } |
mbed_official | 33:9de8bd8ca1c8 | 137 | |
mbed_official | 33:9de8bd8ca1c8 | 138 | void ethernet_callback(ENET_Type *base, enet_handle_t *handle, enet_event_t event, void *param) |
mbed_official | 33:9de8bd8ca1c8 | 139 | { |
mbed_official | 33:9de8bd8ca1c8 | 140 | switch (event) |
mbed_official | 33:9de8bd8ca1c8 | 141 | { |
mbed_official | 33:9de8bd8ca1c8 | 142 | case kENET_RxEvent: |
mbed_official | 33:9de8bd8ca1c8 | 143 | enet_mac_rx_isr(); |
mbed_official | 33:9de8bd8ca1c8 | 144 | break; |
mbed_official | 33:9de8bd8ca1c8 | 145 | case kENET_TxEvent: |
mbed_official | 33:9de8bd8ca1c8 | 146 | enet_mac_tx_isr(); |
mbed_official | 33:9de8bd8ca1c8 | 147 | break; |
mbed_official | 33:9de8bd8ca1c8 | 148 | default: |
mbed_official | 33:9de8bd8ca1c8 | 149 | break; |
mbed_official | 33:9de8bd8ca1c8 | 150 | } |
mbed_official | 33:9de8bd8ca1c8 | 151 | } |
mbed_official | 33:9de8bd8ca1c8 | 152 | |
mbed_official | 33:9de8bd8ca1c8 | 153 | /** \brief Low level init of the MAC and PHY. |
mbed_official | 33:9de8bd8ca1c8 | 154 | * |
mbed_official | 33:9de8bd8ca1c8 | 155 | * \param[in] netif Pointer to LWIP netif structure |
mbed_official | 33:9de8bd8ca1c8 | 156 | */ |
mbed_official | 33:9de8bd8ca1c8 | 157 | static err_t low_level_init(struct netif *netif) |
mbed_official | 33:9de8bd8ca1c8 | 158 | { |
mbed_official | 33:9de8bd8ca1c8 | 159 | struct k64f_enetdata *k64f_enet = netif->state; |
mbed_official | 33:9de8bd8ca1c8 | 160 | uint8_t i; |
mbed_official | 33:9de8bd8ca1c8 | 161 | uint32_t sysClock; |
mbed_official | 33:9de8bd8ca1c8 | 162 | phy_speed_t phy_speed; |
mbed_official | 33:9de8bd8ca1c8 | 163 | phy_duplex_t phy_duplex; |
mbed_official | 33:9de8bd8ca1c8 | 164 | uint32_t phyAddr = 0; |
mbed_official | 33:9de8bd8ca1c8 | 165 | bool link = false; |
mbed_official | 33:9de8bd8ca1c8 | 166 | enet_config_t config; |
mbed_official | 33:9de8bd8ca1c8 | 167 | |
mbed_official | 33:9de8bd8ca1c8 | 168 | // Allocate RX descriptors |
mbed_official | 33:9de8bd8ca1c8 | 169 | rx_desc_start_addr = (uint8_t *)calloc(1, sizeof(enet_rx_bd_struct_t) * ENET_RX_RING_LEN + ENET_BUFF_ALIGNMENT); |
mbed_official | 33:9de8bd8ca1c8 | 170 | if(!rx_desc_start_addr) |
mbed_official | 33:9de8bd8ca1c8 | 171 | return ERR_MEM; |
mbed_official | 33:9de8bd8ca1c8 | 172 | |
mbed_official | 33:9de8bd8ca1c8 | 173 | // Allocate TX descriptors |
mbed_official | 33:9de8bd8ca1c8 | 174 | tx_desc_start_addr = (uint8_t *)calloc(1, sizeof(enet_tx_bd_struct_t) * ENET_TX_RING_LEN + ENET_BUFF_ALIGNMENT); |
mbed_official | 33:9de8bd8ca1c8 | 175 | if(!tx_desc_start_addr) |
mbed_official | 33:9de8bd8ca1c8 | 176 | return ERR_MEM; |
mbed_official | 33:9de8bd8ca1c8 | 177 | |
mbed_official | 33:9de8bd8ca1c8 | 178 | rx_desc_start_addr = (uint8_t *)ENET_ALIGN(rx_desc_start_addr, ENET_BUFF_ALIGNMENT); |
mbed_official | 33:9de8bd8ca1c8 | 179 | tx_desc_start_addr = (uint8_t *)ENET_ALIGN(tx_desc_start_addr, ENET_BUFF_ALIGNMENT); |
mbed_official | 33:9de8bd8ca1c8 | 180 | |
mbed_official | 33:9de8bd8ca1c8 | 181 | /* Create buffers for each receive BD */ |
mbed_official | 33:9de8bd8ca1c8 | 182 | for (i = 0; i < ENET_RX_RING_LEN; i++) { |
mbed_official | 33:9de8bd8ca1c8 | 183 | rx_buff[i] = pbuf_alloc(PBUF_RAW, ENET_ETH_MAX_FLEN + ENET_BUFF_ALIGNMENT, PBUF_RAM); |
mbed_official | 33:9de8bd8ca1c8 | 184 | if (NULL == rx_buff[i]) |
mbed_official | 33:9de8bd8ca1c8 | 185 | return ERR_MEM; |
mbed_official | 33:9de8bd8ca1c8 | 186 | |
mbed_official | 33:9de8bd8ca1c8 | 187 | /* K64F note: the next line ensures that the RX buffer is properly aligned for the K64F |
mbed_official | 33:9de8bd8ca1c8 | 188 | RX descriptors (16 bytes alignment). However, by doing so, we're effectively changing |
mbed_official | 33:9de8bd8ca1c8 | 189 | a data structure which is internal to lwIP. This might not prove to be a good idea |
mbed_official | 33:9de8bd8ca1c8 | 190 | in the long run, but a better fix would probably involve modifying lwIP itself */ |
mbed_official | 33:9de8bd8ca1c8 | 191 | rx_buff[i]->payload = (void*)ENET_ALIGN((uint32_t)rx_buff[i]->payload, ENET_BUFF_ALIGNMENT); |
mbed_official | 33:9de8bd8ca1c8 | 192 | rx_ptr[i] = rx_buff[i]->payload; |
mbed_official | 33:9de8bd8ca1c8 | 193 | } |
mbed_official | 33:9de8bd8ca1c8 | 194 | |
mbed_official | 33:9de8bd8ca1c8 | 195 | k64f_enet->tx_consume_index = k64f_enet->tx_produce_index = 0; |
mbed_official | 33:9de8bd8ca1c8 | 196 | |
mbed_official | 33:9de8bd8ca1c8 | 197 | /* prepare the buffer configuration. */ |
mbed_official | 33:9de8bd8ca1c8 | 198 | enet_buffer_config_t buffCfg = { |
mbed_official | 33:9de8bd8ca1c8 | 199 | ENET_RX_RING_LEN, |
mbed_official | 33:9de8bd8ca1c8 | 200 | ENET_TX_RING_LEN, |
mbed_official | 33:9de8bd8ca1c8 | 201 | ENET_ALIGN(ENET_ETH_MAX_FLEN, ENET_BUFF_ALIGNMENT), |
mbed_official | 33:9de8bd8ca1c8 | 202 | 0, |
mbed_official | 33:9de8bd8ca1c8 | 203 | (volatile enet_rx_bd_struct_t *)rx_desc_start_addr, |
mbed_official | 33:9de8bd8ca1c8 | 204 | (volatile enet_tx_bd_struct_t *)tx_desc_start_addr, |
mbed_official | 33:9de8bd8ca1c8 | 205 | (uint8_t *)&rx_ptr, |
mbed_official | 33:9de8bd8ca1c8 | 206 | NULL, |
mbed_official | 33:9de8bd8ca1c8 | 207 | }; |
mbed_official | 33:9de8bd8ca1c8 | 208 | |
mbed_official | 33:9de8bd8ca1c8 | 209 | k64f_init_eth_hardware(); |
mbed_official | 33:9de8bd8ca1c8 | 210 | |
mbed_official | 33:9de8bd8ca1c8 | 211 | sysClock = CLOCK_GetFreq(kCLOCK_CoreSysClk); |
mbed_official | 33:9de8bd8ca1c8 | 212 | |
mbed_official | 33:9de8bd8ca1c8 | 213 | ENET_GetDefaultConfig(&config); |
mbed_official | 33:9de8bd8ca1c8 | 214 | |
mbed_official | 33:9de8bd8ca1c8 | 215 | PHY_Init(ENET, 0, sysClock); |
mbed_official | 33:9de8bd8ca1c8 | 216 | PHY_GetLinkStatus(ENET, phyAddr, &link); |
mbed_official | 33:9de8bd8ca1c8 | 217 | if (link) |
mbed_official | 33:9de8bd8ca1c8 | 218 | { |
mbed_official | 33:9de8bd8ca1c8 | 219 | /* Get link information from PHY */ |
mbed_official | 33:9de8bd8ca1c8 | 220 | PHY_GetLinkSpeedDuplex(ENET, phyAddr, &phy_speed, &phy_duplex); |
mbed_official | 33:9de8bd8ca1c8 | 221 | /* Change the MII speed and duplex for actual link status. */ |
mbed_official | 33:9de8bd8ca1c8 | 222 | config.miiSpeed = (enet_mii_speed_t)phy_speed; |
mbed_official | 33:9de8bd8ca1c8 | 223 | config.miiDuplex = (enet_mii_duplex_t)phy_duplex; |
mbed_official | 33:9de8bd8ca1c8 | 224 | config.interrupt = kENET_RxFrameInterrupt | kENET_TxFrameInterrupt; |
mbed_official | 33:9de8bd8ca1c8 | 225 | } |
mbed_official | 33:9de8bd8ca1c8 | 226 | config.rxMaxFrameLen = ENET_ETH_MAX_FLEN; |
mbed_official | 33:9de8bd8ca1c8 | 227 | config.macSpecialConfig = kENET_ControlFlowControlEnable; |
mbed_official | 33:9de8bd8ca1c8 | 228 | config.txAccelerConfig = kENET_TxAccelIsShift16Enabled; |
mbed_official | 33:9de8bd8ca1c8 | 229 | config.rxAccelerConfig = kENET_RxAccelisShift16Enabled | kENET_RxAccelMacCheckEnabled; |
mbed_official | 33:9de8bd8ca1c8 | 230 | ENET_Init(ENET, &g_handle, &config, &buffCfg, netif->hwaddr, sysClock); |
mbed_official | 33:9de8bd8ca1c8 | 231 | ENET_SetCallback(&g_handle, ethernet_callback, netif); |
mbed_official | 33:9de8bd8ca1c8 | 232 | ENET_ActiveRead(ENET); |
mbed_official | 33:9de8bd8ca1c8 | 233 | |
mbed_official | 33:9de8bd8ca1c8 | 234 | return ERR_OK; |
mbed_official | 33:9de8bd8ca1c8 | 235 | } |
mbed_official | 33:9de8bd8ca1c8 | 236 | |
mbed_official | 33:9de8bd8ca1c8 | 237 | |
mbed_official | 33:9de8bd8ca1c8 | 238 | /** |
mbed_official | 33:9de8bd8ca1c8 | 239 | * This function is the ethernet packet send function. It calls |
mbed_official | 33:9de8bd8ca1c8 | 240 | * etharp_output after checking link status. |
mbed_official | 33:9de8bd8ca1c8 | 241 | * |
mbed_official | 33:9de8bd8ca1c8 | 242 | * \param[in] netif the lwip network interface structure for this enetif |
mbed_official | 33:9de8bd8ca1c8 | 243 | * \param[in] q Pointer to pbug to send |
mbed_official | 33:9de8bd8ca1c8 | 244 | * \param[in] ipaddr IP address |
mbed_official | 33:9de8bd8ca1c8 | 245 | * \return ERR_OK or error code |
mbed_official | 33:9de8bd8ca1c8 | 246 | */ |
mbed_official | 33:9de8bd8ca1c8 | 247 | err_t k64f_etharp_output(struct netif *netif, struct pbuf *q, ip_addr_t *ipaddr) |
mbed_official | 33:9de8bd8ca1c8 | 248 | { |
mbed_official | 33:9de8bd8ca1c8 | 249 | /* Only send packet is link is up */ |
mbed_official | 33:9de8bd8ca1c8 | 250 | if (netif->flags & NETIF_FLAG_LINK_UP) |
mbed_official | 33:9de8bd8ca1c8 | 251 | return etharp_output(netif, q, ipaddr); |
mbed_official | 33:9de8bd8ca1c8 | 252 | |
mbed_official | 33:9de8bd8ca1c8 | 253 | return ERR_CONN; |
mbed_official | 33:9de8bd8ca1c8 | 254 | } |
mbed_official | 33:9de8bd8ca1c8 | 255 | |
mbed_official | 33:9de8bd8ca1c8 | 256 | /** \brief Allocates a pbuf and returns the data from the incoming packet. |
mbed_official | 33:9de8bd8ca1c8 | 257 | * |
mbed_official | 33:9de8bd8ca1c8 | 258 | * \param[in] netif the lwip network interface structure |
mbed_official | 33:9de8bd8ca1c8 | 259 | * \param[in] idx index of packet to be read |
mbed_official | 33:9de8bd8ca1c8 | 260 | * \return a pbuf filled with the received packet (including MAC header) |
mbed_official | 33:9de8bd8ca1c8 | 261 | */ |
mbed_official | 33:9de8bd8ca1c8 | 262 | static struct pbuf *k64f_low_level_input(struct netif *netif, int idx) |
mbed_official | 33:9de8bd8ca1c8 | 263 | { |
mbed_official | 33:9de8bd8ca1c8 | 264 | volatile enet_rx_bd_struct_t *bdPtr = g_handle.rxBdCurrent; |
mbed_official | 33:9de8bd8ca1c8 | 265 | struct pbuf *p = NULL; |
mbed_official | 33:9de8bd8ca1c8 | 266 | struct pbuf *temp_rxbuf = NULL; |
mbed_official | 33:9de8bd8ca1c8 | 267 | u32_t length = 0; |
mbed_official | 33:9de8bd8ca1c8 | 268 | const u16_t err_mask = ENET_BUFFDESCRIPTOR_RX_TRUNC_MASK | ENET_BUFFDESCRIPTOR_RX_CRC_MASK | |
mbed_official | 33:9de8bd8ca1c8 | 269 | ENET_BUFFDESCRIPTOR_RX_NOOCTET_MASK | ENET_BUFFDESCRIPTOR_RX_LENVLIOLATE_MASK; |
mbed_official | 33:9de8bd8ca1c8 | 270 | |
mbed_official | 33:9de8bd8ca1c8 | 271 | |
mbed_official | 33:9de8bd8ca1c8 | 272 | #ifdef LOCK_RX_THREAD |
mbed_official | 33:9de8bd8ca1c8 | 273 | /* Get exclusive access */ |
mbed_official | 33:9de8bd8ca1c8 | 274 | sys_mutex_lock(&k64f_enet->TXLockMutex); |
mbed_official | 33:9de8bd8ca1c8 | 275 | #endif |
mbed_official | 33:9de8bd8ca1c8 | 276 | |
mbed_official | 33:9de8bd8ca1c8 | 277 | /* Determine if a frame has been received */ |
mbed_official | 33:9de8bd8ca1c8 | 278 | if ((bdPtr->control & err_mask) != 0) { |
mbed_official | 33:9de8bd8ca1c8 | 279 | #if LINK_STATS |
mbed_official | 33:9de8bd8ca1c8 | 280 | if ((bdPtr->control & ENET_BUFFDESCRIPTOR_RX_LENVLIOLATE_MASK) != 0) |
mbed_official | 33:9de8bd8ca1c8 | 281 | LINK_STATS_INC(link.lenerr); |
mbed_official | 33:9de8bd8ca1c8 | 282 | else |
mbed_official | 33:9de8bd8ca1c8 | 283 | LINK_STATS_INC(link.chkerr); |
mbed_official | 33:9de8bd8ca1c8 | 284 | #endif |
mbed_official | 33:9de8bd8ca1c8 | 285 | LINK_STATS_INC(link.drop); |
mbed_official | 33:9de8bd8ca1c8 | 286 | /* Re-use the same buffer in case of error */ |
mbed_official | 33:9de8bd8ca1c8 | 287 | update_read_buffer(NULL); |
mbed_official | 33:9de8bd8ca1c8 | 288 | } else { |
mbed_official | 33:9de8bd8ca1c8 | 289 | /* A packet is waiting, get length */ |
mbed_official | 33:9de8bd8ca1c8 | 290 | length = bdPtr->length; |
mbed_official | 33:9de8bd8ca1c8 | 291 | |
mbed_official | 33:9de8bd8ca1c8 | 292 | /* Zero-copy */ |
mbed_official | 33:9de8bd8ca1c8 | 293 | p = rx_buff[idx]; |
mbed_official | 33:9de8bd8ca1c8 | 294 | p->len = length; |
mbed_official | 33:9de8bd8ca1c8 | 295 | |
mbed_official | 33:9de8bd8ca1c8 | 296 | /* Attempt to queue new buffer */ |
mbed_official | 33:9de8bd8ca1c8 | 297 | temp_rxbuf = pbuf_alloc(PBUF_RAW, ENET_ETH_MAX_FLEN + ENET_BUFF_ALIGNMENT, PBUF_RAM); |
mbed_official | 33:9de8bd8ca1c8 | 298 | if (NULL == temp_rxbuf) { |
mbed_official | 33:9de8bd8ca1c8 | 299 | /* Drop frame (out of memory) */ |
mbed_official | 33:9de8bd8ca1c8 | 300 | LINK_STATS_INC(link.drop); |
mbed_official | 33:9de8bd8ca1c8 | 301 | |
mbed_official | 33:9de8bd8ca1c8 | 302 | /* Re-queue the same buffer */ |
mbed_official | 33:9de8bd8ca1c8 | 303 | update_read_buffer(NULL); |
mbed_official | 33:9de8bd8ca1c8 | 304 | |
mbed_official | 33:9de8bd8ca1c8 | 305 | LWIP_DEBUGF(UDP_LPC_EMAC | LWIP_DBG_TRACE, |
mbed_official | 33:9de8bd8ca1c8 | 306 | ("k64f_low_level_input: Packet index %d dropped for OOM\n", |
mbed_official | 33:9de8bd8ca1c8 | 307 | idx)); |
mbed_official | 33:9de8bd8ca1c8 | 308 | #ifdef LOCK_RX_THREAD |
mbed_official | 33:9de8bd8ca1c8 | 309 | sys_mutex_unlock(&k64f_enet->TXLockMutex); |
mbed_official | 33:9de8bd8ca1c8 | 310 | #endif |
mbed_official | 33:9de8bd8ca1c8 | 311 | |
mbed_official | 33:9de8bd8ca1c8 | 312 | return NULL; |
mbed_official | 33:9de8bd8ca1c8 | 313 | } |
mbed_official | 33:9de8bd8ca1c8 | 314 | |
mbed_official | 33:9de8bd8ca1c8 | 315 | rx_buff[idx] = temp_rxbuf; |
mbed_official | 33:9de8bd8ca1c8 | 316 | /* K64F note: the next line ensures that the RX buffer is properly aligned for the K64F |
mbed_official | 33:9de8bd8ca1c8 | 317 | RX descriptors (16 bytes alignment). However, by doing so, we're effectively changing |
mbed_official | 33:9de8bd8ca1c8 | 318 | a data structure which is internal to lwIP. This might not prove to be a good idea |
mbed_official | 33:9de8bd8ca1c8 | 319 | in the long run, but a better fix would probably involve modifying lwIP itself */ |
mbed_official | 33:9de8bd8ca1c8 | 320 | rx_buff[idx]->payload = (void*)ENET_ALIGN((uint32_t)rx_buff[idx]->payload, ENET_BUFF_ALIGNMENT); |
mbed_official | 33:9de8bd8ca1c8 | 321 | rx_ptr[idx] = rx_buff[idx]->payload; |
mbed_official | 33:9de8bd8ca1c8 | 322 | |
mbed_official | 33:9de8bd8ca1c8 | 323 | update_read_buffer(rx_buff[idx]->payload); |
mbed_official | 33:9de8bd8ca1c8 | 324 | LWIP_DEBUGF(UDP_LPC_EMAC | LWIP_DBG_TRACE, |
mbed_official | 33:9de8bd8ca1c8 | 325 | ("k64f_low_level_input: Packet received: %p, size %d (index=%d)\n", |
mbed_official | 33:9de8bd8ca1c8 | 326 | p, length, idx)); |
mbed_official | 33:9de8bd8ca1c8 | 327 | |
mbed_official | 33:9de8bd8ca1c8 | 328 | /* Save size */ |
mbed_official | 33:9de8bd8ca1c8 | 329 | p->tot_len = (u16_t) length; |
mbed_official | 33:9de8bd8ca1c8 | 330 | LINK_STATS_INC(link.recv); |
mbed_official | 33:9de8bd8ca1c8 | 331 | } |
mbed_official | 33:9de8bd8ca1c8 | 332 | |
mbed_official | 33:9de8bd8ca1c8 | 333 | #ifdef LOCK_RX_THREAD |
mbed_official | 33:9de8bd8ca1c8 | 334 | sys_mutex_unlock(&k64f_enet->TXLockMutex); |
mbed_official | 33:9de8bd8ca1c8 | 335 | #endif |
mbed_official | 33:9de8bd8ca1c8 | 336 | |
mbed_official | 33:9de8bd8ca1c8 | 337 | return p; |
mbed_official | 33:9de8bd8ca1c8 | 338 | } |
mbed_official | 33:9de8bd8ca1c8 | 339 | |
mbed_official | 33:9de8bd8ca1c8 | 340 | /** \brief Attempt to read a packet from the EMAC interface. |
mbed_official | 33:9de8bd8ca1c8 | 341 | * |
mbed_official | 33:9de8bd8ca1c8 | 342 | * \param[in] netif the lwip network interface structure |
mbed_official | 33:9de8bd8ca1c8 | 343 | * \param[in] idx index of packet to be read |
mbed_official | 33:9de8bd8ca1c8 | 344 | */ |
mbed_official | 33:9de8bd8ca1c8 | 345 | void k64f_enetif_input(struct netif *netif, int idx) |
mbed_official | 33:9de8bd8ca1c8 | 346 | { |
mbed_official | 33:9de8bd8ca1c8 | 347 | struct eth_hdr *ethhdr; |
mbed_official | 33:9de8bd8ca1c8 | 348 | struct pbuf *p; |
mbed_official | 33:9de8bd8ca1c8 | 349 | |
mbed_official | 33:9de8bd8ca1c8 | 350 | /* move received packet into a new pbuf */ |
mbed_official | 33:9de8bd8ca1c8 | 351 | p = k64f_low_level_input(netif, idx); |
mbed_official | 33:9de8bd8ca1c8 | 352 | if (p == NULL) |
mbed_official | 33:9de8bd8ca1c8 | 353 | return; |
mbed_official | 33:9de8bd8ca1c8 | 354 | |
mbed_official | 33:9de8bd8ca1c8 | 355 | /* points to packet payload, which starts with an Ethernet header */ |
mbed_official | 33:9de8bd8ca1c8 | 356 | ethhdr = (struct eth_hdr*)p->payload; |
mbed_official | 33:9de8bd8ca1c8 | 357 | |
mbed_official | 33:9de8bd8ca1c8 | 358 | switch (htons(ethhdr->type)) { |
mbed_official | 33:9de8bd8ca1c8 | 359 | case ETHTYPE_IP: |
mbed_official | 33:9de8bd8ca1c8 | 360 | case ETHTYPE_ARP: |
mbed_official | 33:9de8bd8ca1c8 | 361 | #if PPPOE_SUPPORT |
mbed_official | 33:9de8bd8ca1c8 | 362 | case ETHTYPE_PPPOEDISC: |
mbed_official | 33:9de8bd8ca1c8 | 363 | case ETHTYPE_PPPOE: |
mbed_official | 33:9de8bd8ca1c8 | 364 | #endif /* PPPOE_SUPPORT */ |
mbed_official | 33:9de8bd8ca1c8 | 365 | /* full packet send to tcpip_thread to process */ |
mbed_official | 33:9de8bd8ca1c8 | 366 | if (netif->input(p, netif) != ERR_OK) { |
mbed_official | 33:9de8bd8ca1c8 | 367 | LWIP_DEBUGF(NETIF_DEBUG, ("k64f_enetif_input: IP input error\n")); |
mbed_official | 33:9de8bd8ca1c8 | 368 | /* Free buffer */ |
mbed_official | 33:9de8bd8ca1c8 | 369 | pbuf_free(p); |
mbed_official | 33:9de8bd8ca1c8 | 370 | } |
mbed_official | 33:9de8bd8ca1c8 | 371 | break; |
mbed_official | 33:9de8bd8ca1c8 | 372 | |
mbed_official | 33:9de8bd8ca1c8 | 373 | default: |
mbed_official | 33:9de8bd8ca1c8 | 374 | /* Return buffer */ |
mbed_official | 33:9de8bd8ca1c8 | 375 | pbuf_free(p); |
mbed_official | 33:9de8bd8ca1c8 | 376 | break; |
mbed_official | 33:9de8bd8ca1c8 | 377 | } |
mbed_official | 33:9de8bd8ca1c8 | 378 | } |
mbed_official | 33:9de8bd8ca1c8 | 379 | |
mbed_official | 33:9de8bd8ca1c8 | 380 | /** \brief Packet reception task |
mbed_official | 33:9de8bd8ca1c8 | 381 | * |
mbed_official | 33:9de8bd8ca1c8 | 382 | * This task is called when a packet is received. It will |
mbed_official | 33:9de8bd8ca1c8 | 383 | * pass the packet to the LWIP core. |
mbed_official | 33:9de8bd8ca1c8 | 384 | * |
mbed_official | 33:9de8bd8ca1c8 | 385 | * \param[in] pvParameters pointer to the interface data |
mbed_official | 33:9de8bd8ca1c8 | 386 | */ |
mbed_official | 33:9de8bd8ca1c8 | 387 | static void packet_rx(void* pvParameters) { |
mbed_official | 33:9de8bd8ca1c8 | 388 | struct k64f_enetdata *k64f_enet = pvParameters; |
mbed_official | 33:9de8bd8ca1c8 | 389 | int idx = 0; |
mbed_official | 33:9de8bd8ca1c8 | 390 | |
mbed_official | 33:9de8bd8ca1c8 | 391 | while (1) { |
mbed_official | 33:9de8bd8ca1c8 | 392 | /* Wait for receive task to wakeup */ |
mbed_official | 33:9de8bd8ca1c8 | 393 | sys_arch_sem_wait(&k64f_enet->RxReadySem, 0); |
mbed_official | 33:9de8bd8ca1c8 | 394 | |
mbed_official | 33:9de8bd8ca1c8 | 395 | while ((g_handle.rxBdCurrent->control & ENET_BUFFDESCRIPTOR_RX_EMPTY_MASK) == 0) { |
mbed_official | 33:9de8bd8ca1c8 | 396 | k64f_enetif_input(k64f_enet->netif, idx); |
mbed_official | 33:9de8bd8ca1c8 | 397 | idx = (idx + 1) % ENET_RX_RING_LEN; |
mbed_official | 33:9de8bd8ca1c8 | 398 | } |
mbed_official | 33:9de8bd8ca1c8 | 399 | } |
mbed_official | 33:9de8bd8ca1c8 | 400 | } |
mbed_official | 33:9de8bd8ca1c8 | 401 | |
mbed_official | 33:9de8bd8ca1c8 | 402 | /** \brief Transmit cleanup task |
mbed_official | 33:9de8bd8ca1c8 | 403 | * |
mbed_official | 33:9de8bd8ca1c8 | 404 | * This task is called when a transmit interrupt occurs and |
mbed_official | 33:9de8bd8ca1c8 | 405 | * reclaims the pbuf and descriptor used for the packet once |
mbed_official | 33:9de8bd8ca1c8 | 406 | * the packet has been transferred. |
mbed_official | 33:9de8bd8ca1c8 | 407 | * |
mbed_official | 33:9de8bd8ca1c8 | 408 | * \param[in] pvParameters pointer to the interface data |
mbed_official | 33:9de8bd8ca1c8 | 409 | */ |
mbed_official | 33:9de8bd8ca1c8 | 410 | static void packet_tx(void* pvParameters) { |
mbed_official | 33:9de8bd8ca1c8 | 411 | struct k64f_enetdata *k64f_enet = pvParameters; |
mbed_official | 33:9de8bd8ca1c8 | 412 | |
mbed_official | 33:9de8bd8ca1c8 | 413 | while (1) { |
mbed_official | 33:9de8bd8ca1c8 | 414 | /* Wait for transmit cleanup task to wakeup */ |
mbed_official | 33:9de8bd8ca1c8 | 415 | sys_arch_sem_wait(&k64f_enet->TxCleanSem, 0); |
mbed_official | 33:9de8bd8ca1c8 | 416 | k64f_tx_reclaim(k64f_enet); |
mbed_official | 33:9de8bd8ca1c8 | 417 | } |
mbed_official | 33:9de8bd8ca1c8 | 418 | } |
mbed_official | 33:9de8bd8ca1c8 | 419 | |
mbed_official | 33:9de8bd8ca1c8 | 420 | /** \brief Low level output of a packet. Never call this from an |
mbed_official | 33:9de8bd8ca1c8 | 421 | * interrupt context, as it may block until TX descriptors |
mbed_official | 33:9de8bd8ca1c8 | 422 | * become available. |
mbed_official | 33:9de8bd8ca1c8 | 423 | * |
mbed_official | 33:9de8bd8ca1c8 | 424 | * \param[in] netif the lwip network interface structure for this netif |
mbed_official | 33:9de8bd8ca1c8 | 425 | * \param[in] p the MAC packet to send (e.g. IP packet including MAC addresses and type) |
mbed_official | 33:9de8bd8ca1c8 | 426 | * \return ERR_OK if the packet could be sent or an err_t value if the packet couldn't be sent |
mbed_official | 33:9de8bd8ca1c8 | 427 | */ |
mbed_official | 33:9de8bd8ca1c8 | 428 | static err_t k64f_low_level_output(struct netif *netif, struct pbuf *p) |
mbed_official | 33:9de8bd8ca1c8 | 429 | { |
mbed_official | 33:9de8bd8ca1c8 | 430 | struct k64f_enetdata *k64f_enet = netif->state; |
mbed_official | 33:9de8bd8ca1c8 | 431 | struct pbuf *q; |
mbed_official | 33:9de8bd8ca1c8 | 432 | struct pbuf *temp_pbuf; |
mbed_official | 33:9de8bd8ca1c8 | 433 | uint8_t *psend = NULL, *dst; |
mbed_official | 33:9de8bd8ca1c8 | 434 | |
mbed_official | 33:9de8bd8ca1c8 | 435 | |
mbed_official | 33:9de8bd8ca1c8 | 436 | temp_pbuf = pbuf_alloc(PBUF_RAW, p->tot_len + ENET_BUFF_ALIGNMENT, PBUF_RAM); |
mbed_official | 33:9de8bd8ca1c8 | 437 | if (NULL == temp_pbuf) |
mbed_official | 33:9de8bd8ca1c8 | 438 | return ERR_MEM; |
mbed_official | 33:9de8bd8ca1c8 | 439 | |
mbed_official | 33:9de8bd8ca1c8 | 440 | /* K64F note: the next line ensures that the RX buffer is properly aligned for the K64F |
mbed_official | 33:9de8bd8ca1c8 | 441 | RX descriptors (16 bytes alignment). However, by doing so, we're effectively changing |
mbed_official | 33:9de8bd8ca1c8 | 442 | a data structure which is internal to lwIP. This might not prove to be a good idea |
mbed_official | 33:9de8bd8ca1c8 | 443 | in the long run, but a better fix would probably involve modifying lwIP itself */ |
mbed_official | 33:9de8bd8ca1c8 | 444 | psend = (uint8_t *)ENET_ALIGN((uint32_t)temp_pbuf->payload, ENET_BUFF_ALIGNMENT); |
mbed_official | 33:9de8bd8ca1c8 | 445 | |
mbed_official | 33:9de8bd8ca1c8 | 446 | for (q = p, dst = psend; q != NULL; q = q->next) { |
mbed_official | 33:9de8bd8ca1c8 | 447 | MEMCPY(dst, q->payload, q->len); |
mbed_official | 33:9de8bd8ca1c8 | 448 | dst += q->len; |
mbed_official | 33:9de8bd8ca1c8 | 449 | } |
mbed_official | 33:9de8bd8ca1c8 | 450 | |
mbed_official | 33:9de8bd8ca1c8 | 451 | /* Wait until a descriptor is available for the transfer. */ |
mbed_official | 33:9de8bd8ca1c8 | 452 | /* THIS WILL BLOCK UNTIL THERE ARE A DESCRIPTOR AVAILABLE */ |
mbed_official | 33:9de8bd8ca1c8 | 453 | while (g_handle.txBdCurrent->control & ENET_BUFFDESCRIPTOR_TX_READY_MASK) |
mbed_official | 33:9de8bd8ca1c8 | 454 | osSemaphoreWait(k64f_enet->xTXDCountSem.id, osWaitForever); |
mbed_official | 33:9de8bd8ca1c8 | 455 | |
mbed_official | 33:9de8bd8ca1c8 | 456 | /* Get exclusive access */ |
mbed_official | 33:9de8bd8ca1c8 | 457 | sys_mutex_lock(&k64f_enet->TXLockMutex); |
mbed_official | 33:9de8bd8ca1c8 | 458 | |
mbed_official | 33:9de8bd8ca1c8 | 459 | /* Save the buffer so that it can be freed when transmit is done */ |
mbed_official | 33:9de8bd8ca1c8 | 460 | tx_buff[k64f_enet->tx_produce_index] = temp_pbuf; |
mbed_official | 33:9de8bd8ca1c8 | 461 | k64f_enet->tx_produce_index = (k64f_enet->tx_produce_index + 1) % ENET_TX_RING_LEN; |
mbed_official | 33:9de8bd8ca1c8 | 462 | |
mbed_official | 33:9de8bd8ca1c8 | 463 | /* Setup transfers */ |
mbed_official | 33:9de8bd8ca1c8 | 464 | g_handle.txBdCurrent->buffer = psend; |
mbed_official | 33:9de8bd8ca1c8 | 465 | g_handle.txBdCurrent->length = p->tot_len; |
mbed_official | 33:9de8bd8ca1c8 | 466 | g_handle.txBdCurrent->control |= (ENET_BUFFDESCRIPTOR_TX_READY_MASK | ENET_BUFFDESCRIPTOR_TX_LAST_MASK); |
mbed_official | 33:9de8bd8ca1c8 | 467 | |
mbed_official | 33:9de8bd8ca1c8 | 468 | /* Increase the buffer descriptor address. */ |
mbed_official | 33:9de8bd8ca1c8 | 469 | if (g_handle.txBdCurrent->control & ENET_BUFFDESCRIPTOR_TX_WRAP_MASK) |
mbed_official | 33:9de8bd8ca1c8 | 470 | g_handle.txBdCurrent = g_handle.txBdBase; |
mbed_official | 33:9de8bd8ca1c8 | 471 | else |
mbed_official | 33:9de8bd8ca1c8 | 472 | g_handle.txBdCurrent++; |
mbed_official | 33:9de8bd8ca1c8 | 473 | |
mbed_official | 33:9de8bd8ca1c8 | 474 | /* Active the transmit buffer descriptor. */ |
mbed_official | 33:9de8bd8ca1c8 | 475 | ENET->TDAR = ENET_TDAR_TDAR_MASK; |
mbed_official | 33:9de8bd8ca1c8 | 476 | |
mbed_official | 33:9de8bd8ca1c8 | 477 | LINK_STATS_INC(link.xmit); |
mbed_official | 33:9de8bd8ca1c8 | 478 | |
mbed_official | 33:9de8bd8ca1c8 | 479 | /* Restore access */ |
mbed_official | 33:9de8bd8ca1c8 | 480 | sys_mutex_unlock(&k64f_enet->TXLockMutex); |
mbed_official | 33:9de8bd8ca1c8 | 481 | |
mbed_official | 33:9de8bd8ca1c8 | 482 | return ERR_OK; |
mbed_official | 33:9de8bd8ca1c8 | 483 | } |
mbed_official | 33:9de8bd8ca1c8 | 484 | |
mbed_official | 33:9de8bd8ca1c8 | 485 | /******************************************************************************* |
mbed_official | 33:9de8bd8ca1c8 | 486 | * PHY task: monitor link |
mbed_official | 33:9de8bd8ca1c8 | 487 | *******************************************************************************/ |
mbed_official | 33:9de8bd8ca1c8 | 488 | |
mbed_official | 33:9de8bd8ca1c8 | 489 | #define PHY_TASK_PERIOD_MS 200 |
mbed_official | 33:9de8bd8ca1c8 | 490 | #define STATE_UNKNOWN (-1) |
mbed_official | 33:9de8bd8ca1c8 | 491 | |
mbed_official | 33:9de8bd8ca1c8 | 492 | typedef struct { |
mbed_official | 33:9de8bd8ca1c8 | 493 | int connected; |
mbed_official | 33:9de8bd8ca1c8 | 494 | phy_speed_t speed; |
mbed_official | 33:9de8bd8ca1c8 | 495 | phy_duplex_t duplex; |
mbed_official | 33:9de8bd8ca1c8 | 496 | } PHY_STATE; |
mbed_official | 33:9de8bd8ca1c8 | 497 | |
mbed_official | 33:9de8bd8ca1c8 | 498 | int phy_link_status() { |
mbed_official | 33:9de8bd8ca1c8 | 499 | bool connection_status; |
mbed_official | 33:9de8bd8ca1c8 | 500 | uint32_t phyAddr = 0; |
mbed_official | 33:9de8bd8ca1c8 | 501 | |
mbed_official | 33:9de8bd8ca1c8 | 502 | PHY_GetLinkStatus(ENET, phyAddr, &connection_status); |
mbed_official | 33:9de8bd8ca1c8 | 503 | return (int)connection_status; |
mbed_official | 33:9de8bd8ca1c8 | 504 | } |
mbed_official | 33:9de8bd8ca1c8 | 505 | |
mbed_official | 33:9de8bd8ca1c8 | 506 | static void k64f_phy_task(void *data) { |
mbed_official | 33:9de8bd8ca1c8 | 507 | struct netif *netif = (struct netif*)data; |
mbed_official | 33:9de8bd8ca1c8 | 508 | bool connection_status; |
mbed_official | 33:9de8bd8ca1c8 | 509 | PHY_STATE crt_state = {STATE_UNKNOWN, (phy_speed_t)STATE_UNKNOWN, (phy_duplex_t)STATE_UNKNOWN}; |
mbed_official | 33:9de8bd8ca1c8 | 510 | PHY_STATE prev_state; |
mbed_official | 33:9de8bd8ca1c8 | 511 | uint32_t phyAddr = 0; |
mbed_official | 33:9de8bd8ca1c8 | 512 | uint32_t rcr = 0; |
mbed_official | 33:9de8bd8ca1c8 | 513 | |
mbed_official | 33:9de8bd8ca1c8 | 514 | prev_state = crt_state; |
mbed_official | 33:9de8bd8ca1c8 | 515 | while (true) { |
mbed_official | 33:9de8bd8ca1c8 | 516 | // Get current status |
mbed_official | 33:9de8bd8ca1c8 | 517 | PHY_GetLinkStatus(ENET, phyAddr, &connection_status); |
mbed_official | 33:9de8bd8ca1c8 | 518 | crt_state.connected = connection_status ? 1 : 0; |
mbed_official | 33:9de8bd8ca1c8 | 519 | // Get the actual PHY link speed |
mbed_official | 33:9de8bd8ca1c8 | 520 | PHY_GetLinkSpeedDuplex(ENET, phyAddr, &crt_state.speed, &crt_state.duplex); |
mbed_official | 33:9de8bd8ca1c8 | 521 | |
mbed_official | 33:9de8bd8ca1c8 | 522 | // Compare with previous state |
mbed_official | 33:9de8bd8ca1c8 | 523 | if (crt_state.connected != prev_state.connected) { |
mbed_official | 33:9de8bd8ca1c8 | 524 | if (crt_state.connected) |
mbed_official | 33:9de8bd8ca1c8 | 525 | tcpip_callback_with_block((tcpip_callback_fn)netif_set_link_up, (void*) netif, 1); |
mbed_official | 33:9de8bd8ca1c8 | 526 | else |
mbed_official | 33:9de8bd8ca1c8 | 527 | tcpip_callback_with_block((tcpip_callback_fn)netif_set_link_down, (void*) netif, 1); |
mbed_official | 33:9de8bd8ca1c8 | 528 | } |
mbed_official | 33:9de8bd8ca1c8 | 529 | |
mbed_official | 33:9de8bd8ca1c8 | 530 | if (crt_state.speed != prev_state.speed) { |
mbed_official | 33:9de8bd8ca1c8 | 531 | rcr = ENET->RCR; |
mbed_official | 33:9de8bd8ca1c8 | 532 | rcr &= ~ENET_RCR_RMII_10T_MASK; |
mbed_official | 33:9de8bd8ca1c8 | 533 | rcr |= ENET_RCR_RMII_10T(!crt_state.speed); |
mbed_official | 33:9de8bd8ca1c8 | 534 | ENET->RCR = rcr; |
mbed_official | 33:9de8bd8ca1c8 | 535 | } |
mbed_official | 33:9de8bd8ca1c8 | 536 | |
mbed_official | 33:9de8bd8ca1c8 | 537 | prev_state = crt_state; |
mbed_official | 33:9de8bd8ca1c8 | 538 | osDelay(PHY_TASK_PERIOD_MS); |
mbed_official | 33:9de8bd8ca1c8 | 539 | } |
mbed_official | 33:9de8bd8ca1c8 | 540 | } |
mbed_official | 33:9de8bd8ca1c8 | 541 | |
mbed_official | 33:9de8bd8ca1c8 | 542 | /** |
mbed_official | 33:9de8bd8ca1c8 | 543 | * Should be called at the beginning of the program to set up the |
mbed_official | 33:9de8bd8ca1c8 | 544 | * network interface. |
mbed_official | 33:9de8bd8ca1c8 | 545 | * |
mbed_official | 33:9de8bd8ca1c8 | 546 | * This function should be passed as a parameter to netif_add(). |
mbed_official | 33:9de8bd8ca1c8 | 547 | * |
mbed_official | 33:9de8bd8ca1c8 | 548 | * @param[in] netif the lwip network interface structure for this netif |
mbed_official | 33:9de8bd8ca1c8 | 549 | * @return ERR_OK if the loopif is initialized |
mbed_official | 33:9de8bd8ca1c8 | 550 | * ERR_MEM if private data couldn't be allocated |
mbed_official | 33:9de8bd8ca1c8 | 551 | * any other err_t on error |
mbed_official | 33:9de8bd8ca1c8 | 552 | */ |
mbed_official | 33:9de8bd8ca1c8 | 553 | err_t eth_arch_enetif_init(struct netif *netif) |
mbed_official | 33:9de8bd8ca1c8 | 554 | { |
mbed_official | 33:9de8bd8ca1c8 | 555 | err_t err; |
mbed_official | 33:9de8bd8ca1c8 | 556 | |
mbed_official | 33:9de8bd8ca1c8 | 557 | LWIP_ASSERT("netif != NULL", (netif != NULL)); |
mbed_official | 33:9de8bd8ca1c8 | 558 | |
mbed_official | 33:9de8bd8ca1c8 | 559 | k64f_enetdata.netif = netif; |
mbed_official | 33:9de8bd8ca1c8 | 560 | |
mbed_official | 33:9de8bd8ca1c8 | 561 | /* set MAC hardware address */ |
mbed_official | 33:9de8bd8ca1c8 | 562 | #if (MBED_MAC_ADDRESS_SUM != MBED_MAC_ADDR_INTERFACE) |
mbed_official | 33:9de8bd8ca1c8 | 563 | netif->hwaddr[0] = MBED_MAC_ADDR_0; |
mbed_official | 33:9de8bd8ca1c8 | 564 | netif->hwaddr[1] = MBED_MAC_ADDR_1; |
mbed_official | 33:9de8bd8ca1c8 | 565 | netif->hwaddr[2] = MBED_MAC_ADDR_2; |
mbed_official | 33:9de8bd8ca1c8 | 566 | netif->hwaddr[3] = MBED_MAC_ADDR_3; |
mbed_official | 33:9de8bd8ca1c8 | 567 | netif->hwaddr[4] = MBED_MAC_ADDR_4; |
mbed_official | 33:9de8bd8ca1c8 | 568 | netif->hwaddr[5] = MBED_MAC_ADDR_5; |
mbed_official | 33:9de8bd8ca1c8 | 569 | #else |
mbed_official | 33:9de8bd8ca1c8 | 570 | mbed_mac_address((char *)netif->hwaddr); |
mbed_official | 33:9de8bd8ca1c8 | 571 | #endif |
mbed_official | 33:9de8bd8ca1c8 | 572 | netif->hwaddr_len = ETHARP_HWADDR_LEN; |
mbed_official | 33:9de8bd8ca1c8 | 573 | |
mbed_official | 33:9de8bd8ca1c8 | 574 | /* maximum transfer unit */ |
mbed_official | 33:9de8bd8ca1c8 | 575 | netif->mtu = 1500; |
mbed_official | 33:9de8bd8ca1c8 | 576 | |
mbed_official | 33:9de8bd8ca1c8 | 577 | /* device capabilities */ |
mbed_official | 33:9de8bd8ca1c8 | 578 | // TODOETH: check if the flags are correct below |
mbed_official | 33:9de8bd8ca1c8 | 579 | netif->flags = NETIF_FLAG_BROADCAST | NETIF_FLAG_ETHARP | NETIF_FLAG_ETHERNET | NETIF_FLAG_IGMP; |
mbed_official | 33:9de8bd8ca1c8 | 580 | |
mbed_official | 33:9de8bd8ca1c8 | 581 | /* Initialize the hardware */ |
mbed_official | 33:9de8bd8ca1c8 | 582 | netif->state = &k64f_enetdata; |
mbed_official | 33:9de8bd8ca1c8 | 583 | err = low_level_init(netif); |
mbed_official | 33:9de8bd8ca1c8 | 584 | if (err != ERR_OK) |
mbed_official | 33:9de8bd8ca1c8 | 585 | return err; |
mbed_official | 33:9de8bd8ca1c8 | 586 | |
mbed_official | 33:9de8bd8ca1c8 | 587 | #if LWIP_NETIF_HOSTNAME |
mbed_official | 33:9de8bd8ca1c8 | 588 | /* Initialize interface hostname */ |
mbed_official | 33:9de8bd8ca1c8 | 589 | netif->hostname = "lwipk64f"; |
mbed_official | 33:9de8bd8ca1c8 | 590 | #endif /* LWIP_NETIF_HOSTNAME */ |
mbed_official | 33:9de8bd8ca1c8 | 591 | |
mbed_official | 33:9de8bd8ca1c8 | 592 | netif->name[0] = 'e'; |
mbed_official | 33:9de8bd8ca1c8 | 593 | netif->name[1] = 'n'; |
mbed_official | 33:9de8bd8ca1c8 | 594 | |
mbed_official | 33:9de8bd8ca1c8 | 595 | netif->output = k64f_etharp_output; |
mbed_official | 33:9de8bd8ca1c8 | 596 | netif->linkoutput = k64f_low_level_output; |
mbed_official | 33:9de8bd8ca1c8 | 597 | |
mbed_official | 33:9de8bd8ca1c8 | 598 | /* CMSIS-RTOS, start tasks */ |
mbed_official | 33:9de8bd8ca1c8 | 599 | #ifdef CMSIS_OS_RTX |
mbed_official | 33:9de8bd8ca1c8 | 600 | memset(k64f_enetdata.xTXDCountSem.data, 0, sizeof(k64f_enetdata.xTXDCountSem.data)); |
mbed_official | 33:9de8bd8ca1c8 | 601 | k64f_enetdata.xTXDCountSem.def.semaphore = k64f_enetdata.xTXDCountSem.data; |
mbed_official | 33:9de8bd8ca1c8 | 602 | #endif |
mbed_official | 33:9de8bd8ca1c8 | 603 | k64f_enetdata.xTXDCountSem.id = osSemaphoreCreate(&k64f_enetdata.xTXDCountSem.def, ENET_TX_RING_LEN); |
mbed_official | 33:9de8bd8ca1c8 | 604 | |
mbed_official | 33:9de8bd8ca1c8 | 605 | LWIP_ASSERT("xTXDCountSem creation error", (k64f_enetdata.xTXDCountSem.id != NULL)); |
mbed_official | 33:9de8bd8ca1c8 | 606 | |
mbed_official | 33:9de8bd8ca1c8 | 607 | err = sys_mutex_new(&k64f_enetdata.TXLockMutex); |
mbed_official | 33:9de8bd8ca1c8 | 608 | LWIP_ASSERT("TXLockMutex creation error", (err == ERR_OK)); |
mbed_official | 33:9de8bd8ca1c8 | 609 | |
mbed_official | 33:9de8bd8ca1c8 | 610 | /* Packet receive task */ |
mbed_official | 33:9de8bd8ca1c8 | 611 | err = sys_sem_new(&k64f_enetdata.RxReadySem, 0); |
mbed_official | 33:9de8bd8ca1c8 | 612 | LWIP_ASSERT("RxReadySem creation error", (err == ERR_OK)); |
mbed_official | 33:9de8bd8ca1c8 | 613 | sys_thread_new("receive_thread", packet_rx, netif->state, DEFAULT_THREAD_STACKSIZE, RX_PRIORITY); |
mbed_official | 33:9de8bd8ca1c8 | 614 | |
mbed_official | 33:9de8bd8ca1c8 | 615 | /* Transmit cleanup task */ |
mbed_official | 33:9de8bd8ca1c8 | 616 | err = sys_sem_new(&k64f_enetdata.TxCleanSem, 0); |
mbed_official | 33:9de8bd8ca1c8 | 617 | LWIP_ASSERT("TxCleanSem creation error", (err == ERR_OK)); |
mbed_official | 33:9de8bd8ca1c8 | 618 | sys_thread_new("txclean_thread", packet_tx, netif->state, DEFAULT_THREAD_STACKSIZE, TX_PRIORITY); |
mbed_official | 33:9de8bd8ca1c8 | 619 | |
mbed_official | 33:9de8bd8ca1c8 | 620 | /* PHY monitoring task */ |
mbed_official | 33:9de8bd8ca1c8 | 621 | sys_thread_new("phy_thread", k64f_phy_task, netif, DEFAULT_THREAD_STACKSIZE, PHY_PRIORITY); |
mbed_official | 33:9de8bd8ca1c8 | 622 | |
mbed_official | 33:9de8bd8ca1c8 | 623 | /* Allow the PHY task to detect the initial link state and set up the proper flags */ |
mbed_official | 33:9de8bd8ca1c8 | 624 | osDelay(10); |
mbed_official | 33:9de8bd8ca1c8 | 625 | |
mbed_official | 33:9de8bd8ca1c8 | 626 | return ERR_OK; |
mbed_official | 33:9de8bd8ca1c8 | 627 | } |
mbed_official | 33:9de8bd8ca1c8 | 628 | |
mbed_official | 33:9de8bd8ca1c8 | 629 | void eth_arch_enable_interrupts(void) { |
mbed_official | 33:9de8bd8ca1c8 | 630 | //NVIC_SetPriority(ENET_Receive_IRQn, 6U); |
mbed_official | 33:9de8bd8ca1c8 | 631 | //NVIC_SetPriority(ENET_Transmit_IRQn, 6U); |
mbed_official | 33:9de8bd8ca1c8 | 632 | } |
mbed_official | 33:9de8bd8ca1c8 | 633 | |
mbed_official | 33:9de8bd8ca1c8 | 634 | void eth_arch_disable_interrupts(void) { |
mbed_official | 33:9de8bd8ca1c8 | 635 | |
mbed_official | 33:9de8bd8ca1c8 | 636 | } |
mbed_official | 33:9de8bd8ca1c8 | 637 | |
mbed_official | 33:9de8bd8ca1c8 | 638 | /** |
mbed_official | 33:9de8bd8ca1c8 | 639 | * @} |
mbed_official | 33:9de8bd8ca1c8 | 640 | */ |
mbed_official | 33:9de8bd8ca1c8 | 641 | |
mbed_official | 33:9de8bd8ca1c8 | 642 | /* --------------------------------- End Of File ------------------------------ */ |
mbed_official | 33:9de8bd8ca1c8 | 643 |