diff options
| author | hathach <[email protected]> | 2013-09-16 16:38:46 +0700 |
|---|---|---|
| committer | hathach <[email protected]> | 2013-09-16 16:38:46 +0700 |
| commit | 1cd2d5cf369dbdb945b431d04a855df275befea7 (patch) | |
| tree | 621adba6bf8625962db15210a2d3257c61feea8d /vendor | |
| parent | ba3bd1da9efe555c2d787c3b15b42b397afd9df2 (diff) | |
able to build with newly added lwip folder
Diffstat (limited to 'vendor')
| -rw-r--r-- | vendor/lwip/lpclwip/arch/cc.h | 33 | ||||
| -rw-r--r-- | vendor/lwip/lpclwip/arch/lpc17xx_40xx_emac.c | 882 | ||||
| -rw-r--r-- | vendor/lwip/lpclwip/arch/lpc17xx_40xx_emac.h | 128 | ||||
| -rw-r--r-- | vendor/lwip/lpclwip/arch/lpc17xx_40xx_systick_arch.c | 142 | ||||
| -rw-r--r-- | vendor/lwip/lpclwip/arch/lpc18xx_43xx_emac.c | 965 | ||||
| -rw-r--r-- | vendor/lwip/lpclwip/arch/lpc18xx_43xx_emac.h | 139 | ||||
| -rw-r--r-- | vendor/lwip/lpclwip/arch/lpc18xx_43xx_mac_regs.h | 359 | ||||
| -rw-r--r-- | vendor/lwip/lpclwip/arch/lpc18xx_43xx_systick_arch.c | 173 | ||||
| -rw-r--r-- | vendor/lwip/lpclwip/arch/lpc_arch.h | 115 | ||||
| -rw-r--r-- | vendor/lwip/lpclwip/arch/lpc_debug.c | 101 | ||||
| -rw-r--r-- | vendor/lwip/lpclwip/arch/sys_arch_freertos.c | 9 | ||||
| -rw-r--r-- | vendor/lwip/lpclwip/lpc_phy.h | 151 | ||||
| -rw-r--r-- | vendor/lwip/lpclwip/lpc_phy_lan8720.c | 300 |
13 files changed, 1555 insertions, 1942 deletions
diff --git a/vendor/lwip/lpclwip/arch/cc.h b/vendor/lwip/lpclwip/arch/cc.h index 06e806660..3650e5105 100644 --- a/vendor/lwip/lpclwip/arch/cc.h +++ b/vendor/lwip/lpclwip/arch/cc.h @@ -33,11 +33,6 @@ #define __CC_H__ #include <stdint.h> -#include <stdio.h> - -/** @ingroup NET_LWIP_ARCH - * @{ - */ /* Types based on stdint.h */ typedef uint8_t u8_t; @@ -77,9 +72,7 @@ typedef uintptr_t mem_ptr_t; #define PACK_STRUCT_END #define PACK_STRUCT_FIELD(fld) fld // #define PACK_STRUCT_USE_INCLUDES - #define ALIGNEDX(x) _Pragma(#x) - #define ALIGNEDXX(x) ALIGNEDX(data_alignment=x) - #define ALIGNED(x) ALIGNEDXX(x) + #error NEEDS ALIGNED // FIXME TBD #else /* GCC tools (CodeSourcery) */ #define PACK_STRUCT_BEGIN @@ -87,40 +80,20 @@ typedef uintptr_t mem_ptr_t; #define PACK_STRUCT_END #define PACK_STRUCT_FIELD(fld) fld #define ALIGNED(n) __attribute__((aligned (n))) -// #define ALIGNED(n) __align(n) #endif /* Used with IP headers only */ #define LWIP_CHKSUM_ALGORITHM 1 -#ifdef LWIP_DEBUG -/** - * @brief Displays an error message on assertion - * @param msg : Error message to display - * @param line : Line number in file with error - * @param file : Filename with error - * @return Nothing - * @note This function will display an error message on an assertion - * to the debug output. - */ +#ifdef LWIP_DEBUG void assert_printf(char *msg, int line, char *file); /* Plaform specific diagnostic output */ #define LWIP_PLATFORM_DIAG(vars) printf vars #define LWIP_PLATFORM_ASSERT(flag) { assert_printf((flag), __LINE__, __FILE__); } #else - -/** - * @brief LWIP optimized assertion loop (no LWIP_DEBUG) - * @return DoesnNothing, function doesn't return - */ -void assert_loop(void); #define LWIP_PLATFORM_DIAG(msg) { ; } -#define LWIP_PLATFORM_ASSERT(flag) { assert_loop(); } +#define LWIP_PLATFORM_ASSERT(flag) { while (1); } #endif -/** - * @} - */ - #endif /* __CC_H__ */ diff --git a/vendor/lwip/lpclwip/arch/lpc17xx_40xx_emac.c b/vendor/lwip/lpclwip/arch/lpc17xx_40xx_emac.c deleted file mode 100644 index c8272c1a1..000000000 --- a/vendor/lwip/lpclwip/arch/lpc17xx_40xx_emac.c +++ /dev/null @@ -1,882 +0,0 @@ -/* - * @brief LPC17xx/40xx LWIP EMAC driver - * - * @note - * Copyright(C) NXP Semiconductors, 2012 - * All rights reserved. - * - * @par - * Software that is described herein is for illustrative purposes only - * which provides customers with programming information regarding the - * LPC products. This software is supplied "AS IS" without any warranties of - * any kind, and NXP Semiconductors and its licensor disclaim any and - * all warranties, express or implied, including all implied warranties of - * merchantability, fitness for a particular purpose and non-infringement of - * intellectual property rights. NXP Semiconductors assumes no responsibility - * or liability for the use of the software, conveys no license or rights under any - * patent, copyright, mask work right, or any other intellectual property rights in - * or to any products. NXP Semiconductors reserves the right to make changes - * in the software without notification. NXP Semiconductors also makes no - * representation or warranty that such application will be suitable for the - * specified use without further testing or modification. - * - * @par - * Permission to use, copy, modify, and distribute this software and its - * documentation is hereby granted, under NXP Semiconductors' and its - * licensor's relevant copyrights in the software, without fee, provided that it - * is used in conjunction with NXP Semiconductors microcontrollers. This - * copyright, permission, and disclaimer notice must appear in all copies of - * this code. - */ - -#include "lwip/opt.h" -#include "lwip/sys.h" -#include "lwip/def.h" -#include "lwip/mem.h" -#include "lwip/pbuf.h" -#include "lwip/stats.h" -#include "lwip/snmp.h" -#include "netif/etharp.h" -#include "netif/ppp_oe.h" - -#include "lpc_17xx40xx_emac_config.h" -#include "lpc17xx_40xx_emac.h" - -#include "chip.h" -#include "board.h" -#include "lpc_phy.h" - -#include <string.h> - -extern void msDelay(uint32_t ms); - -#if LPC_NUM_BUFF_TXDESCS < 2 -#error LPC_NUM_BUFF_TXDESCS must be at least 2 -#endif - -#if LPC_NUM_BUFF_RXDESCS < 3 -#error LPC_NUM_BUFF_RXDESCS must be at least 3 -#endif - -/** @ingroup NET_LWIP_LPC17XX40XX_EMAC_DRIVER - * @{ - */ - -/***************************************************************************** - * Private types/enumerations/variables - ****************************************************************************/ - -#if NO_SYS == 0 -/** - * @brief Driver transmit and receive thread priorities - * Thread priorities for receive thread and TX cleanup thread. Alter - * to prioritize receive or transmit bandwidth. In a heavily loaded - * system or with LWIP_DEBUG enabled, the priorities might be better - * the same. */ -#define tskRECPKT_PRIORITY (DEFAULT_THREAD_PRIO + 4) -#define tskTXCLEAN_PRIORITY (DEFAULT_THREAD_PRIO + 5) -// #define tskTXCLEAN_PRIORITY (TCPIP_THREAD_PRIO - 1) // FIXME -// #define tskRECPKT_PRIORITY (TCPIP_THREAD_PRIO - 1) // FIXME -#endif - -/** @brief Debug output formatter lock define - * When using FreeRTOS and with LWIP_DEBUG enabled, enabling this - * define will allow RX debug messages to not interleave with the - * TX messages (so they are actually readable). Not enabling this - * define when the system is under load will cause the output to - * be unreadable. There is a small tradeoff in performance for this - * so use it only for debug. */ -// #define LOCK_RX_THREAD - -#if NO_SYS == 0 -/** @brief Receive group interrupts - */ -#define RXINTGROUP (ENET_INT_RXOVERRUN | ENET_INT_RXERROR | ENET_INT_RXDONE) - -/** @brief Transmit group interrupts - */ -#define TXINTGROUP (ENET_INT_TXUNDERRUN | ENET_INT_TXERROR | ENET_INT_TXDONE) -#else -#define RXINTGROUP 0 -#define TXINTGROUP 0 -#endif - -/* LPC EMAC driver data structure */ -typedef struct { - /* prxs must be 8 byte aligned! */ - ENET_RXSTAT_T prxs[LPC_NUM_BUFF_RXDESCS]; /**< Pointer to RX statuses */ - ENET_RXDESC_T prxd[LPC_NUM_BUFF_RXDESCS]; /**< Pointer to RX descriptor list */ - ENET_TXSTAT_T ptxs[LPC_NUM_BUFF_TXDESCS]; /**< Pointer to TX statuses */ - ENET_TXDESC_T ptxd[LPC_NUM_BUFF_TXDESCS]; /**< Pointer to TX descriptor list */ - struct netif *pnetif; /**< Reference back to LWIP parent netif */ - - struct pbuf *rxb[LPC_NUM_BUFF_RXDESCS]; /**< RX pbuf pointer list, zero-copy mode */ - - u32_t rx_fill_desc_index; /**< RX descriptor next available index */ - volatile u32_t rx_free_descs; /**< Count of free RX descriptors */ - struct pbuf *txb[LPC_NUM_BUFF_TXDESCS]; /**< TX pbuf pointer list, zero-copy mode */ - - u32_t lpc_last_tx_idx; /**< TX last descriptor index, zero-copy mode */ -#if NO_SYS == 0 - sys_sem_t rx_sem; /**< RX receive thread wakeup semaphore */ - sys_sem_t tx_clean_sem; /**< TX cleanup thread wakeup semaphore */ - sys_mutex_t tx_lock_mutex; /**< TX critical section mutex */ - sys_mutex_t rx_lock_mutex; /**< RX critical section mutex */ - xSemaphoreHandle xtx_count_sem; /**< TX free buffer counting semaphore */ -#endif -} lpc_enetdata_t; - -/** \brief LPC EMAC driver work data - */ -ALIGNED(8) lpc_enetdata_t lpc_enetdata; - -/***************************************************************************** - * Public types/enumerations/variables - ****************************************************************************/ - -/***************************************************************************** - * Private functions - ****************************************************************************/ - -/* Queues a pbuf into the RX descriptor list */ -STATIC void lpc_rxqueue_pbuf(lpc_enetdata_t *lpc_enetif, struct pbuf *p) -{ - u32_t idx; - - /* Get next free descriptor index */ - idx = lpc_enetif->rx_fill_desc_index; - - /* Setup descriptor and clear statuses */ - lpc_enetif->prxd[idx].Control = ENET_RCTRL_INT | ((u32_t) ENET_RCTRL_SIZE(p->len)); - lpc_enetif->prxd[idx].Packet = (u32_t) p->payload; - lpc_enetif->prxs[idx].StatusInfo = 0xFFFFFFFF; - lpc_enetif->prxs[idx].StatusHashCRC = 0xFFFFFFFF; - - /* Save pbuf pointer for push to network layer later */ - lpc_enetif->rxb[idx] = p; - - /* Wrap at end of descriptor list */ - idx++; - if (idx >= LPC_NUM_BUFF_RXDESCS) { - idx = 0; - } - - /* Queue descriptor(s) */ - lpc_enetif->rx_free_descs -= 1; - lpc_enetif->rx_fill_desc_index = idx; - - LWIP_DEBUGF(EMAC_DEBUG | LWIP_DBG_TRACE, - ("lpc_rxqueue_pbuf: pbuf packet queued: %p (free desc=%d)\n", p, - lpc_enetif->rx_free_descs)); -} - -/* Sets up the RX descriptor ring buffers. */ -STATIC err_t lpc_rx_setup(lpc_enetdata_t *lpc_enetif) -{ - /* Setup pointers to RX structures */ - Chip_ENET_InitRxDescriptors(LPC_ETHERNET, lpc_enetif->prxd, lpc_enetif->prxs, LPC_NUM_BUFF_RXDESCS); - - lpc_enetif->rx_free_descs = LPC_NUM_BUFF_RXDESCS; - lpc_enetif->rx_fill_desc_index = 0; - - /* Build RX buffer and descriptors */ - lpc_rx_queue(lpc_enetif->pnetif); - - return ERR_OK; -} - -/* Allocates a pbuf and returns the data from the incoming packet */ -STATIC struct pbuf *lpc_low_level_input(struct netif *netif) { - lpc_enetdata_t *lpc_enetif = netif->state; - struct pbuf *p = NULL; - u32_t idx, length; - -#ifdef LOCK_RX_THREAD -#if NO_SYS == 0 - /* Get exclusive access */ - sys_mutex_lock(&lpc_enetif->rx_lock_mutex); -#endif -#endif - - /* Monitor RX overrun status. This should never happen unless - (possibly) the internal bus is behing held up by something. - Unless your system is running at a very low clock speed or - there are possibilities that the internal buses may be held - up for a long time, this can probably safely be removed. */ - if (Chip_ENET_GetIntStatus(LPC_ETHERNET) & ENET_INT_RXOVERRUN) { - LINK_STATS_INC(link.err); - LINK_STATS_INC(link.drop); - - /* Temporarily disable RX */ - Chip_ENET_RXDisable(LPC_ETHERNET); - - /* Reset the RX side */ - Chip_ENET_ResetRXLogic(LPC_ETHERNET); - Chip_ENET_ClearIntStatus(LPC_ETHERNET, ENET_INT_RXOVERRUN); - - /* De-allocate all queued RX pbufs */ - for (idx = 0; idx < LPC_NUM_BUFF_RXDESCS; idx++) { - if (lpc_enetif->rxb[idx] != NULL) { - pbuf_free(lpc_enetif->rxb[idx]); - lpc_enetif->rxb[idx] = NULL; - } - } - - /* Start RX side again */ - lpc_rx_setup(lpc_enetif); - - /* Re-enable RX */ - Chip_ENET_RXEnable(LPC_ETHERNET); - -#ifdef LOCK_RX_THREAD -#if NO_SYS == 0 - sys_mutex_unlock(&lpc_enetif->rx_lock_mutex); -#endif -#endif - - return NULL; - } - - /* Determine if a frame has been received */ - length = 0; - idx = Chip_ENET_GetRXConsumeIndex(LPC_ETHERNET); - if (!Chip_ENET_IsRxEmpty(LPC_ETHERNET)) { - /* Handle errors */ - if (lpc_enetif->prxs[idx].StatusInfo & (ENET_RINFO_CRC_ERR | - ENET_RINFO_SYM_ERR | ENET_RINFO_ALIGN_ERR | ENET_RINFO_LEN_ERR)) { -#if LINK_STATS - if (lpc_enetif->prxs[idx].StatusInfo & (ENET_RINFO_CRC_ERR | - ENET_RINFO_SYM_ERR | ENET_RINFO_ALIGN_ERR)) { - LINK_STATS_INC(link.chkerr); - } - if (lpc_enetif->prxs[idx].StatusInfo & ENET_RINFO_LEN_ERR) { - LINK_STATS_INC(link.lenerr); - } -#endif - - /* Drop the frame */ - LINK_STATS_INC(link.drop); - - /* Re-queue the pbuf for receive */ - lpc_enetif->rx_free_descs++; - p = lpc_enetif->rxb[idx]; - lpc_enetif->rxb[idx] = NULL; - lpc_rxqueue_pbuf(lpc_enetif, p); - - LWIP_DEBUGF(EMAC_DEBUG | LWIP_DBG_TRACE, - ("lpc_low_level_input: Packet dropped with errors (0x%x)\n", - lpc_enetif->prxs[idx].StatusInfo)); - - p = NULL; - } - else { - /* A packet is waiting, get length */ - length = ENET_RINFO_SIZE(lpc_enetif->prxs[idx].StatusInfo) - 4; /* Remove FCS */ - - /* Zero-copy */ - p = lpc_enetif->rxb[idx]; - p->len = (u16_t) length; - - /* Free pbuf from desriptor */ - lpc_enetif->rxb[idx] = NULL; - lpc_enetif->rx_free_descs++; - - /* Queue new buffer(s) */ - if (lpc_rx_queue(lpc_enetif->pnetif) == 0) { - - /* Re-queue the pbuf for receive */ - lpc_rxqueue_pbuf(lpc_enetif, p); - - /* Drop the frame */ - LINK_STATS_INC(link.drop); - - LWIP_DEBUGF(EMAC_DEBUG | LWIP_DBG_TRACE, - ("lpc_low_level_input: Packet dropped since it could not allocate Rx Buffer\n")); - - p = NULL; - } - else { - - LWIP_DEBUGF(EMAC_DEBUG | LWIP_DBG_TRACE, - ("lpc_low_level_input: Packet received: %p, size %d (index=%d)\n", - p, length, idx)); - - /* Save size */ - p->tot_len = (u16_t) length; - LINK_STATS_INC(link.recv); - } - } - - /* Update Consume index */ - Chip_ENET_IncRXConsumeIndex(LPC_ETHERNET); - } - -#ifdef LOCK_RX_THREAD -#if NO_SYS == 0 - sys_mutex_unlock(&lpc_enetif->rx_lock_mutex); -#endif -#endif - - return p; -} - -/* Determine if the passed address is usable for the ethernet DMA controller */ -STATIC s32_t lpc_packet_addr_notsafe(void *addr) { -#if defined(CHIP_LPC175X_6X) - /* Check for legal address ranges */ - if ((((u32_t) addr >= 0x10000000) && ((u32_t) addr < 0x10008000)) /* 32kB local SRAM */ - || (((u32_t) addr >= 0x1FFF0000) && ((u32_t) addr < 0x1FFF2000)) /* 8kB ROM */ - || (((u32_t) addr >= 0x2007C000) && ((u32_t) addr < 0x20084000)) /* 32kB AHB SRAM */ - ) { - return 0; - } - return 1; -#else - /* Check for legal address ranges */ - if ((((u32_t) addr >= 0x20000000) && ((u32_t) addr < 0x20008000)) || - (((u32_t) addr >= 0x80000000) && ((u32_t) addr < 0xF0000000))) { - return 0; - } - return 1; -#endif -} - -/* Sets up the TX descriptor ring buffers */ -STATIC err_t lpc_tx_setup(lpc_enetdata_t *lpc_enetif) -{ - s32_t idx; - - /* Build TX descriptors for local buffers */ - for (idx = 0; idx < LPC_NUM_BUFF_TXDESCS; idx++) { - lpc_enetif->ptxd[idx].Control = 0; - lpc_enetif->ptxs[idx].StatusInfo = 0xFFFFFFFF; - } - - /* Setup pointers to TX structures */ - Chip_ENET_InitTxDescriptors(LPC_ETHERNET, lpc_enetif->ptxd, lpc_enetif->ptxs, LPC_NUM_BUFF_TXDESCS); - - lpc_enetif->lpc_last_tx_idx = 0; - - return ERR_OK; -} - -/* Free TX buffers that are complete */ -STATIC void lpc_tx_reclaim_st(lpc_enetdata_t *lpc_enetif, u32_t cidx) -{ -#if NO_SYS == 0 - /* Get exclusive access */ - sys_mutex_lock(&lpc_enetif->tx_lock_mutex); -#endif - - while (cidx != lpc_enetif->lpc_last_tx_idx) { - if (lpc_enetif->txb[lpc_enetif->lpc_last_tx_idx] != NULL) { - LWIP_DEBUGF(EMAC_DEBUG | LWIP_DBG_TRACE, - ("lpc_tx_reclaim_st: Freeing packet %p (index %d)\n", - lpc_enetif->txb[lpc_enetif->lpc_last_tx_idx], - lpc_enetif->lpc_last_tx_idx)); - pbuf_free(lpc_enetif->txb[lpc_enetif->lpc_last_tx_idx]); - lpc_enetif->txb[lpc_enetif->lpc_last_tx_idx] = NULL; - } - -#if NO_SYS == 0 - xSemaphoreGive(lpc_enetif->xtx_count_sem); -#endif - lpc_enetif->lpc_last_tx_idx++; - if (lpc_enetif->lpc_last_tx_idx >= LPC_NUM_BUFF_TXDESCS) { - lpc_enetif->lpc_last_tx_idx = 0; - } - } - -#if NO_SYS == 0 - /* Restore access */ - sys_mutex_unlock(&lpc_enetif->tx_lock_mutex); -#endif -} - -/* Low level output of a packet. Never call this from an interrupt context, - * as it may block until TX descriptors become available. */ -STATIC err_t lpc_low_level_output(struct netif *netif, struct pbuf *p) -{ - lpc_enetdata_t *lpc_enetif = netif->state; - struct pbuf *q; - -#if LPC_TX_PBUF_BOUNCE_EN == 1 - u8_t *dst; - struct pbuf *np; -#endif - u32_t idx; - u32_t dn, notdmasafe = 0; - - /* Zero-copy TX buffers may be fragmented across mutliple payload - chains. Determine the number of descriptors needed for the - transfer. The pbuf chaining can be a mess! */ - dn = (u32_t) pbuf_clen(p); - - /* Test to make sure packet addresses are DMA safe. A DMA safe - address is once that uses external memory or periphheral RAM. - IRAM and FLASH are not safe! */ - for (q = p; q != NULL; q = q->next) { - notdmasafe += lpc_packet_addr_notsafe(q->payload); - } - -#if LPC_TX_PBUF_BOUNCE_EN == 1 - /* If the pbuf is not DMA safe, a new bounce buffer (pbuf) will be - created that will be used instead. This requires an copy from the - non-safe DMA region to the new pbuf */ - if (notdmasafe) { - /* Allocate a pbuf in DMA memory */ - np = pbuf_alloc(PBUF_RAW, p->tot_len, PBUF_RAM); - if (np == NULL) { - LWIP_DEBUGF(EMAC_DEBUG | LWIP_DBG_TRACE, - ("lpc_low_level_output: could not allocate TX pbuf\n")); - return ERR_MEM; - } - - /* This buffer better be contiguous! */ - LWIP_ASSERT("lpc_low_level_output: New transmit pbuf is chained", - (pbuf_clen(np) == 1)); - - /* Copy to DMA safe pbuf */ - dst = (u8_t *) np->payload; - for (q = p; q != NULL; q = q->next) { - /* Copy the buffer to the descriptor's buffer */ - MEMCPY(dst, (u8_t *) q->payload, q->len); - dst += q->len; - } - np->len = p->tot_len; - - LWIP_DEBUGF(EMAC_DEBUG | LWIP_DBG_TRACE, - ("lpc_low_level_output: Switched to DMA safe buffer, old=%p, new=%p\n", - q, np)); - - /* use the new buffer for descrptor queueing. The original pbuf will - be de-allocated outsuide this driver. */ - p = np; - dn = 1; - } -#else - if (notdmasafe) { - LWIP_ASSERT("lpc_low_level_output: Not a DMA safe pbuf", - (notdmasafe == 0)); - } -#endif - - /* Wait until enough descriptors are available for the transfer. */ - /* THIS WILL BLOCK UNTIL THERE ARE ENOUGH DESCRIPTORS AVAILABLE */ - while (dn > lpc_tx_ready(netif)) { -#if NO_SYS == 0 - xSemaphoreTake(lpc_enetif->xtx_count_sem, 0); -#else - msDelay(1); -#endif - } - - /* Get free TX buffer index */ - idx = Chip_ENET_GetTXProduceIndex(LPC_ETHERNET); - -#if NO_SYS == 0 - /* Get exclusive access */ - sys_mutex_lock(&lpc_enetif->tx_lock_mutex); -#endif - - /* Prevent LWIP from de-allocating this pbuf. The driver will - free it once it's been transmitted. */ - if (!notdmasafe) { - pbuf_ref(p); - } - - /* Setup transfers */ - q = p; - while (dn > 0) { - dn--; - - /* Only save pointer to free on last descriptor */ - if (dn == 0) { - /* Save size of packet and signal it's ready */ - lpc_enetif->ptxd[idx].Control = ENET_TCTRL_SIZE(q->len) | ENET_TCTRL_INT | - ENET_TCTRL_LAST; - lpc_enetif->txb[idx] = p; - } - else { - /* Save size of packet, descriptor is not last */ - lpc_enetif->ptxd[idx].Control = ENET_TCTRL_SIZE(q->len) | ENET_TCTRL_INT; - lpc_enetif->txb[idx] = NULL; - } - - LWIP_DEBUGF(EMAC_DEBUG | LWIP_DBG_TRACE, - ("lpc_low_level_output: pbuf packet(%p) sent, chain#=%d," - " size = %d (index=%d)\n", q->payload, dn, q->len, idx)); - - lpc_enetif->ptxd[idx].Packet = (u32_t) q->payload; - - q = q->next; - - idx = Chip_ENET_IncTXProduceIndex(LPC_ETHERNET); - } - - LINK_STATS_INC(link.xmit); - -#if NO_SYS == 0 - /* Restore access */ - sys_mutex_unlock(&lpc_enetif->tx_lock_mutex); -#endif - - return ERR_OK; -} - -#if NO_SYS == 0 -/* Packet reception task for FreeRTOS */ -STATIC portTASK_FUNCTION(vPacketReceiveTask, pvParameters) -{ - lpc_enetdata_t *lpc_enetif = pvParameters; - - while (1) { - /* Wait for receive task to wakeup */ - sys_arch_sem_wait(&lpc_enetif->rx_sem, 0); - - /* Process packets until all empty */ - while (!Chip_ENET_IsRxEmpty(LPC_ETHERNET)) { - lpc_enetif_input(lpc_enetif->pnetif); - } - } -} - -/* Transmit cleanup task for FreeRTOS */ -STATIC portTASK_FUNCTION(vTransmitCleanupTask, pvParameters) -{ - lpc_enetdata_t *lpc_enetif = pvParameters; - s32_t idx; - - while (1) { - /* Wait for transmit cleanup task to wakeup */ - sys_arch_sem_wait(&lpc_enetif->tx_clean_sem, 0); - - /* Error handling for TX underruns. This should never happen unless - something is holding the bus or the clocks are going too slow. It - can probably be safely removed. */ - if (Chip_ENET_GetIntStatus(LPC_ETHERNET) & ENET_INT_TXUNDERRUN) { - LINK_STATS_INC(link.err); - LINK_STATS_INC(link.drop); - -#if NO_SYS == 0 - /* Get exclusive access */ - sys_mutex_lock(&lpc_enetif->tx_lock_mutex); -#endif - /* Reset the TX side */ - Chip_ENET_ResetTXLogic(LPC_ETHERNET); - Chip_ENET_ClearIntStatus(LPC_ETHERNET, ENET_INT_TXUNDERRUN); - - /* De-allocate all queued TX pbufs */ - for (idx = 0; idx < LPC_NUM_BUFF_TXDESCS; idx++) { - if (lpc_enetif->txb[idx] != NULL) { - pbuf_free(lpc_enetif->txb[idx]); - lpc_enetif->txb[idx] = NULL; - } - } - -#if NO_SYS == 0 - /* Restore access */ - sys_mutex_unlock(&lpc_enetif->tx_lock_mutex); -#endif - /* Start TX side again */ - lpc_tx_setup(lpc_enetif); - } - else { - /* Free TX buffers that are done sending */ - lpc_tx_reclaim(lpc_enetdata.pnetif); - } - } -} - -#endif - -/* Low level init of the MAC and PHY */ -STATIC err_t low_level_init(struct netif *netif) -{ - lpc_enetdata_t *lpc_enetif = netif->state; - err_t err = ERR_OK; - - Chip_ENET_Init(LPC_ETHERNET); - - /* Initialize the PHY */ - Chip_ENET_SetupMII(LPC_ETHERNET, Chip_ENET_FindMIIDiv(LPC_ETHERNET, 2500000), LPC_PHYDEF_PHYADDR); -#if defined(USE_RMII) - if (lpc_phy_init(true, msDelay) != SUCCESS) { - return ERROR; - } -#else - if (lpc_phy_init(false, msDelay) != SUCCESS) { - return ERROR; - } -#endif - - /* Save station address */ - Chip_ENET_SetADDR(LPC_ETHERNET, netif->hwaddr); - - /* Setup transmit and receive descriptors */ - if (lpc_tx_setup(lpc_enetif) != ERR_OK) { - return ERR_BUF; - } - if (lpc_rx_setup(lpc_enetif) != ERR_OK) { - return ERR_BUF; - } - - /* Enable packet reception */ -#if IP_SOF_BROADCAST_RECV - Chip_ENET_EnableRXFilter(LPC_ETHERNET, ENET_RXFILTERCTRL_APE | ENET_RXFILTERCTRL_ABE); -#else - Chip_ENET_EnableRXFilter(ENET_RXFILTERCTRL_APE); -#endif - - /* Clear and enable rx/tx interrupts */ - Chip_ENET_EnableInt(LPC_ETHERNET, RXINTGROUP | TXINTGROUP); - - /* Enable RX and TX */ - Chip_ENET_TXEnable(LPC_ETHERNET); - Chip_ENET_RXEnable(LPC_ETHERNET); - - return err; -} - -/* This function is the ethernet packet send function. It calls - * etharp_output after checking link status. */ -STATIC err_t lpc_etharp_output(struct netif *netif, struct pbuf *q, - ip_addr_t *ipaddr) -{ - /* Only send packet is link is up */ - if (netif->flags & NETIF_FLAG_LINK_UP) { - return etharp_output(netif, q, ipaddr); - } - - return ERR_CONN; -} - -/***************************************************************************** - * Public functions - ****************************************************************************/ -/* Attempt to allocate and requeue a new pbuf for RX */ -s32_t lpc_rx_queue(struct netif *netif) -{ - lpc_enetdata_t *lpc_enetif = netif->state; - struct pbuf *p; - - s32_t queued = 0; - - /* Attempt to requeue as many packets as possible */ - while (lpc_enetif->rx_free_descs > 0) { - /* Allocate a pbuf from the pool. We need to allocate at the - maximum size as we don't know the size of the yet to be - received packet. */ - p = pbuf_alloc(PBUF_RAW, (u16_t) ENET_ETH_MAX_FLEN, PBUF_RAM); - if (p == NULL) { - LWIP_DEBUGF(EMAC_DEBUG | LWIP_DBG_TRACE, - ("lpc_rx_queue: could not allocate RX pbuf (free desc=%d)\n", - lpc_enetif->rx_free_descs)); - return queued; - } - - /* pbufs allocated from the RAM pool should be non-chained. */ - LWIP_ASSERT("lpc_rx_queue: pbuf is not contiguous (chained)", - pbuf_clen(p) <= 1); - - /* Queue packet */ - lpc_rxqueue_pbuf(lpc_enetif, p); - - /* Update queued count */ - queued++; - } - - return queued; -} - -/* Attempt to read a packet from the EMAC interface */ -void lpc_enetif_input(struct netif *netif) -{ - struct eth_hdr *ethhdr; - - struct pbuf *p; - - /* move received packet into a new pbuf */ - p = lpc_low_level_input(netif); - if (p == NULL) { - return; - } - - /* points to packet payload, which starts with an Ethernet header */ - ethhdr = p->payload; - - switch (htons(ethhdr->type)) { - case ETHTYPE_IP: - case ETHTYPE_ARP: -#if PPPOE_SUPPORT - case ETHTYPE_PPPOEDISC: - case ETHTYPE_PPPOE: -#endif /* PPPOE_SUPPORT */ - /* full packet send to tcpip_thread to process */ - if (netif->input(p, netif) != ERR_OK) { - LWIP_DEBUGF(NETIF_DEBUG, ("lpc_enetif_input: IP input error\n")); - /* Free buffer */ - pbuf_free(p); - } - break; - - default: - /* Return buffer */ - pbuf_free(p); - break; - } -} - -/* Call for freeing TX buffers that are complete */ -void lpc_tx_reclaim(struct netif *netif) -{ - lpc_tx_reclaim_st((lpc_enetdata_t *) netif->state, - Chip_ENET_GetTXConsumeIndex(LPC_ETHERNET)); -} - -/* Polls if an available TX descriptor is ready */ -s32_t lpc_tx_ready(struct netif *netif) -{ - u32_t pidx, cidx; - - cidx = Chip_ENET_GetTXConsumeIndex(LPC_ETHERNET); - pidx = Chip_ENET_GetTXProduceIndex(LPC_ETHERNET); - - return Chip_ENET_GetFreeDescNum(LPC_ETHERNET, pidx, cidx, LPC_NUM_BUFF_TXDESCS); -} - -/** - * @brief EMAC interrupt handler - * @return Nothing - * @note This function handles the transmit, receive, and error interrupt of - * the LPC17xx/40xx. This is meant to be used when NO_SYS=0. - */ -void ETH_IRQHandler(void) -{ -#if NO_SYS == 1 - /* Interrupts are not used without an RTOS */ - NVIC_DisableIRQ(ETHERNET_IRQn); -#else - signed portBASE_TYPE xRecTaskWoken = pdFALSE, XTXTaskWoken = pdFALSE; - uint32_t ints; - - /* Interrupts are of 2 groups - transmit or receive. Based on the - interrupt, kick off the receive or transmit (cleanup) task */ - - /* Get pending interrupts */ - ints = Chip_ENET_GetIntStatus(LPC_ETHERNET); - - if (ints & RXINTGROUP) { - /* RX group interrupt(s) */ - /* Give semaphore to wakeup RX receive task. Note the FreeRTOS - method is used instead of the LWIP arch method. */ - xSemaphoreGiveFromISR(lpc_enetdata.rx_sem, &xRecTaskWoken); - } - - if (ints & TXINTGROUP) { - /* TX group interrupt(s) */ - /* Give semaphore to wakeup TX cleanup task. Note the FreeRTOS - method is used instead of the LWIP arch method. */ - xSemaphoreGiveFromISR(lpc_enetdata.tx_clean_sem, &XTXTaskWoken); - } - - /* Clear pending interrupts */ - Chip_ENET_ClearIntStatus(LPC_ETHERNET, ints); - - /* Context switch needed? */ - portEND_SWITCHING_ISR(xRecTaskWoken || XTXTaskWoken); -#endif -} - -/* Set up the MAC interface duplex */ -void lpc_emac_set_duplex(int full_duplex) -{ - if (full_duplex) { - Chip_ENET_SetFullDuplex(LPC_ETHERNET); - } - else { - Chip_ENET_SetHalfDuplex(LPC_ETHERNET); - } -} - -/* Set up the MAC interface speed */ -void lpc_emac_set_speed(int mbs_100) -{ - if (mbs_100) { - Chip_ENET_Set100Mbps(LPC_ETHERNET); - } - else { - Chip_ENET_Set10Mbps(LPC_ETHERNET); - } -} - -/* LWIP 17xx/40xx EMAC initialization function */ -err_t lpc_enetif_init(struct netif *netif) -{ - err_t err; - - LWIP_ASSERT("netif != NULL", (netif != NULL)); - - lpc_enetdata.pnetif = netif; - - /* set MAC hardware address */ - Board_ENET_GetMacADDR(netif->hwaddr); - netif->hwaddr_len = ETHARP_HWADDR_LEN; - - /* maximum transfer unit */ - netif->mtu = 1500; - - /* device capabilities */ - netif->flags = NETIF_FLAG_BROADCAST | NETIF_FLAG_ETHARP | NETIF_FLAG_UP | - NETIF_FLAG_ETHERNET; - - /* Initialize the hardware */ - netif->state = &lpc_enetdata; - err = low_level_init(netif); - if (err != ERR_OK) { - return err; - } - -#if LWIP_NETIF_HOSTNAME - /* Initialize interface hostname */ - netif->hostname = "lwiplpc"; -#endif /* LWIP_NETIF_HOSTNAME */ - - netif->name[0] = 'e'; - netif->name[1] = 'n'; - - netif->output = lpc_etharp_output; - netif->linkoutput = lpc_low_level_output; - - /* For FreeRTOS, start tasks */ -#if NO_SYS == 0 - lpc_enetdata.xtx_count_sem = xSemaphoreCreateCounting(LPC_NUM_BUFF_TXDESCS, - LPC_NUM_BUFF_TXDESCS); - LWIP_ASSERT("xtx_count_sem creation error", - (lpc_enetdata.xtx_count_sem != NULL)); - - err = sys_mutex_new(&lpc_enetdata.tx_lock_mutex); - LWIP_ASSERT("tx_lock_mutex creation error", (err == ERR_OK)); - - err = sys_mutex_new(&lpc_enetdata.rx_lock_mutex); - LWIP_ASSERT("rx_lock_mutex creation error", (err == ERR_OK)); - - /* Packet receive task */ - err = sys_sem_new(&lpc_enetdata.rx_sem, 0); - LWIP_ASSERT("rx_sem creation error", (err == ERR_OK)); - sys_thread_new("receive_thread", vPacketReceiveTask, netif->state, - DEFAULT_THREAD_STACKSIZE, tskRECPKT_PRIORITY); - - /* Transmit cleanup task */ - err = sys_sem_new(&lpc_enetdata.tx_clean_sem, 0); - LWIP_ASSERT("tx_clean_sem creation error", (err == ERR_OK)); - sys_thread_new("txclean_thread", vTransmitCleanupTask, netif->state, - DEFAULT_THREAD_STACKSIZE, tskTXCLEAN_PRIORITY); -#endif - - return ERR_OK; -} - -/** - * @} - */ diff --git a/vendor/lwip/lpclwip/arch/lpc17xx_40xx_emac.h b/vendor/lwip/lpclwip/arch/lpc17xx_40xx_emac.h deleted file mode 100644 index 9c615d307..000000000 --- a/vendor/lwip/lpclwip/arch/lpc17xx_40xx_emac.h +++ /dev/null @@ -1,128 +0,0 @@ -/* - * @brief LPC17xx/40xx LWIP EMAC driver - * - * @note - * Copyright(C) NXP Semiconductors, 2012 - * All rights reserved. - * - * @par - * Software that is described herein is for illustrative purposes only - * which provides customers with programming information regarding the - * LPC products. This software is supplied "AS IS" without any warranties of - * any kind, and NXP Semiconductors and its licensor disclaim any and - * all warranties, express or implied, including all implied warranties of - * merchantability, fitness for a particular purpose and non-infringement of - * intellectual property rights. NXP Semiconductors assumes no responsibility - * or liability for the use of the software, conveys no license or rights under any - * patent, copyright, mask work right, or any other intellectual property rights in - * or to any products. NXP Semiconductors reserves the right to make changes - * in the software without notification. NXP Semiconductors also makes no - * representation or warranty that such application will be suitable for the - * specified use without further testing or modification. - * - * @par - * Permission to use, copy, modify, and distribute this software and its - * documentation is hereby granted, under NXP Semiconductors' and its - * licensor's relevant copyrights in the software, without fee, provided that it - * is used in conjunction with NXP Semiconductors microcontrollers. This - * copyright, permission, and disclaimer notice must appear in all copies of - * this code. - */ - -#ifndef __LPC17XX_40XX_EMAC_H_ -#define __LPC17XX_40XX_EMAC_H_ - -#include "lwip/opt.h" -#include "lwip/netif.h" - -#ifdef __cplusplus -extern "C" -{ -#endif - -/** @defgroup NET_LWIP_LPC17XX40XX_EMAC_DRIVER 17xx/40xx EMAC driver for LWIP - * @ingroup NET_LWIP - * @note This is the LPC17xx/40xx EMAC driver for LWIP. This driver supports both - * RTOS-based and no-RTOS operation with LWIP. WHen using an RTOS, several - * threads will be created for handling RX and TX packet fucntions. - * - * Note that some LWIP examples may not necessarily use all the provided - * LWIP driver functions or may contain overriden versions of the functions. - * (For example, PHY drives may have their own implementation of the MII - * read/write functions). - * @{ - */ - -/** - * @brief Attempt to read a packet from the EMAC interface - * @param netif : lwip network interface structure pointer - * @return Nothing - */ -void lpc_enetif_input(struct netif *netif); - -/** - * @brief Attempt to allocate and requeue a new pbuf for RX - * @param netif : lwip network interface structure pointer - * @return The number of new descriptors queued - */ -s32_t lpc_rx_queue(struct netif *netif); - -/** - * @brief Polls if an available TX descriptor is ready - * @param netif : lwip network interface structure pointer - * @return 0 if no descriptors are read, or >0 - * @note Can be used to determine if the low level transmit function will block - */ -s32_t lpc_tx_ready(struct netif *netif); - -/** - * @brief Call for freeing TX buffers that are complete - * @param netif : lwip network interface structure pointer - * @return Nothing - */ -void lpc_tx_reclaim(struct netif *netif); - -/** - * @brief LWIP 17xx/40xx EMAC initialization function - * @param netif : lwip network interface structure pointer - * @return ERR_OK if the loopif is initialized, or ERR_* on other errors - * @note Should be called at the beginning of the program to set up the - * network interface. This function should be passed as a parameter to - * netif_add(). - */ -err_t lpc_enetif_init(struct netif *netif); - -/** - * @brief Set up the MAC interface duplex - * @param full_duplex : 0 = half duplex, 1 = full duplex - * @return Nothing - * @note This function provides a method for the PHY to setup the EMAC - * for the PHY negotiated duplex mode. - */ -void lpc_emac_set_duplex(int full_duplex); - -/** - * @brief Set up the MAC interface speed - * @param mbs_100 : 0 = 10mbs mode, 1 = 100mbs mode - * @return Nothing - * @note This function provides a method for the PHY to setup the EMAC - * for the PHY negotiated bit rate. - */ -void lpc_emac_set_speed(int mbs_100); - -/** - * @brief Millisecond Delay function - * @param ms : Milliseconds to wait - * @return None - */ -extern void msDelay(uint32_t ms); - -#ifdef __cplusplus -} -#endif - -/** - * @} - */ - -#endif /* __LPC17XX_40XX_EMAC_H_ */ diff --git a/vendor/lwip/lpclwip/arch/lpc17xx_40xx_systick_arch.c b/vendor/lwip/lpclwip/arch/lpc17xx_40xx_systick_arch.c deleted file mode 100644 index ebe8514e4..000000000 --- a/vendor/lwip/lpclwip/arch/lpc17xx_40xx_systick_arch.c +++ /dev/null @@ -1,142 +0,0 @@ -/********************************************************************** - * @brief Setups up the LWIP timebase (tick) - * - * @note - * Copyright(C) NXP Semiconductors, 2012 - * All rights reserved. - * - * @par - * Software that is described herein is for illustrative purposes only - * which provides customers with programming information regarding the - * LPC products. This software is supplied "AS IS" without any warranties of - * any kind, and NXP Semiconductors and its licensor disclaim any and - * all warranties, express or implied, including all implied warranties of - * merchantability, fitness for a particular purpose and non-infringement of - * intellectual property rights. NXP Semiconductors assumes no responsibility - * or liability for the use of the software, conveys no license or rights under any - * patent, copyright, mask work right, or any other intellectual property rights in - * or to any products. NXP Semiconductors reserves the right to make changes - * in the software without notification. NXP Semiconductors also makes no - * representation or warranty that such application will be suitable for the - * specified use without further testing or modification. - * - * @par - * Permission to use, copy, modify, and distribute this software and its - * documentation is hereby granted, under NXP Semiconductors' and its - * licensor's relevant copyrights in the software, without fee, provided that it - * is used in conjunction with NXP Semiconductors microcontrollers. This - * copyright, permission, and disclaimer notice must appear in all copies of - * this code. - */ - -#include "lwip/opt.h" - -#if NO_SYS == 1 - -#include "chip.h" -#include "lpc_arch.h" - -/** @ingroup NET_LWIP_ARCH - * @{ - */ - -/***************************************************************************** - * Private types/enumerations/variables - ****************************************************************************/ - -/* Saved reference period foe standalone mode */ -static uint32_t saved_period; - -/* Saved total time in mS since timer was enabled */ -static volatile u32_t systick_timems; - -/***************************************************************************** - * Public types/enumerations/variables - ****************************************************************************/ - -/* Current system clock rate, mainly used for sysTick */ -extern uint32_t SystemCoreClock; - -/***************************************************************************** - * Private functions - ****************************************************************************/ - -/***************************************************************************** - * Public functions - ****************************************************************************/ - -/* Enable LWIP tick and interrupt */ -void SysTick_Enable(uint32_t period) -{ - /* Initialize System Tick with time interval */ -// SYSTICK_InternalInit(period); // FIXME -// saved_period = period; // FIXME -// systick_timems = 0; // FIXME - - /* Enable System Tick interrupt */ -// SYSTICK_IntCmd(ENABLE); // FIXME - - /* Enable System Tick Counter */ -// SYSTICK_Cmd(ENABLE); // FIXME - - saved_period = period; - SysTick_Config((SystemCoreClock * period) / 1000); -} - -/* Disable LWIP tick */ -void SysTick_Disable(void) -{ - /* Disable System Tick Counter */ -// SYSTICK_Cmd(DISABLE); // FIXME - - /* Disable System Tick interrupt */ -// SYSTICK_IntCmd(DISABLE); // FIXME - - SysTick->CTRL &= ~SysTick_CTRL_ENABLE_Msk; -} - -/** - * @brief SysTick IRQ handler and timebase management - * @return Nothing - * @note This function keeps a timebase for LWIP that can be - * used for other functions. - */ -void SysTick_Handler(void) -{ - /* Clear System Tick counter flag */ -// SYSTICK_ClearCounterFlag(); // FIXME - - /* Increment tick count */ - systick_timems += saved_period; -} - - -/* Get the current systick time in milliSeconds */ -uint32_t SysTick_GetMS(void) -{ - return systick_timems; -} - -/* Delay for the specified number of milliSeconds */ -void msDelay(uint32_t ms) -{ - uint32_t to = ms + systick_timems; - - while (to > systick_timems) {} -} - -/** - * @brief LWIP standalone mode time support - * @return Returns the current time in mS - * @note Returns the current time in mS. This is needed for the LWIP timers - */ -u32_t sys_now(void) -{ - return (u32_t) SysTick_GetMS(); -} - -/** - * @} - */ - -#endif /* NO_SYS == 1 */ diff --git a/vendor/lwip/lpclwip/arch/lpc18xx_43xx_emac.c b/vendor/lwip/lpclwip/arch/lpc18xx_43xx_emac.c index 58602d5c1..7f5106d83 100644 --- a/vendor/lwip/lpclwip/arch/lpc18xx_43xx_emac.c +++ b/vendor/lwip/lpclwip/arch/lpc18xx_43xx_emac.c @@ -1,33 +1,27 @@ -/* - * @brief LPC18xx/43xx LWIP EMAC driver - * - * @note - * Copyright(C) NXP Semiconductors, 2012 - * All rights reserved. - * - * @par - * Software that is described herein is for illustrative purposes only - * which provides customers with programming information regarding the - * LPC products. This software is supplied "AS IS" without any warranties of - * any kind, and NXP Semiconductors and its licensor disclaim any and - * all warranties, express or implied, including all implied warranties of - * merchantability, fitness for a particular purpose and non-infringement of - * intellectual property rights. NXP Semiconductors assumes no responsibility - * or liability for the use of the software, conveys no license or rights under any - * patent, copyright, mask work right, or any other intellectual property rights in - * or to any products. NXP Semiconductors reserves the right to make changes - * in the software without notification. NXP Semiconductors also makes no - * representation or warranty that such application will be suitable for the - * specified use without further testing or modification. - * - * @par - * Permission to use, copy, modify, and distribute this software and its - * documentation is hereby granted, under NXP Semiconductors' and its - * licensor's relevant copyrights in the software, without fee, provided that it - * is used in conjunction with NXP Semiconductors microcontrollers. This - * copyright, permission, and disclaimer notice must appear in all copies of - * this code. - */ +/********************************************************************** +* $Id$ lpc18xx_43xx_emac.c 2011-11-20 +*//** +* @file lpc18xx_43xx_emac.c +* @brief LPC18xx/43xx ethernet driver for LWIP +* @version 1.0 +* @date 20. Nov. 2011 +* @author NXP MCU SW Application Team +* +* Copyright(C) 2012, NXP Semiconductor +* All rights reserved. +* +*********************************************************************** +* Software that is described herein is for illustrative purposes only +* which provides customers with programming information regarding the +* products. This software is supplied "AS IS" without any warranties. +* NXP Semiconductors assumes no responsibility or liability for the +* use of the software, conveys no license or title under any patent, +* copyright, or mask work right to the product. NXP Semiconductors +* reserves the right to make changes in the software without +* notification. NXP Semiconductors also make no representation or +* warranty that such application will be suitable for the specified +* use without further testing or modification. +**********************************************************************/ #include "lwip/opt.h" #include "lwip/sys.h" @@ -39,16 +33,17 @@ #include "netif/etharp.h" #include "netif/ppp_oe.h" -#include "lpc_18xx43xx_emac_config.h" +#include "boards/board.h" +#include "lpc18xx_43xx_mac_regs.h" #include "lpc18xx_43xx_emac.h" - -#include "chip.h" -#include "board.h" #include "lpc_phy.h" -#include <string.h> +// FIXME - still to do +// Checksum offloading for packets using 43xx hardware -extern void msDelay(uint32_t ms); +#ifndef LPC_EMAC_RMII +#error LPC_EMAC_RMII is not defined! +#endif #if LPC_NUM_BUFF_TXDESCS < 2 #error LPC_NUM_BUFF_TXDESCS must be at least 2 @@ -62,17 +57,15 @@ extern void msDelay(uint32_t ms); #error LPC_CHECK_SLOWMEM must be 0 or 1 #endif -/** @ingroup NET_LWIP_LPC18XX43XX_EMAC_DRIVER +/** @defgroup lwip18xx_43xx_emac_DRIVER lpc18xx/43xx EMAC driver for LWIP + * @ingroup lwip_emac + * * @{ */ -/***************************************************************************** - * Private types/enumerations/variables - ****************************************************************************/ - #if NO_SYS == 0 -/** - * @brief Driver transmit and receive thread priorities +/** \brief Driver transmit and receive thread priorities + * * Thread priorities for receive thread and TX cleanup thread. Alter * to prioritize receive or transmit bandwidth. In a heavily loaded * system or with LWIP_DEBUG enabled, the priorities might be better @@ -81,64 +74,140 @@ extern void msDelay(uint32_t ms); #define tskRECPKT_PRIORITY (TCPIP_THREAD_PRIO - 1) #endif -/** @brief Debug output formatter lock define +/** \brief Debug output formatter lock define + * * When using FreeRTOS and with LWIP_DEBUG enabled, enabling this * define will allow RX debug messages to not interleave with the * TX messages (so they are actually readable). Not enabling this * define when the system is under load will cause the output to * be unreadable. There is a small tradeoff in performance for this * so use it only for debug. */ -// #define LOCK_RX_THREAD +//#define LOCK_RX_THREAD /* LPC EMAC driver data structure */ struct lpc_enetdata { - struct netif *netif; /**< Reference back to LWIP parent netif */ - - IP_ENET_001_ENHTXDESC_T ptdesc[LPC_NUM_BUFF_TXDESCS]; /**< TX descriptor list */ - IP_ENET_001_ENHRXDESC_T prdesc[LPC_NUM_BUFF_RXDESCS]; /**< RX descriptor list */ - struct pbuf *txpbufs[LPC_NUM_BUFF_TXDESCS]; /**< Saved pbuf pointers, for free after TX */ - - volatile u32_t tx_free_descs; /**< Number of free TX descriptors */ - u32_t tx_fill_idx; /**< Current free TX descriptor index */ - u32_t tx_reclaim_idx; /**< Next incoming TX packet descriptor index */ - struct pbuf *rxpbufs[LPC_NUM_BUFF_RXDESCS]; /**< Saved pbuf pointers for RX */ - - volatile u32_t rx_free_descs; /**< Number of free RX descriptors */ - volatile u32_t rx_get_idx; /**< Index to next RX descriptor that id to be received */ - u32_t rx_next_idx; /**< Index to next RX descriptor that needs a pbuf */ + struct netif *netif; /**< Reference back to LWIP parent netif */ + TRAN_DESC_ENH_T ptdesc[LPC_NUM_BUFF_TXDESCS]; /**< TX descriptor list */ + REC_DESC_ENH_T prdesc[LPC_NUM_BUFF_RXDESCS]; /**< RX descriptor list */ + struct pbuf *txpbufs[LPC_NUM_BUFF_TXDESCS]; /**< Saved pbuf pointers, for free after TX */ + volatile u32_t tx_free_descs; /**< Number of free TX descriptors */ + u32_t tx_fill_idx; /**< Current free TX descriptor index */ + u32_t tx_reclaim_idx; /**< Next incoming TX packet descriptor index */ + struct pbuf *rxpbufs[LPC_NUM_BUFF_RXDESCS]; /**< Saved pbuf pointers for RX */ + volatile u32_t rx_free_descs; /**< Number of free RX descriptors */ + volatile u32_t rx_get_idx; /**< Index to next RX descriptor that id to be received */ + u32_t rx_next_idx; /**< Index to next RX descriptor that needs a pbuf */ #if NO_SYS == 0 - sys_sem_t RxSem;/**< RX receive thread wakeup semaphore */ - sys_sem_t TxCleanSem; /**< TX cleanup thread wakeup semaphore */ - sys_mutex_t TXLockMutex;/**< TX critical section mutex */ - xSemaphoreHandle xTXDCountSem; /**< TX free buffer counting semaphore */ + sys_sem_t RxSem; /**< RX receive thread wakeup semaphore */ + sys_sem_t TxCleanSem; /**< TX cleanup thread wakeup semaphore */ + sys_mutex_t TXLockMutex; /**< TX critical section mutex */ + xSemaphoreHandle xTXDCountSem; /**< TX free buffer counting semaphore */ #endif }; -/* LPC EMAC driver work data */ +/** \brief LPC EMAC driver work data + */ static struct lpc_enetdata lpc_enetdata; -static uint32_t intMask; - #if LPC_CHECK_SLOWMEM == 1 struct lpc_slowmem_array_t { u32_t start; u32_t end; }; - -const static struct lpc_slowmem_array_t slmem[] = LPC_SLOWMEM_ARRAY; +const struct lpc_slowmem_array_t slmem[] = LPC_SLOWMEM_ARRAY; #endif -/***************************************************************************** - * Public types/enumerations/variables - ****************************************************************************/ +/* Write a value via the MII link (non-blocking) */ +void lpc_mii_write_noblock(u32_t PhyReg, u32_t Value) +{ + /* Write value at PHY address and register */ + LPC_ETHERNET->MAC_MII_ADDR = MAC_MIIA_PA(LPC_PHYDEF_PHYADDR) | + MAC_MIIA_GR(PhyReg) | MAC_MIIA_CR(4) | MAC_MIIA_W; + LPC_ETHERNET->MAC_MII_DATA = Value; + LPC_ETHERNET->MAC_MII_ADDR |= MAC_MIIA_GB; +} + +/* Write a value via the MII link (blocking) */ +err_t lpc_mii_write(u32_t PhyReg, u32_t Value) +{ + u32_t mst = 250; + err_t sts = ERR_OK; + + /* Write value at PHY address and register */ + lpc_mii_write_noblock(PhyReg, Value); + + /* Wait for unbusy status */ + while (mst > 0) { + sts = LPC_ETHERNET->MAC_MII_ADDR & MAC_MIIA_GB; + if (sts == 0) + mst = 0; + else { + mst--; + msDelay(1); + } + } -/***************************************************************************** - * Private functions - ****************************************************************************/ + if (sts != 0) + sts = ERR_TIMEOUT; -/* Queues a pbuf into a free RX descriptor */ + return sts; +} + +/* Reads current MII link busy status */ +u32_t lpc_mii_is_busy(void) +{ + return (LPC_ETHERNET->MAC_MII_ADDR & MAC_MIIA_GB); +} + +/* Starts a read operation via the MII link (non-blocking) */ +u32_t lpc_mii_read_data(void) +{ + return LPC_ETHERNET->MAC_MII_DATA; +} + +/* Starts a read operation via the MII link (non-blocking) */ +void lpc_mii_read_noblock(u32_t PhyReg) +{ + /* Read value at PHY address and register */ + LPC_ETHERNET->MAC_MII_ADDR = MAC_MIIA_PA(LPC_PHYDEF_PHYADDR) | + MAC_MIIA_GR(PhyReg) | MAC_MIIA_CR(4); + LPC_ETHERNET->MAC_MII_ADDR |= MAC_MIIA_GB; +} + +/* Read a value via the MII link (blocking) */ +err_t lpc_mii_read(u32_t PhyReg, u32_t *data) +{ + u32_t mst = 250; + err_t sts = ERR_OK; + + /* Read value at PHY address and register */ + lpc_mii_read_noblock(PhyReg); + + /* Wait for unbusy status */ + while (mst > 0) { + sts = LPC_ETHERNET->MAC_MII_ADDR & MAC_MIIA_GB; + if (sts == 0) { + mst = 0; + *data = LPC_ETHERNET->MAC_MII_DATA; + } else { + mst--; + msDelay(1); + } + } + + if (sts != 0) + sts = ERR_TIMEOUT; + + return sts; +} + +/** \brief Queues a pbuf into a free RX descriptor + * + * \param[in] lpc_netifdata Pointer to the driver data structure + * \param[in] p Pointer to pbuf to queue + */ static void lpc_rxqueue_pbuf(struct lpc_enetdata *lpc_netifdata, - struct pbuf *p) + struct pbuf *p) { u32_t idx = lpc_netifdata->rx_next_idx; @@ -147,10 +216,9 @@ static void lpc_rxqueue_pbuf(struct lpc_enetdata *lpc_netifdata, /* Buffer size and address for pbuf */ lpc_netifdata->prdesc[idx].CTRL = (u32_t) RDES_ENH_BS1(p->len) | - RDES_ENH_RCH; - if (idx == (LPC_NUM_BUFF_RXDESCS - 1)) { + RDES_ENH_RCH; + if (idx == (LPC_NUM_BUFF_RXDESCS - 1)) lpc_netifdata->prdesc[idx].CTRL |= RDES_ENH_RER; - } lpc_netifdata->prdesc[idx].B1ADD = (u32_t) p->payload; /* Give descriptor to MAC/DMA */ @@ -159,19 +227,64 @@ static void lpc_rxqueue_pbuf(struct lpc_enetdata *lpc_netifdata, /* Update free count */ lpc_netifdata->rx_free_descs--; - LWIP_DEBUGF(EMAC_DEBUG | LWIP_DBG_TRACE, - ("lpc_rxqueue_pbuf: Queueing packet %p at index %d, free %d\n", - p, idx, lpc_netifdata->rx_free_descs)); + LWIP_DEBUGF(UDP_LPC_EMAC | LWIP_DBG_TRACE, + ("lpc_rxqueue_pbuf: Queueing packet %p at index %d, free %d\n", + p, idx, lpc_netifdata->rx_free_descs)); /* Update index for next pbuf */ idx++; - if (idx >= LPC_NUM_BUFF_RXDESCS) { + if (idx >= LPC_NUM_BUFF_RXDESCS) idx = 0; - } lpc_netifdata->rx_next_idx = idx; } -/* This function sets up the descriptor list used for receive packets */ +/** \brief Attempt to allocate and requeue a new pbuf for RX + * + * \param[in] netif Pointer to the netif structure + * \returns The number of new descriptors queued + */ +s32_t lpc_rx_queue(struct netif *netif) +{ + struct lpc_enetdata *lpc_netifdata = netif->state; + struct pbuf *p; + s32_t queued = 0; + + /* Attempt to requeue as many packets as possible */ + while (lpc_netifdata->rx_free_descs > 0) { + /* Allocate a pbuf from the pool. We need to allocate at the + maximum size as we don't know the size of the yet to be + received packet. */ + p = pbuf_alloc(PBUF_RAW, (u16_t) EMAC_ETH_MAX_FLEN, PBUF_RAM); + if (p == NULL) { + LWIP_DEBUGF(UDP_LPC_EMAC | LWIP_DBG_TRACE, + ("lpc_rx_queue: could not allocate RX pbuf index %d, " + "free %d)\n", lpc_netifdata->rx_next_idx, + lpc_netifdata->rx_free_descs)); + return queued; + } + + /* pbufs allocated from the RAM pool should be non-chained (although + the hardware will allow chaining) */ + LWIP_ASSERT("lpc_rx_queue: pbuf is not contiguous (chained)", + pbuf_clen(p) <= 1); + + /* Queue packet */ + lpc_rxqueue_pbuf(lpc_netifdata, p); + + /* Update queued count */ + queued++; + } + + return queued; +} + +/** \brief Sets up the RX descriptor ring buffers + * + * This function sets up the descriptor list used for receive packets. + * + * \param[in] lpc_netifdata Pointer to driver data structure + * \returns Always returns ERR_OK + */ static err_t lpc_rx_setup(struct lpc_enetdata *lpc_netifdata) { s32_t idx; @@ -189,7 +302,7 @@ static err_t lpc_rx_setup(struct lpc_enetdata *lpc_netifdata) for (idx = 0; idx < LPC_NUM_BUFF_RXDESCS; idx++) { lpc_netifdata->prdesc[idx].CTRL = RDES_ENH_RCH; lpc_netifdata->prdesc[idx].B2ADD = (u32_t) - &lpc_netifdata->prdesc[idx + 1]; + &lpc_netifdata->prdesc[idx + 1]; } lpc_netifdata->prdesc[LPC_NUM_BUFF_RXDESCS - 1].CTRL = RDES_ENH_RCH | RDES_ENH_RER; @@ -198,17 +311,22 @@ static err_t lpc_rx_setup(struct lpc_enetdata *lpc_netifdata) LPC_ETHERNET->DMA_REC_DES_ADDR = (u32_t) lpc_netifdata->prdesc; /* Setup up RX pbuf queue, but post a warning if not enough were - queued for all descriptors. */ - if (lpc_rx_queue(lpc_netifdata->netif) != LPC_NUM_BUFF_RXDESCS) { - LWIP_DEBUGF(EMAC_DEBUG | LWIP_DBG_TRACE, - ("lpc_rx_setup: Warning, not enough memory for RX pbufs\n")); - } + queued for all descriptors. */ + if (lpc_rx_queue(lpc_netifdata->netif) != LPC_NUM_BUFF_RXDESCS) + LWIP_DEBUGF(UDP_LPC_EMAC | LWIP_DBG_TRACE, + ("lpc_rx_setup: Warning, not enough memory for RX pbufs\n")); return ERR_OK; } -/* Gets data from queue and forwards to LWIP */ -static struct pbuf *lpc_low_level_input(struct netif *netif) { +/** \brief Gets data from queue and forwards to LWIP + * + * \param[in] netif the lwip network interface structure for this lpc_enetif + * \return a pbuf filled with the received packet (including MAC header) or + * NULL on memory error + */ +static struct pbuf *lpc_low_level_input(struct netif *netif) +{ struct lpc_enetdata *lpc_netifdata = netif->state; u32_t status, ridx; int rxerr = 0; @@ -257,17 +375,25 @@ static struct pbuf *lpc_low_level_input(struct netif *netif) { LINK_STATS_INC(link.drop); /* Error conditions that cause a packet drop */ - if (status & intMask) { + if (status & ( +#if LPC_EMAC_RMII == 0 + RDES_CE | RDES_RE | RDES_RWT | RDES_LC | RDES_OE | RDES_SAF | + RDES_AFM +#else + RDES_CE | RDES_DE | RDES_RE | RDES_RWT | RDES_LC | RDES_OE | + RDES_SAF | RDES_AFM +#endif + )) { LINK_STATS_INC(link.err); rxerr = 1; - } - else + } else + /* Length error check needs qualification */ if ((status & (RDES_LE | RDES_FT)) == RDES_LE) { LINK_STATS_INC(link.lenerr); rxerr = 1; - } - else + } else + /* CRC error check needs qualification */ if ((status & (RDES_CE | RDES_LS)) == (RDES_CE | RDES_LS)) { LINK_STATS_INC(link.chkerr); @@ -278,8 +404,8 @@ static struct pbuf *lpc_low_level_input(struct netif *netif) { if ((status & (RDES_DE | RDES_LS)) == (RDES_DE | RDES_LS)) { LINK_STATS_INC(link.err); rxerr = 1; - } - else + } else + /* Dribble bit error only applies in half duplex mode */ if ((status & RDES_DE) && (!(LPC_ETHERNET->MAC_CONFIG & MAC_CFG_DM))) { @@ -291,9 +417,8 @@ static struct pbuf *lpc_low_level_input(struct netif *netif) { /* Increment free descriptor count and next get index */ lpc_netifdata->rx_free_descs++; ridx++; - if (ridx >= LPC_NUM_BUFF_RXDESCS) { + if (ridx >= LPC_NUM_BUFF_RXDESCS) ridx = 0; - } lpc_netifdata->rx_get_idx = ridx; /* If an error occurred, just re-queue the pbuf */ @@ -301,11 +426,10 @@ static struct pbuf *lpc_low_level_input(struct netif *netif) { lpc_rxqueue_pbuf(lpc_netifdata, p); p = NULL; - LWIP_DEBUGF(EMAC_DEBUG | LWIP_DBG_TRACE, - ("lpc_low_level_input: RX error condition status 0x%08x\n", - status)); - } - else { + LWIP_DEBUGF(UDP_LPC_EMAC | LWIP_DBG_TRACE, + ("lpc_low_level_input: RX error condition status 0x%08x\n", + status)); + } else { /* Attempt to queue a new pbuf for the descriptor */ lpc_rx_queue(netif); @@ -314,9 +438,9 @@ static struct pbuf *lpc_low_level_input(struct netif *netif) { LINK_STATS_INC(link.recv); - LWIP_DEBUGF(EMAC_DEBUG | LWIP_DBG_TRACE, - ("lpc_low_level_input: Packet received, %d bytes, " - "status 0x%08x\n", p->len, status)); + LWIP_DEBUGF(UDP_LPC_EMAC | LWIP_DBG_TRACE, + ("lpc_low_level_input: Packet received, %d bytes, " + "status 0x%08x\n", p->len, status)); } /* (Re)start receive polling */ @@ -329,16 +453,61 @@ static struct pbuf *lpc_low_level_input(struct netif *netif) { #endif #endif - return p; + return p; } -/* This function sets up the descriptor list used for transmit packets */ +/** \brief Attempt to read a packet from the EMAC interface. + * + * \param[in] netif the lwip network interface structure for this lpc_enetif + */ +void lpc_enetif_input(struct netif *netif) +{ + struct eth_hdr *ethhdr; + struct pbuf *p; + + /* move received packet into a new pbuf */ + p = lpc_low_level_input(netif); + if (p == NULL) + return; + + /* points to packet payload, which starts with an Ethernet header */ + ethhdr = p->payload; + + switch (htons(ethhdr->type)) { + case ETHTYPE_IP: + case ETHTYPE_ARP: +#if PPPOE_SUPPORT + case ETHTYPE_PPPOEDISC: + case ETHTYPE_PPPOE: +#endif /* PPPOE_SUPPORT */ + /* full packet send to tcpip_thread to process */ + if (netif->input(p, netif) != ERR_OK) { + LWIP_DEBUGF(NETIF_DEBUG, + ("lpc_enetif_input: IP input error\n")); + /* Free buffer */ + pbuf_free(p); + } + break; + + default: + /* Return buffer */ + pbuf_free(p); + break; + } +} + +/** \brief Sets up the TX descriptor ring buffers. + * + * This function sets up the descriptor list used for transmit packets. + * + * \param[in] lpc_netifdata Pointer to driver data structure + */ static err_t lpc_tx_setup(struct lpc_enetdata *lpc_netifdata) { s32_t idx; /* Clear TX descriptors, will be queued with pbufs as needed */ - memset((void *) &lpc_netifdata->ptdesc[0], 0, sizeof(lpc_netifdata->ptdesc)); + memset(&lpc_netifdata->ptdesc[0], 0, sizeof(lpc_netifdata->ptdesc)); lpc_netifdata->tx_free_descs = LPC_NUM_BUFF_TXDESCS; lpc_netifdata->tx_fill_idx = 0; lpc_netifdata->tx_reclaim_idx = 0; @@ -352,7 +521,7 @@ static err_t lpc_tx_setup(struct lpc_enetdata *lpc_netifdata) lpc_netifdata->ptdesc[LPC_NUM_BUFF_TXDESCS - 1].CTRLSTAT = TDES_ENH_TCH | TDES_ENH_TER | TDES_ENH_CIC(3); lpc_netifdata->ptdesc[LPC_NUM_BUFF_TXDESCS - 1].B2ADD = - (u32_t) &lpc_netifdata->ptdesc[0]; + (u32_t) &lpc_netifdata->ptdesc[0]; /* Setup pointer to TX descriptor table */ LPC_ETHERNET->DMA_TRANS_DES_ADDR = (u32_t) lpc_netifdata->ptdesc; @@ -360,26 +529,113 @@ static err_t lpc_tx_setup(struct lpc_enetdata *lpc_netifdata) return ERR_OK; } -/* Low level output of a packet. Never call this from an interrupt context, - as it may block until TX descriptors become available */ +/** \brief Call for freeing TX buffers that are complete + * + * \param[in] netif the lwip network interface structure for this lpc_enetif + */ +void lpc_tx_reclaim(struct netif *netif) +{ + struct lpc_enetdata *lpc_netifdata = netif->state; + s32_t ridx; + u32_t status; + +#if NO_SYS == 0 + /* Get exclusive access */ + sys_mutex_lock(&lpc_netifdata->TXLockMutex); +#endif + + /* If a descriptor is available and is no longer owned by the + hardware, it can be reclaimed */ + ridx = lpc_netifdata->tx_reclaim_idx; + while ((lpc_netifdata->tx_free_descs < LPC_NUM_BUFF_TXDESCS) && + (!(lpc_netifdata->ptdesc[ridx].CTRLSTAT & TDES_OWN))) { + /* Peek at the status of the descriptor to determine if the + packet is good and any status information. */ + status = lpc_netifdata->ptdesc[ridx].CTRLSTAT; + + LWIP_DEBUGF(UDP_LPC_EMAC | LWIP_DBG_TRACE, + ("lpc_tx_reclaim: Reclaiming sent packet %p, index %d\n", + lpc_netifdata->txpbufs[ridx], ridx)); + + /* Check TX error conditions */ + if (status & TDES_ES) { + LWIP_DEBUGF(UDP_LPC_EMAC | LWIP_DBG_TRACE, + ("lpc_tx_reclaim: TX error condition status 0x%x\n", status)); + LINK_STATS_INC(link.err); + +#if LINK_STATS == 1 + /* Error conditions that cause a packet drop */ + if (status & (TDES_UF | TDES_ED | TDES_EC | TDES_LC)) + LINK_STATS_INC(link.drop); +#endif + } + + /* Reset control for this descriptor */ + if (ridx == (LPC_NUM_BUFF_TXDESCS - 1)) + lpc_netifdata->ptdesc[ridx].CTRLSTAT = TDES_ENH_TCH | + TDES_ENH_TER; + else + lpc_netifdata->ptdesc[ridx].CTRLSTAT = TDES_ENH_TCH; + + /* Free the pbuf associate with this descriptor */ + if (lpc_netifdata->txpbufs[ridx]) + pbuf_free(lpc_netifdata->txpbufs[ridx]); + + /* Reclaim this descriptor */ + lpc_netifdata->tx_free_descs++; +#if NO_SYS == 0 + xSemaphoreGive(lpc_netifdata->xTXDCountSem); +#endif + ridx++; + if (ridx >= LPC_NUM_BUFF_TXDESCS) + ridx = 0; + } + + lpc_netifdata->tx_reclaim_idx = ridx; + +#if NO_SYS == 0 + /* Restore access */ + sys_mutex_unlock(&lpc_netifdata->TXLockMutex); +#endif +} + +/** \brief Polls if an available TX descriptor is ready. Can be used to + * determine if the low level transmit function will block. + * + * \param[in] netif the lwip network interface structure for this lpc_enetif + * \return 0 if no descriptors are read, or >0 + */ +s32_t lpc_tx_ready(struct netif *netif) +{ + return ((struct lpc_enetdata *) netif->state)->tx_free_descs; +} + +/** \brief Low level output of a packet. Never call this from an + * interrupt context, as it may block until TX descriptors + * become available. + * + * \param[in] netif the lwip network interface structure for this lpc_enetif + * \param[in] sendp the MAC packet to send (e.g. IP packet including MAC addresses and type) + * \return ERR_OK if the packet could be sent or + * an err_t value if the packet couldn't be sent + */ static err_t lpc_low_level_output(struct netif *netif, struct pbuf *sendp) { struct lpc_enetdata *lpc_netifdata = netif->state; - u32_t idx, fidx, dn; + u32_t idx, fidx, dn, fdn; struct pbuf *p = sendp; #if LPC_CHECK_SLOWMEM == 1 struct pbuf *q, *wp; - u8_t *dst; int pcopy = 0; /* Check packet address to determine if it's in slow memory and relocate if necessary */ - for (q = p; ((q != NULL) && (pcopy == 0)); q = q->next) { + for(q = p; ((q != NULL) && (pcopy == 0)); q = q->next) { fidx = 0; for (idx = 0; idx < sizeof(slmem); - idx += sizeof(struct lpc_slowmem_array_t)) { + idx += sizeof(struct lpc_slowmem_array_t)) { if ((q->payload >= (void *) slmem[fidx].start) && (q->payload <= (void *) slmem[fidx].end)) { /* Needs copy */ @@ -399,7 +655,7 @@ static err_t lpc_low_level_output(struct netif *netif, struct pbuf *sendp) /* Copy pbuf */ dst = (u8_t *) wp->payload; wp->tot_len = 0; - for (q = p; q != NULL; q = q->next) { + for(q = p; q != NULL; q = q->next) { MEMCPY(dst, (u8_t *) q->payload, q->len); dst += q->len; wp->tot_len += q->len; @@ -421,9 +677,9 @@ static err_t lpc_low_level_output(struct netif *netif, struct pbuf *sendp) /* THIS WILL BLOCK UNTIL THERE ARE ENOUGH DESCRIPTORS AVAILABLE */ while (dn > lpc_tx_ready(netif)) #if NO_SYS == 0 - {xSemaphoreTake(lpc_netifdata->xTXDCountSem, 0); } + xSemaphoreTake(lpc_netifdata->xTXDCountSem, 0); #else - {msDelay(1); } + msDelay(1); #endif /* Get the next free descriptor index */ @@ -450,51 +706,45 @@ static err_t lpc_low_level_output(struct netif *netif, struct pbuf *sendp) lpc_netifdata->tx_free_descs--; if (idx == fidx) { lpc_netifdata->ptdesc[idx].CTRLSTAT |= TDES_ENH_FS; + #if LPC_CHECK_SLOWMEM == 1 /* If this is a copied pbuf, then avoid getting the extra reference or the TX reclaim will be off by 1 */ - if (!pcopy) { + if (!pcopy) pbuf_ref(p); - } #else /* Increment reference count on this packet so LWIP doesn't attempt to free it on return from this call */ - pbuf_ref(p); + pbuf_ref(p); #endif - } - else { + } else lpc_netifdata->ptdesc[idx].CTRLSTAT |= TDES_OWN; - } /* Save address of pbuf, but make sure it's associated with the first chained pbuf so it gets freed once all pbuf chains are transferred. */ - if (!dn) { + if (!dn) lpc_netifdata->txpbufs[idx] = sendp; - } - else { + else lpc_netifdata->txpbufs[idx] = NULL; - } /* For last packet only, interrupt and last flag */ - if (dn == 0) { + if (dn == 0) lpc_netifdata->ptdesc[idx].CTRLSTAT |= TDES_ENH_LS | - TDES_ENH_IC; - } + TDES_ENH_IC; - /* IP checksumming requires full buffering in IP */ + /* FIXME: For now, only IP header checksumming */ lpc_netifdata->ptdesc[idx].CTRLSTAT |= TDES_ENH_CIC(3); - LWIP_DEBUGF(EMAC_DEBUG | LWIP_DBG_TRACE, - ("lpc_low_level_output: pbuf packet %p sent, chain %d," - " size %d, index %d, free %d\n", p, dn, p->len, idx, - lpc_netifdata->tx_free_descs)); + LWIP_DEBUGF(UDP_LPC_EMAC | LWIP_DBG_TRACE, + ("lpc_low_level_output: pbuf packet %p sent, chain %d," + " size %d, index %d, free %d\n", p, dn, p->len, idx, + lpc_netifdata->tx_free_descs)); /* Update next available descriptor */ idx++; - if (idx >= LPC_NUM_BUFF_TXDESCS) { + if (idx >= LPC_NUM_BUFF_TXDESCS) idx = 0; - } /* Next packet fragment */ p = p->next; @@ -518,24 +768,55 @@ static err_t lpc_low_level_output(struct netif *netif, struct pbuf *sendp) return ERR_OK; } -/* This function is the ethernet packet send function. It calls - etharp_output after checking link status */ -static err_t lpc_etharp_output(struct netif *netif, struct pbuf *q, - ip_addr_t *ipaddr) +/** \brief LPC EMAC interrupt handler. + * + * This function handles the transmit, receive, and error interrupt of + * the LPC118xx/43xx. This is meant to be used when NO_SYS=0. + */ +void ETH_IRQHandler(void) { - /* Only send packet is link is up */ - if (netif->flags & NETIF_FLAG_LINK_UP) { - return etharp_output(netif, q, ipaddr); +#if NO_SYS == 1 + /* Interrupts are not used without an RTOS */ + NVIC_DisableIRQ(ETHERNET_IRQn); +#else + signed portBASE_TYPE xRecTaskWoken = pdFALSE, XTXTaskWoken = pdFALSE; + uint32_t ints; + + /* Get pending interrupts */ + ints = LPC_ETHERNET->DMA_STAT; + + /* RX group interrupt(s) */ + if (ints & (DMA_ST_RI | DMA_ST_OVF | DMA_ST_RU)) { + /* Give semaphore to wakeup RX receive task. Note the FreeRTOS + method is used instead of the LWIP arch method. */ + xSemaphoreGiveFromISR(lpc_enetdata.RxSem, &xRecTaskWoken); } - return ERR_CONN; + /* TX group interrupt(s) */ + if (ints & (DMA_ST_TI | DMA_ST_UNF | DMA_ST_TU)) { + /* Give semaphore to wakeup TX cleanup task. Note the FreeRTOS + method is used instead of the LWIP arch method. */ + xSemaphoreGiveFromISR(lpc_enetdata.TxCleanSem, &XTXTaskWoken); + } + + /* Clear pending interrupts */ + LPC_ETHERNET->DMA_STAT = ints; + + /* Context switch needed? */ + portEND_SWITCHING_ISR( xRecTaskWoken || XTXTaskWoken ); +#endif } #if NO_SYS == 0 -/* Packet reception task - This task is called when a packet is received. It will - pass the packet to the LWIP core */ -static portTASK_FUNCTION(vPacketReceiveTask, pvParameters) { +/** \brief Packet reception task + * + * This task is called when a packet is received. It will + * pass the packet to the LWIP core. + * + * \param[in] pvParameters Pointer to driver data + */ +static portTASK_FUNCTION( vPacketReceiveTask, pvParameters ) +{ struct lpc_enetdata *lpc_netifdata = pvParameters; while (1) { @@ -544,17 +825,21 @@ static portTASK_FUNCTION(vPacketReceiveTask, pvParameters) { /* Process receive packets */ while (!(lpc_netifdata->prdesc[lpc_netifdata->rx_get_idx].STATUS - & RDES_OWN)) { + & RDES_OWN)) lpc_enetif_input(lpc_netifdata->netif); - } } } -/* Transmit cleanup task - This task is called when a transmit interrupt occurs and - reclaims the pbuf and descriptor used for the packet once - the packet has been transferred */ -static portTASK_FUNCTION(vTransmitCleanupTask, pvParameters) { +/** \brief Transmit cleanup task + * + * This task is called when a transmit interrupt occurs and + * reclaims the pbuf and descriptor used for the packet once + * the packet has been transferred. + * + * \param[in] pvParameters Pointer to driver data + */ +static portTASK_FUNCTION( vTransmitCleanupTask, pvParameters ) +{ struct lpc_enetdata *lpc_netifdata = pvParameters; while (1) { @@ -567,54 +852,84 @@ static portTASK_FUNCTION(vTransmitCleanupTask, pvParameters) { } #endif -/* Low level init of the MAC and PHY */ +/** \brief Low level init of the MAC and PHY. + * + * \param[in] netif Pointer to LWIP netif structure + * \return ERR_OK or error code + */ static err_t low_level_init(struct netif *netif) { struct lpc_enetdata *lpc_netifdata = netif->state; + err_t err; + s32_t timeout; - /* Initialize via Chip ENET function */ - Chip_ENET_Init(LPC_ETHERNET); + /* Enable MAC clocking from same source as CPU */ + CGU_EntityConnect(CGU_CLKSRC_PLL1, CGU_PERIPHERAL_ETHERNET); + + /* Slightly different clocking for RMII and MII modes */ + CGU_EntityConnect(CGU_CLKSRC_ENET_TX_CLK, CGU_BASE_PHY_TX); +#if LPC_EMAC_RMII == 1 + /* RMII mode gets PHY RX clock from ENET_REF_CLK (same pin as + ENET_TX_CLK on the chip) */ + CGU_EntityConnect(CGU_CLKSRC_ENET_TX_CLK, CGU_BASE_PHY_RX); +#else + /* MII mode gets PHY RX clock from ENET_RX_CLK */ + CGU_EntityConnect(CGU_CLKSRC_ENET_RX_CLK, CGU_BASE_PHY_RX); +#endif + + /* Reset ethernet via RGU. This should be 1 clock, but we wait + anyways. If the while loop really stalls, something else + is wrong. */ + LPC_RGU->RESET_CTRL0 = (1 << 22); + timeout = 10; + while (!(LPC_RGU->RESET_ACTIVE_STATUS0 & (1 << 22))) { + msDelay(1); + timeout--; + if (timeout == 0) + return ERR_TIMEOUT; + } + + /* Reset MAC Subsystem internal registers and logic */ + LPC_ETHERNET->DMA_BUS_MODE |= DMA_BM_SWR; + timeout = 3; + while (LPC_ETHERNET->DMA_BUS_MODE & DMA_BM_SWR) { + msDelay(1); + timeout--; + if (timeout == 0) + return ERR_TIMEOUT; + } + LPC_ETHERNET->DMA_BUS_MODE = DMA_BM_ATDS | DMA_BM_PBL(1) | DMA_BM_RPBL(1); /* Save MAC address */ - Chip_ENET_SetADDR(LPC_ETHERNET, netif->hwaddr); + LPC_ETHERNET->MAC_ADDR0_LOW = ((u32_t) netif->hwaddr[3] << 24) | + ((u32_t) netif->hwaddr[2] << 16) | ((u32_t) netif->hwaddr[1] << 8) | + (u32_t) netif->hwaddr[0]; + LPC_ETHERNET->MAC_ADDR0_HIGH = ((u32_t) netif->hwaddr[5] << 8) | + (u32_t) netif->hwaddr[4]; /* Initial MAC configuration for checksum offload, full duplex, 100Mbps, disable receive own in half duplex, inter-frame gap of 64-bits */ LPC_ETHERNET->MAC_CONFIG = MAC_CFG_BL(0) | MAC_CFG_IPC | MAC_CFG_DM | - MAC_CFG_DO | MAC_CFG_FES | MAC_CFG_PS | MAC_CFG_IFG(3); + MAC_CFG_DO | MAC_CFG_FES | MAC_CFG_PS | MAC_CFG_IFG(3); /* Setup filter */ #if IP_SOF_BROADCAST_RECV LPC_ETHERNET->MAC_FRAME_FILTER = MAC_FF_PR | MAC_FF_RA; #else - LPC_ETHERNET->MAC_FRAME_FILTER = 0; /* Only matching MAC address */ + LPC_ETHERNET->MAC_FRAME_FILTER = 0; /* Only matching MAC address */ #endif /* Initialize the PHY */ -#if defined(USE_RMII) - if (lpc_phy_init(true, msDelay) != SUCCESS) { - return ERROR; - } - - intMask = RDES_CE | RDES_DE | RDES_RE | RDES_RWT | RDES_LC | RDES_OE | - RDES_SAF | RDES_AFM; -#else - if (lpc_phy_init(false, msDelay) != SUCCESS) { - return ERROR; - } - - intMask = RDES_CE | RDES_RE | RDES_RWT | RDES_LC | RDES_OE | RDES_SAF | - RDES_AFM; -#endif + err = lpc_phy_init(netif, LPC_EMAC_RMII); + if (err != ERR_OK) + return err; /* Setup transmit and receive descriptors */ - if (lpc_tx_setup(lpc_netifdata) != ERR_OK) { + if (lpc_tx_setup(lpc_netifdata) != ERR_OK) return ERR_BUF; - } - if (lpc_rx_setup(lpc_netifdata) != ERR_OK) { + if (lpc_rx_setup(lpc_netifdata) != ERR_OK) return ERR_BUF; - } /* Flush transmit FIFO */ LPC_ETHERNET->DMA_OP_MODE = DMA_OM_FTF; @@ -632,14 +947,14 @@ static err_t low_level_init(struct netif *netif) 0; #else DMA_IE_TIE | DMA_IE_OVE | DMA_IE_UNE | DMA_IE_RIE | DMA_IE_NIE | - DMA_IE_AIE | DMA_IE_TUE | DMA_IE_RUE; + DMA_IE_AIE | DMA_IE_TUE | DMA_IE_RUE; #endif /* Enable receive and transmit DMA processes */ LPC_ETHERNET->DMA_OP_MODE |= DMA_OM_ST | DMA_OM_SR; /* Enable packet reception */ - LPC_ETHERNET->MAC_CONFIG |= MAC_CFG_RE | MAC_CFG_TE; + LPC_ETHERNET->MAC_CONFIG |= MAC_CFG_RE | MAC_CFG_TE; /* Start receive polling */ LPC_ETHERNET->DMA_REC_POLL_DEMAND = 1; @@ -647,252 +962,88 @@ static err_t low_level_init(struct netif *netif) return ERR_OK; } -/***************************************************************************** - * Public functions - ****************************************************************************/ -/* Attempt to allocate and requeue a new pbuf for RX */ -s32_t lpc_rx_queue(struct netif *netif) -{ - struct lpc_enetdata *lpc_netifdata = netif->state; - struct pbuf *p; - - s32_t queued = 0; - - /* Attempt to requeue as many packets as possible */ - while (lpc_netifdata->rx_free_descs > 0) { - /* Allocate a pbuf from the pool. We need to allocate at the - maximum size as we don't know the size of the yet to be - received packet. */ - p = pbuf_alloc(PBUF_RAW, (u16_t) EMAC_ETH_MAX_FLEN, PBUF_RAM); - if (p == NULL) { - LWIP_DEBUGF(EMAC_DEBUG | LWIP_DBG_TRACE, - ("lpc_rx_queue: could not allocate RX pbuf index %d, " - "free %d)\n", lpc_netifdata->rx_next_idx, - lpc_netifdata->rx_free_descs)); - return queued; - } - - /* pbufs allocated from the RAM pool should be non-chained (although - the hardware will allow chaining) */ - LWIP_ASSERT("lpc_rx_queue: pbuf is not contiguous (chained)", - pbuf_clen(p) <= 1); - - /* Queue packet */ - lpc_rxqueue_pbuf(lpc_netifdata, p); - - /* Update queued count */ - queued++; - } - - return queued; -} - -/* Attempt to read a packet from the EMAC interface */ -void lpc_enetif_input(struct netif *netif) -{ - struct eth_hdr *ethhdr; - - struct pbuf *p; - - /* move received packet into a new pbuf */ - p = lpc_low_level_input(netif); - if (p == NULL) { - return; - } - - /* points to packet payload, which starts with an Ethernet header */ - ethhdr = p->payload; - - switch (htons(ethhdr->type)) { - case ETHTYPE_IP: - case ETHTYPE_ARP: -#if PPPOE_SUPPORT - case ETHTYPE_PPPOEDISC: - case ETHTYPE_PPPOE: -#endif /* PPPOE_SUPPORT */ - /* full packet send to tcpip_thread to process */ - if (netif->input(p, netif) != ERR_OK) { - LWIP_DEBUGF(NETIF_DEBUG, - ("lpc_enetif_input: IP input error\n")); - /* Free buffer */ - pbuf_free(p); - } - break; - - default: - /* Return buffer */ - pbuf_free(p); - break; - } -} - -/* Call for freeing TX buffers that are complete */ -void lpc_tx_reclaim(struct netif *netif) -{ - struct lpc_enetdata *lpc_netifdata = netif->state; - s32_t ridx; - u32_t status; - -#if NO_SYS == 0 - /* Get exclusive access */ - sys_mutex_lock(&lpc_netifdata->TXLockMutex); -#endif - - /* If a descriptor is available and is no longer owned by the - hardware, it can be reclaimed */ - ridx = lpc_netifdata->tx_reclaim_idx; - while ((lpc_netifdata->tx_free_descs < LPC_NUM_BUFF_TXDESCS) && - (!(lpc_netifdata->ptdesc[ridx].CTRLSTAT & TDES_OWN))) { - /* Peek at the status of the descriptor to determine if the - packet is good and any status information. */ - status = lpc_netifdata->ptdesc[ridx].CTRLSTAT; - - LWIP_DEBUGF(EMAC_DEBUG | LWIP_DBG_TRACE, - ("lpc_tx_reclaim: Reclaiming sent packet %p, index %d\n", - lpc_netifdata->txpbufs[ridx], ridx)); - - /* Check TX error conditions */ - if (status & TDES_ES) { - LWIP_DEBUGF(EMAC_DEBUG | LWIP_DBG_TRACE, - ("lpc_tx_reclaim: TX error condition status 0x%x\n", status)); - LINK_STATS_INC(link.err); - -#if LINK_STATS == 1 - /* Error conditions that cause a packet drop */ - if (status & (TDES_UF | TDES_ED | TDES_EC | TDES_LC)) { - LINK_STATS_INC(link.drop); - } -#endif - } - - /* Reset control for this descriptor */ - if (ridx == (LPC_NUM_BUFF_TXDESCS - 1)) { - lpc_netifdata->ptdesc[ridx].CTRLSTAT = TDES_ENH_TCH | - TDES_ENH_TER; - } - else { - lpc_netifdata->ptdesc[ridx].CTRLSTAT = TDES_ENH_TCH; - } - - /* Free the pbuf associate with this descriptor */ - if (lpc_netifdata->txpbufs[ridx]) { - pbuf_free(lpc_netifdata->txpbufs[ridx]); - } - - /* Reclaim this descriptor */ - lpc_netifdata->tx_free_descs++; -#if NO_SYS == 0 - xSemaphoreGive(lpc_netifdata->xTXDCountSem); -#endif - ridx++; - if (ridx >= LPC_NUM_BUFF_TXDESCS) { - ridx = 0; - } - } - - lpc_netifdata->tx_reclaim_idx = ridx; - -#if NO_SYS == 0 - /* Restore access */ - sys_mutex_unlock(&lpc_netifdata->TXLockMutex); -#endif -} - -/* Polls if an available TX descriptor is ready */ -s32_t lpc_tx_ready(struct netif *netif) -{ - return ((struct lpc_enetdata *) netif->state)->tx_free_descs; -} - /** - * @brief EMAC interrupt handler - * @return Nothing - * @note This function handles the transmit, receive, and error interrupt of - * the LPC118xx/43xx. This is meant to be used when NO_SYS=0. + * This function provides a method for the PHY to setup the EMAC + * for the PHY negotiated duplex mode. + * + * \param[in] full_duplex 0 = half duplex, 1 = full duplex */ -void ETH_IRQHandler(void) -{ -#if NO_SYS == 1 - /* Interrupts are not used without an RTOS */ - NVIC_DisableIRQ((IRQn_Type) ETHERNET_IRQn); -#else - signed portBASE_TYPE xRecTaskWoken = pdFALSE, XTXTaskWoken = pdFALSE; - uint32_t ints; - - /* Get pending interrupts */ - ints = LPC_ETHERNET->DMA_STAT; - - /* RX group interrupt(s) */ - if (ints & (DMA_ST_RI | DMA_ST_OVF | DMA_ST_RU)) { - /* Give semaphore to wakeup RX receive task. Note the FreeRTOS - method is used instead of the LWIP arch method. */ - xSemaphoreGiveFromISR(lpc_enetdata.RxSem, &xRecTaskWoken); - } - - /* TX group interrupt(s) */ - if (ints & (DMA_ST_TI | DMA_ST_UNF | DMA_ST_TU)) { - /* Give semaphore to wakeup TX cleanup task. Note the FreeRTOS - method is used instead of the LWIP arch method. */ - xSemaphoreGiveFromISR(lpc_enetdata.TxCleanSem, &XTXTaskWoken); - } - - /* Clear pending interrupts */ - LPC_ETHERNET->DMA_STAT = ints; - - /* Context switch needed? */ - portEND_SWITCHING_ISR(xRecTaskWoken || XTXTaskWoken); -#endif -} - -/* Set up the MAC interface duplex */ void lpc_emac_set_duplex(int full_duplex) { - if (full_duplex) { + if (full_duplex) LPC_ETHERNET->MAC_CONFIG |= MAC_CFG_DM; - } - else { + else LPC_ETHERNET->MAC_CONFIG &= ~MAC_CFG_DM; - } } -/* Set up the MAC interface speed */ +/** + * This function provides a method for the PHY to setup the EMAC + * for the PHY negotiated bit rate. + * + * \param[in] mbs_100 0 = 10mbs mode, 1 = 100mbs mode + */ void lpc_emac_set_speed(int mbs_100) { - if (mbs_100) { + if (mbs_100) LPC_ETHERNET->MAC_CONFIG |= MAC_CFG_FES; - } - else { + else LPC_ETHERNET->MAC_CONFIG &= ~MAC_CFG_FES; - } } -/* LWIP 18xx/43xx EMAC initialization function */ +/** + * This function is the ethernet packet send function. It calls + * etharp_output after checking link status. + * + * \param[in] netif the lwip network interface structure for this lpc_enetif + * \param[in] q Pointer to pbug to send + * \param[in] ipaddr IP address + * \return ERR_OK or error code + */ +err_t lpc_etharp_output(struct netif *netif, struct pbuf *q, + ip_addr_t *ipaddr) +{ + /* Only send packet is link is up */ + if (netif->flags & NETIF_FLAG_LINK_UP) + return etharp_output(netif, q, ipaddr); + + return ERR_CONN; +} + +/** + * Should be called at the beginning of the program to set up the + * network interface. + * + * This function should be passed as a parameter to netif_add(). + * + * \param[in] netif the lwip network interface structure for this lpc_enetif + * \return ERR_OK if the loopif is initialized + * ERR_MEM if private data couldn't be allocated + * any other err_t on error + */ err_t lpc_enetif_init(struct netif *netif) { err_t err; - extern void Board_ENET_GetMacADDR(u8_t *mcaddr); LWIP_ASSERT("netif != NULL", (netif != NULL)); - + lpc_enetdata.netif = netif; /* set MAC hardware address */ - Board_ENET_GetMacADDR(netif->hwaddr); + boardGetMACaddr(netif->hwaddr); netif->hwaddr_len = ETHARP_HWADDR_LEN; - /* maximum transfer unit */ + /* maximum transfer unit */ netif->mtu = 1500; /* device capabilities */ netif->flags = NETIF_FLAG_BROADCAST | NETIF_FLAG_ETHARP | NETIF_FLAG_UP | - NETIF_FLAG_ETHERNET; + NETIF_FLAG_ETHERNET; /* Initialize the hardware */ netif->state = &lpc_enetdata; err = low_level_init(netif); - if (err != ERR_OK) { + if (err != ERR_OK) return err; - } #if LWIP_NETIF_HOSTNAME /* Initialize interface hostname */ @@ -908,9 +1059,9 @@ err_t lpc_enetif_init(struct netif *netif) /* For FreeRTOS, start tasks */ #if NO_SYS == 0 lpc_enetdata.xTXDCountSem = xSemaphoreCreateCounting(LPC_NUM_BUFF_TXDESCS, - LPC_NUM_BUFF_TXDESCS); + LPC_NUM_BUFF_TXDESCS); LWIP_ASSERT("xTXDCountSem creation error", - (lpc_enetdata.xTXDCountSem != NULL)); + (lpc_enetdata.xTXDCountSem != NULL)); err = sys_mutex_new(&lpc_enetdata.TXLockMutex); LWIP_ASSERT("TXLockMutex creation error", (err == ERR_OK)); @@ -919,13 +1070,13 @@ err_t lpc_enetif_init(struct netif *netif) err = sys_sem_new(&lpc_enetdata.RxSem, 0); LWIP_ASSERT("RxSem creation error", (err == ERR_OK)); sys_thread_new("receive_thread", vPacketReceiveTask, netif->state, - DEFAULT_THREAD_STACKSIZE, tskRECPKT_PRIORITY); + DEFAULT_THREAD_STACKSIZE, tskRECPKT_PRIORITY); /* Transmit cleanup task */ err = sys_sem_new(&lpc_enetdata.TxCleanSem, 0); LWIP_ASSERT("TxCleanSem creation error", (err == ERR_OK)); sys_thread_new("txclean_thread", vTransmitCleanupTask, netif->state, - DEFAULT_THREAD_STACKSIZE, tskTXCLEAN_PRIORITY); + DEFAULT_THREAD_STACKSIZE, tskTXCLEAN_PRIORITY); #endif return ERR_OK; @@ -934,3 +1085,5 @@ err_t lpc_enetif_init(struct netif *netif) /** * @} */ + +/* --------------------------------- End Of File ------------------------------ */ diff --git a/vendor/lwip/lpclwip/arch/lpc18xx_43xx_emac.h b/vendor/lwip/lpclwip/arch/lpc18xx_43xx_emac.h index b255bda05..1636b2874 100644 --- a/vendor/lwip/lpclwip/arch/lpc18xx_43xx_emac.h +++ b/vendor/lwip/lpclwip/arch/lpc18xx_43xx_emac.h @@ -1,36 +1,30 @@ -/* - * @brief LPC18xx/43xx LWIP EMAC driver - * - * @note - * Copyright(C) NXP Semiconductors, 2012 - * All rights reserved. - * - * @par - * Software that is described herein is for illustrative purposes only - * which provides customers with programming information regarding the - * LPC products. This software is supplied "AS IS" without any warranties of - * any kind, and NXP Semiconductors and its licensor disclaim any and - * all warranties, express or implied, including all implied warranties of - * merchantability, fitness for a particular purpose and non-infringement of - * intellectual property rights. NXP Semiconductors assumes no responsibility - * or liability for the use of the software, conveys no license or rights under any - * patent, copyright, mask work right, or any other intellectual property rights in - * or to any products. NXP Semiconductors reserves the right to make changes - * in the software without notification. NXP Semiconductors also makes no - * representation or warranty that such application will be suitable for the - * specified use without further testing or modification. - * - * @par - * Permission to use, copy, modify, and distribute this software and its - * documentation is hereby granted, under NXP Semiconductors' and its - * licensor's relevant copyrights in the software, without fee, provided that it - * is used in conjunction with NXP Semiconductors microcontrollers. This - * copyright, permission, and disclaimer notice must appear in all copies of - * this code. - */ +/********************************************************************** +* $Id$ lpc18xx_43xx_emac.h 2011-11-20 +*//** +* @file lpc18xx_43xx_emac.h +* @brief LPC18xx/43xx ethernet driver header file for LWIP +* @version 1.0 +* @date 20. Nov. 2011 +* @author NXP MCU SW Application Team +* +* Copyright(C) 2011, NXP Semiconductor +* All rights reserved. +* +*********************************************************************** +* Software that is described herein is for illustrative purposes only +* which provides customers with programming information regarding the +* products. This software is supplied "AS IS" without any warranties. +* NXP Semiconductors assumes no responsibility or liability for the +* use of the software, conveys no license or title under any patent, +* copyright, or mask work right to the product. NXP Semiconductors +* reserves the right to make changes in the software without +* notification. NXP Semiconductors also make no representation or +* warranty that such application will be suitable for the specified +* use without further testing or modification. +**********************************************************************/ -#ifndef __LPC18XX_43XX_EMAC_H_ -#define __LPC18XX_43XX_EMAC_H_ +#ifndef __LPC18XX_43XX_EMAC_H +#define __LPC18XX_43XX_EMAC_H #include "lwip/opt.h" #include "lwip/netif.h" @@ -40,89 +34,18 @@ extern "C" { #endif -/** @defgroup NET_LWIP_LPC18XX43XX_EMAC_DRIVER 18xx/43xx EMAC driver for LWIP - * @ingroup NET_LWIP - * This is the LPC18xx/43xx EMAC driver for LWIP. This driver supports both - * RTOS-based and no-RTOS operation with LWIP. WHen using an RTOS, several - * threads will be created for handling RX and TX packet fucntions. - * - * Note that some LWIP examples may not necessarily use all the provided - * LWIP driver functions or may contain overriden versions of the functions. - * (For example, PHY drives may have their own implementation of the MII - * read/write functions). - * @{ - */ - -/** - * @brief Attempt to read a packet from the EMAC interface - * @param netif : lwip network interface structure pointer - * @return Nothing - */ +/* These functions are only visible when not using an RTOS */ +#if NO_SYS == 1 void lpc_enetif_input(struct netif *netif); - -/** - * @brief Attempt to allocate and requeue a new pbuf for RX - * @param netif : lwip network interface structure pointer - * @return The number of new descriptors queued - */ -s32_t lpc_rx_queue(struct netif *netif); - -/** - * @brief Polls if an available TX descriptor is ready - * @param netif : lwip network interface structure pointer - * @return 0 if no descriptors are read, or >0 - * @note Can be used to determine if the low level transmit function will block - */ s32_t lpc_tx_ready(struct netif *netif); - -/** - * @brief Call for freeing TX buffers that are complete - * @param netif : lwip network interface structure pointer - * @return Nothing - */ +s32_t lpc_rx_queue(struct netif *netif); void lpc_tx_reclaim(struct netif *netif); +#endif -/** - * @brief LWIP 18xx/43xx EMAC initialization function - * @param netif : lwip network interface structure pointer - * @return ERR_OK if the loopif is initialized, or ERR_* on other errors - * @note Should be called at the beginning of the program to set up the - * network interface. This function should be passed as a parameter to - * netif_add(). - */ err_t lpc_enetif_init(struct netif *netif); -/** - * @brief Set up the MAC interface duplex - * @param full_duplex : 0 = half duplex, 1 = full duplex - * @return Nothing - * @note This function provides a method for the PHY to setup the EMAC - * for the PHY negotiated duplex mode. - */ -void lpc_emac_set_duplex(int full_duplex); - -/** - * @brief Set up the MAC interface speed - * @param mbs_100 : 0 = 10mbs mode, 1 = 100mbs mode - * @return Nothing - * @note This function provides a method for the PHY to setup the EMAC - * for the PHY negotiated bit rate. - */ -void lpc_emac_set_speed(int mbs_100); - -/** - * @brief Millisecond Delay function - * @param ms : Milliseconds to wait - * @return None - */ -extern void msDelay(uint32_t ms); - #ifdef __cplusplus } #endif -/** - * @} - */ - -#endif /* __LPC18XX_43XX_EMAC_H_ */ +#endif /* __LPC18XX_43XX_EMAC_H */ diff --git a/vendor/lwip/lpclwip/arch/lpc18xx_43xx_mac_regs.h b/vendor/lwip/lpclwip/arch/lpc18xx_43xx_mac_regs.h new file mode 100644 index 000000000..a9564f71e --- /dev/null +++ b/vendor/lwip/lpclwip/arch/lpc18xx_43xx_mac_regs.h @@ -0,0 +1,359 @@ +/********************************************************************** +* $Id$ lpc43xx_mac.h 2011-06-02 +*//** +* @file lpc43xx_mac.h +* @brief Contains all functions support for the MAC peripheral +* @version 1.0 +* @date 02. June. 2011 +* @author NXP MCU SW Application Team +* +* Copyright(C) 2011, NXP Semiconductor +* All rights reserved. +* +*********************************************************************** +* Software that is described herein is for illustrative purposes only +* which provides customers with programming information regarding the +* products. This software is supplied "AS IS" without any warranties. +* NXP Semiconductors assumes no responsibility or liability for the +* use of the software, conveys no license or title under any patent, +* copyright, or mask work right to the product. NXP Semiconductors +* reserves the right to make changes in the software without +* notification. NXP Semiconductors also make no representation or +* warranty that such application will be suitable for the specified +* use without further testing or modification. +* Permission to use, copy, modify, and distribute this software and its +* documentation is hereby granted, under NXP Semiconductors� +* relevant copyright in the software, without fee, provided that it +* is used in conjunction with NXP Semiconductors microcontrollers. This +* copyright, permission, and disclaimer notice must appear in all copies of +* this code. +**********************************************************************/ + +#ifndef __lpc18xx_lpc43xx_mac_regs_H_ +#define __lpc18xx_lpc43xx_mac_regs_H_ + +#include "lpc_types.h" + +#ifdef __cplusplus +extern "C" +{ +#endif + +/** @defgroup lwip18xx_43xx_emac_regs lpc18xx/43xx EMAC registers + * @ingroup lwip18xx_43xx_emac_DRIVER + * + * Variants of these constants and macros exist in the lpc18xx or + * lpc43xx files. These are signficantly shorter and make the code + * easier to read. + * + * @{ + */ + +/* MAC_CONFIG register bit defines */ +#define MAC_CFG_RE (1 << 2) /*!< Receiver enable */ +#define MAC_CFG_TE (1 << 3) /*!< Transmitter Enable */ +#define MAC_CFG_DF (1 << 4) /*!< Deferral Check */ +#define MAC_CFG_BL(n) ((n) << 5) /*!< Back-Off Limit */ +#define MAC_CFG_ACS (1 << 7) /*!< Automatic Pad/CRC Stripping */ +#define MAC_CFG_LUD (1 << 8) /*!< Link Up/Down, 1 = up */ +#define MAC_CFG_DR (1 << 9) /*!< Disable Retry */ +#define MAC_CFG_IPC (1 << 10) /*!< Checksum Offload */ +#define MAC_CFG_DM (1 << 11) /*!< Duplex Mode, 1 = full, 0 = half */ +#define MAC_CFG_LM (1 << 12) /*!< Loopback Mode */ +#define MAC_CFG_DO (1 << 13) /*!< Disable Receive Own */ +#define MAC_CFG_FES (1 << 14) /*!< Speed, 1 = 100Mbps, 0 = 10Mbos */ +#define MAC_CFG_PS (1 << 15) /*!< Port select, must always be 1 */ +#define MAC_CFG_DCRS (1 << 16) /*!< Disable carrier sense during transmission */ +#define MAC_CFG_IFG(n) ((n) << 17) /*!< Inter-frame gap, 40..96, n incs by 8 */ +#define MAC_CFG_JE (1 << 20) /*!< Jumbo Frame Enable */ +#define MAC_CFG_JD (1 << 22) /*!< Jabber Disable */ +#define MAC_CFG_WD (1 << 23) /*!< Watchdog Disable */ + +/* MAC_FRAME_FILTER register bit defines */ +#define MAC_FF_PR (1 << 0) /*!< Promiscuous Mode */ +#define MAC_FF_DAIF (1 << 3) /*!< DA Inverse Filtering */ +#define MAC_FF_PM (1 << 4) /*!< Pass All Multicast */ +#define MAC_FF_DBF (1 << 5) /*!< Disable Broadcast Frames */ +#define MAC_FF_PCF(n) ((n) << 6) /*!< Pass Control Frames, n = see user manual */ +#define MAC_FF_SAIF (1 << 8) /*!< SA Inverse Filtering */ +#define MAC_FF_SAF (1 << 9) /*!< Source Address Filter Enable */ +#define MAC_FF_RA (1UL << 31) /*!< Receive all */ + +/* MAC_MII_ADDR register bit defines */ +#define MAC_MIIA_GB (1 << 0) /*!< MII busy */ +#define MAC_MIIA_W (1 << 1) /*!< MII write */ +#define MAC_MIIA_CR(n) ((n) << 2) /*!< CSR clock range, n = see manual */ +#define MAC_MIIA_GR(n) ((n) << 6) /*!< MII register. n = 0..31 */ +#define MAC_MIIA_PA(n) ((n) << 11) /*!< Physical layer address, n = 0..31 */ + +/* MAC_MII_DATA register bit defines */ +#define MAC_MIID_GDMSK (0xFFFF) /*!< MII data mask */ + +/* MAC_FLOW_CONTROL register bit defines */ +#define MAC_FC_FCB (1 << 0) /*!< Flow Control Busy/Backpressure Activate */ +#define MAC_FC_TFE (1 << 1) /*!< Transmit Flow Control Enable */ +#define MAC_FC_RFE (1 << 2) /*!< Receive Flow Control Enable */ +#define MAC_FC_UP (1 << 3) /*!< Unicast Pause Frame Detect */ +#define MAC_FC_PLT(n) ((n) << 4) /*!< Pause Low Threshold, n = see manual */ +#define MAC_FC_DZPQ (1 << 7) /*!< Disable Zero-Quanta Pause */ +#define MAC_FC_PT(n) ((n) << 16) /*!< Pause time */ + +/* MAC_VLAN_TAG register bit defines */ +#define MAC_VT_VL(n) ((n) << 0) /*!< VLAN Tag Identifier for Receive Frames */ +#define MAC_VT_ETC (1 << 7) /*!< Enable 12-Bit VLAN Tag Comparison */ + +/* MAC_DEBUG register bit defines */ + +/* MAC_PMT_CTRL_STAT register bit defines */ +#define MAC_PMT_PD (1 << 0) /*!< Power-down */ +#define MAC_PMT_MPE (1 << 1) /*!< Magic packet enable */ +#define MAC_PMT_WFE (1 << 2) /*!< Wake-up frame enable */ +#define MAC_PMT_MPR (1 << 5) /*!< Magic Packet Received */ +#define MAC_PMT_WFR (1 << 6) /*!< Wake-up Frame Received */ +#define MAC_PMT_GU (1 << 9) /*!< Global Unicast */ +#define MAC_PMT_WFFRPR (1UL << 31) /*!< Wake-up Frame Filter Register Pointer Reset */ + +/* MAC_INTR_MASK register bit defines */ +#define MAC_IM_PMT (1 << 3) /*!< PMT Interrupt Mask */ + +/* MAC_ADDR0_HIGH register bit defines */ +#define MAC_ADRH_MO (1UL << 31) /*!< Always 1 when writing register */ + +/* MAC_ADDR0_HIGH register bit defines */ +#define MAC_ADRH_MO (1UL << 31) /*!< Always 1 when writing register */ + +/* MAC_TIMESTAMP register bit defines */ +#define MAC_TS_TSENA (1 << 0) /*!< Time Stamp Enable */ +#define MAC_TS_TSCFUP (1 << 1) /*!< Time Stamp Fine or Coarse Update */ +#define MAC_TS_TSINIT (1 << 2) /*!< Time Stamp Initialize */ +#define MAC_TS_TSUPDT (1 << 3) /*!< Time Stamp Update */ +#define MAC_TS_TSTRIG (1 << 4) /*!< Time Stamp Interrupt Trigger Enable */ +#define MAC_TS_TSADDR (1 << 5) /*!< Addend Reg Update */ +#define MAC_TS_TSENAL (1 << 8) /*!< Enable Time Stamp for All Frames */ +#define MAC_TS_TSCTRL (1 << 9) /*!< Time Stamp Digital or Binary rollover control */ +#define MAC_TS_TSVER2 (1 << 10) /*!< Enable PTP packet snooping for version 2 format */ +#define MAC_TS_TSIPENA (1 << 11) /*!< Enable Time Stamp Snapshot for PTP over Ethernet frames */ +#define MAC_TS_TSIPV6E (1 << 12) /*!< Enable Time Stamp Snapshot for IPv6 frames */ +#define MAC_TS_TSIPV4E (1 << 13) /*!< Enable Time Stamp Snapshot for IPv4 frames */ +#define MAC_TS_TSEVNT (1 << 14) /*!< Enable Time Stamp Snapshot for Event Messages */ +#define MAC_TS_TSMSTR (1 << 15) /*!< Enable Snapshot for Messages Relevant to Master */ +#define MAC_TS_TSCLKT(n) ((n) << 16) /*!< Select the type of clock node, n = see menual */ +#define MAC_TS_TSENMA (1 << 18) /*!< Enable MAC address for PTP frame filtering */ + +/* DMA_BUS_MODE register bit defines */ +#define DMA_BM_SWR (1 << 0) /*!< Software reset */ +#define DMA_BM_DA (1 << 1) /*!< DMA arbitration scheme, 1 = TX has priority over TX */ +#define DMA_BM_DSL(n) ((n) << 2) /*!< Descriptor skip length, n = see manual */ +#define DMA_BM_ATDS (1 << 7) /*!< Alternate (Enhanced) descriptor size */ +#define DMA_BM_PBL(n) ((n) << 8) /*!< Programmable burst length, n = see manual */ +#define DMA_BM_PR(n) ((n) << 14) /*!< Rx-to-Tx priority ratio, n = see manual */ +#define DMA_BM_FB (1 << 16) /*!< Fixed burst */ +#define DMA_BM_RPBL(n) ((n) << 17) /*!< RxDMA PBL, n = see manual */ +#define DMA_BM_USP (1 << 23) /*!< Use separate PBL */ +#define DMA_BM_PBL8X (1 << 24) /*!< 8 x PBL mode */ +#define DMA_BM_AAL (1 << 25) /*!< Address-aligned beats */ +#define DMA_BM_MB (1 << 26) /*!< Mixed burst */ +#define DMA_BM_TXPR (1 << 27) /*!< Transmit DMA has higher priority than receive DMA */ + +/* DMA_STAT register bit defines */ +#define DMA_ST_TI (1 << 0) /*!< Transmit interrupt */ +#define DMA_ST_TPS (1 << 1) /*!< Transmit process stopped */ +#define DMA_ST_TU (1 << 2) /*!< Transmit buffer unavailable */ +#define DMA_ST_TJT (1 << 3) /*!< Transmit jabber timeout */ +#define DMA_ST_OVF (1 << 4) /*!< Receive overflow */ +#define DMA_ST_UNF (1 << 5) /*!< Transmit underflow */ +#define DMA_ST_RI (1 << 6) /*!< Receive interrupt */ +#define DMA_ST_RU (1 << 7) /*!< Receive buffer unavailable */ +#define DMA_ST_RPS (1 << 8) /*!< Received process stopped */ +#define DMA_ST_RWT (1 << 9) /*!< Receive watchdog timeout */ +#define DMA_ST_ETI (1 << 10) /*!< Early transmit interrupt */ +#define DMA_ST_FBI (1 << 13) /*!< Fatal bus error interrupt */ +#define DMA_ST_ERI (1 << 14) /*!< Early receive interrupt */ +#define DMA_ST_AIE (1 << 15) /*!< Abnormal interrupt summary */ +#define DMA_ST_NIS (1 << 16) /*!< Normal interrupt summary */ +#define DMA_ST_ALL (0x1E7FF) /*!< All interrupts */ + +/* DMA_OP_MODE register bit defines */ +#define DMA_OM_SR (1 << 1) /*!< Start/stop receive */ +#define DMA_OM_OSF (1 << 2) /*!< Operate on second frame */ +#define DMA_OM_RTC(n) ((n) << 3) /*!< Receive threshold control, n = see manual */ +#define DMA_OM_FUF (1 << 6) /*!< Forward undersized good frames */ +#define DMA_OM_FEF (1 << 7) /*!< Forward error frames */ +#define DMA_OM_ST (1 << 13) /*!< Start/Stop Transmission Command */ +#define DMA_OM_TTC(n) ((n) << 14) /*!< Transmit threshold control, n = see manual */ +#define DMA_OM_FTF (1 << 20) /*!< Flush transmit FIFO */ +#define DMA_OM_TSF (1 << 21) /*!< Transmit store and forward */ +#define DMA_OM_DFF (1 << 24) /*!< Disable flushing of received frames */ +#define DMA_OM_RSF (1 << 25) /*!< Receive store and forward */ +#define DMA_OM_DT (1 << 26) /*!< Disable Dropping of TCP/IP Checksum Error Frames */ + +/* DMA_INT_EN register bit defines */ +#define DMA_IE_TIE (1 << 0) /*!< Transmit interrupt enable */ +#define DMA_IE_TSE (1 << 1) /*!< Transmit stopped enable */ +#define DMA_IE_TUE (1 << 2) /*!< Transmit buffer unavailable enable */ +#define DMA_IE_TJE (1 << 3) /*!< Transmit jabber timeout enable */ +#define DMA_IE_OVE (1 << 4) /*!< Overflow interrupt enable */ +#define DMA_IE_UNE (1 << 5) /*!< Underflow interrupt enable */ +#define DMA_IE_RIE (1 << 6) /*!< Receive interrupt enable */ +#define DMA_IE_RUE (1 << 7) /*!< Receive buffer unavailable enable */ +#define DMA_IE_RSE (1 << 8) /*!< Received stopped enable */ +#define DMA_IE_RWE (1 << 9) /*!< Receive watchdog timeout enable */ +#define DMA_IE_ETE (1 << 10) /*!< Early transmit interrupt enable */ +#define DMA_IE_FBE (1 << 13) /*!< Fatal bus error enable */ +#define DMA_IE_ERE (1 << 14) /*!< Early receive interrupt enable */ +#define DMA_IE_AIE (1 << 15) /*!< Abnormal interrupt summary enable */ +#define DMA_IE_NIE (1 << 16) /*!< Normal interrupt summary enable */ + +/* DMA_MFRM_BUFOF register bit defines */ +#define DMA_MFRM_FMCMSK (0xFFFF) /*!< Number of frames missed mask */ +#define DMA_MFRM_OC (1 << 16) /*!< Overflow bit for missed frame counter */ +#define DMA_MFRM_FMA(n) (((n) & 0x0FFE0000) >> 17) /*!< Number of frames missed by the application mask/shift */ +#define DMA_MFRM_OF (1 << 28) /*!< Overflow bit for FIFO overflow counter */ + +/* Common TRAN_DESC_T and TRAN_DESC_ENH_T CTRLSTAT field bit defines */ +#define TDES_DB (1 << 0) /*!< Deferred Bit */ +#define TDES_UF (1 << 1) /*!< Underflow Error */ +#define TDES_ED (1 << 2) /*!< Excessive Deferral */ +#define TDES_CCMSK(n) (((n) & 0x000000F0) >> 3) /*!< CC: Collision Count (Status field) mask and shift */ +#define TDES_VF (1 << 7) /*!< VLAN Frame */ +#define TDES_EC (1 << 8) /*!< Excessive Collision */ +#define TDES_LC (1 << 9) /*!< Late Collision */ +#define TDES_NC (1 << 10) /*!< No Carrier */ +#define TDES_LCAR (1 << 11) /*!< Loss of Carrier */ +#define TDES_IPE (1 << 12) /*!< IP Payload Error */ +#define TDES_FF (1 << 13) /*!< Frame Flushed */ +#define TDES_JT (1 << 14) /*!< Jabber Timeout */ +#define TDES_ES (1 << 15) /*!< Error Summary */ +#define TDES_IHE (1 << 16) /*!< IP Header Error */ +#define TDES_TTSS (1 << 17) /*!< Transmit Timestamp Status */ +#define TDES_OWN (1UL << 31) /*!< Own Bit */ + +/* TRAN_DESC_ENH_T only CTRLSTAT field bit defines */ +#define TDES_ENH_IC (1UL << 30) /*!< Interrupt on Completion, enhanced descriptor */ +#define TDES_ENH_LS (1 << 29) /*!< Last Segment, enhanced descriptor */ +#define TDES_ENH_FS (1 << 28) /*!< First Segment, enhanced descriptor */ +#define TDES_ENH_DC (1 << 27) /*!< Disable CRC, enhanced descriptor */ +#define TDES_ENH_DP (1 << 26) /*!< Disable Pad, enhanced descriptor */ +#define TDES_ENH_TTSE (1 << 25) /*!< Transmit Timestamp Enable, enhanced descriptor */ +#define TDES_ENH_CIC(n) ((n) << 22) /*!< Checksum Insertion Control, enhanced descriptor */ +#define TDES_ENH_TER (1 << 21) /*!< Transmit End of Ring, enhanced descriptor */ +#define TDES_ENH_TCH (1 << 20) /*!< Second Address Chained, enhanced descriptor */ + +/* TRAN_DESC_T only BSIZE field bit defines */ +#define TDES_NORM_IC (1UL << 31) /*!< Interrupt on Completion, normal descriptor */ +#define TDES_NORM_FS (1 << 30) /*!< First Segment, normal descriptor */ +#define TDES_NORM_LS (1 << 29) /*!< Last Segment, normal descriptor */ +#define TDES_NORM_CIC(n) ((n) << 27) /*!< Checksum Insertion Control, normal descriptor */ +#define TDES_NORM_DC (1 << 26) /*!< Disable CRC, normal descriptor */ +#define TDES_NORM_TER (1 << 25) /*!< Transmit End of Ring, normal descriptor */ +#define TDES_NORM_TCH (1 << 24) /*!< Second Address Chained, normal descriptor */ +#define TDES_NORM_DP (1 << 23) /*!< Disable Pad, normal descriptor */ +#define TDES_NORM_TTSE (1 << 22) /*!< Transmit Timestamp Enable, normal descriptor */ +#define TDES_NORM_BS2(n) (((n) & 0x3FF) << 11) /*!< Buffer 2 size, normal descriptor */ +#define TDES_NORM_BS1(n) (((n) & 0x3FF) << 0) /*!< Buffer 1 size, normal descriptor */ + +/* TRAN_DESC_ENH_T only BSIZE field bit defines */ +#define TDES_ENH_BS2(n) (((n) & 0xFFF) << 16) /*!< Buffer 2 size, enhanced descriptor */ +#define TDES_ENH_BS1(n) (((n) & 0xFFF) << 0) /*!< Buffer 1 size, enhanced descriptor */ + +/* Common REC_DESC_T and REC_DESC_ENH_T STATUS field bit defines */ +#define RDES_ESA (1 << 0) /*!< Extended Status Available/Rx MAC Address */ +#define RDES_CE (1 << 1) /*!< CRC Error */ +#define RDES_DRE (1 << 2) /*!< Dribble Bit Error */ +#define RDES_RE (1 << 3) /*!< Receive Error */ +#define RDES_RWT (1 << 4) /*!< Receive Watchdog Timeout */ +#define RDES_FT (1 << 5) /*!< Frame Type */ +#define RDES_LC (1 << 6) /*!< Late Collision */ +#define RDES_TSA (1 << 7) /*!< Timestamp Available/IP Checksum Error (Type1) /Giant Frame */ +#define RDES_LS (1 << 8) /*!< Last Descriptor */ +#define RDES_FS (1 << 9) /*!< First Descriptor */ +#define RDES_VLAN (1 << 10) /*!< VLAN Tag */ +#define RDES_OE (1 << 11) /*!< Overflow Error */ +#define RDES_LE (1 << 12) /*!< Length Error */ +#define RDES_SAF (1 << 13) /*!< Source Address Filter Fail */ +#define RDES_DE (1 << 14) /*!< Descriptor Error */ +#define RDES_ES (1 << 15) /*!< ES: Error Summary */ +#define RDES_FLMSK(n) (((n) & 0x3FFF0000) >> 16) /*!< Frame Length mask and shift */ +#define RDES_AFM (1 << 30) /*!< Destination Address Filter Fail */ +#define RDES_OWN (1UL << 31) /*!< Own Bit */ + +/* Common REC_DESC_T and REC_DESC_ENH_T CTRL field bit defines */ +#define RDES_DINT (1UL << 31) /*!< Disable interrupt on completion */ + +/* REC_DESC_T pnly CTRL field bit defines */ +#define RDES_NORM_RER (1 << 25) /*!< Receive End of Ring, normal descriptor */ +#define RDES_NORM_RCH (1 << 24) /*!< Second Address Chained, normal descriptor */ +#define RDES_NORM_BS2(n) (((n) & 0x3FF) << 11) /*!< Buffer 2 size, normal descriptor */ +#define RDES_NORM_BS1(n) (((n) & 0x3FF) << 0) /*!< Buffer 1 size, normal descriptor */ + +/* REC_DESC_ENH_T only CTRL field bit defines */ +#define RDES_ENH_RER (1 << 15) /*!< Receive End of Ring, enhanced descriptor */ +#define RDES_ENH_RCH (1 << 14) /*!< Second Address Chained, enhanced descriptor */ +#define RDES_ENH_BS2(n) (((n) & 0xFFF) << 16) /*!< Buffer 2 size, enhanced descriptor */ +#define RDES_ENH_BS1(n) (((n) & 0xFFF) << 0) /*!< Buffer 1 size, enhanced descriptor */ + +/* REC_DESC_ENH_T only EXTSTAT field bit defines */ +#define RDES_ENH_IPPL(n) (((n) & 0x7) >> 2) /*!< IP Payload Type mask and shift, enhanced descripto */ +#define RDES_ENH_IPHE (1 << 3) /*!< IP Header Error, enhanced descripto */ +#define RDES_ENH_IPPLE (1 << 4) /*!< IP Payload Error, enhanced descripto */ +#define RDES_ENH_IPCSB (1 << 5) /*!< IP Checksum Bypassed, enhanced descripto */ +#define RDES_ENH_IPV4 (1 << 6) /*!< IPv4 Packet Received, enhanced descripto */ +#define RDES_ENH_IPV6 (1 << 7) /*!< IPv6 Packet Received, enhanced descripto */ +#define RDES_ENH_MTMSK(n) (((n) & 0xF) >> 8) /*!< Message Type mask and shift, enhanced descripto */ + +/* Maximum size of an ethernet buffer */ +#define EMAC_ETH_MAX_FLEN (1536) + +/* Structure of a transmit descriptor (without timestamp) */ +typedef struct +{ + __IO uint32_t CTRLSTAT; /*!< TDES control and status word */ + __IO uint32_t BSIZE; /*!< Buffer 1/2 byte counts */ + __IO uint32_t B1ADD; /*!< Buffer 1 address */ + __IO uint32_t B2ADD; /*!< Buffer 2 or next descriptor address */ +} TRAN_DESC_T; + +/* Structure of a enhanced transmit descriptor (with timestamp) */ +typedef struct +{ + __IO uint32_t CTRLSTAT; /*!< TDES control and status word */ + __IO uint32_t BSIZE; /*!< Buffer 1/2 byte counts */ + __IO uint32_t B1ADD; /*!< Buffer 1 address */ + __IO uint32_t B2ADD; /*!< Buffer 2 or next descriptor address */ + __IO uint32_t TDES4; /*!< Reserved */ + __IO uint32_t TDES5; /*!< Reserved */ + __IO uint32_t TTSL; /*!< Timestamp value low */ + __IO uint32_t TTSH; /*!< Timestamp value high */ +} TRAN_DESC_ENH_T; + +/* Structure of a receive descriptor (without timestamp) */ +typedef struct +{ + __IO uint32_t STATUS; /*!< RDES status word */ + __IO uint32_t CTRL; /*!< Buffer 1/2 byte counts and control */ + __IO uint32_t B1ADD; /*!< Buffer 1 address */ + __IO uint32_t B2ADD; /*!< Buffer 2 or next descriptor address */ +} REC_DESC_T; + +/* Structure of a enhanced receive descriptor (with timestamp) */ +typedef struct +{ + __IO uint32_t STATUS; /*!< RDES status word */ + __IO uint32_t CTRL; /*!< Buffer 1/2 byte counts */ + __IO uint32_t B1ADD; /*!< Buffer 1 address */ + __IO uint32_t B2ADD; /*!< Buffer 2 or next descriptor address */ + __IO uint32_t EXTSTAT; /*!< Extended Status */ + __IO uint32_t RDES5; /*!< Reserved */ + __IO uint32_t RTSL; /*!< Timestamp value low */ + __IO uint32_t RTSH; /*!< Timestamp value high */ +} REC_DESC_ENH_T; + +/** + * @} + */ + +#ifdef __cplusplus +} +#endif + +#endif /* __lpc18xx_lpc43xx_mac_regs_H_ */ diff --git a/vendor/lwip/lpclwip/arch/lpc18xx_43xx_systick_arch.c b/vendor/lwip/lpclwip/arch/lpc18xx_43xx_systick_arch.c index 65791c5d3..c2bf0933f 100644 --- a/vendor/lwip/lpclwip/arch/lpc18xx_43xx_systick_arch.c +++ b/vendor/lwip/lpclwip/arch/lpc18xx_43xx_systick_arch.c @@ -1,139 +1,71 @@ /********************************************************************** - * @brief Setups up the LWIP timebase (tick) - * - * @note - * Copyright(C) NXP Semiconductors, 2012 - * All rights reserved. - * - * @par - * Software that is described herein is for illustrative purposes only - * which provides customers with programming information regarding the - * LPC products. This software is supplied "AS IS" without any warranties of - * any kind, and NXP Semiconductors and its licensor disclaim any and - * all warranties, express or implied, including all implied warranties of - * merchantability, fitness for a particular purpose and non-infringement of - * intellectual property rights. NXP Semiconductors assumes no responsibility - * or liability for the use of the software, conveys no license or rights under any - * patent, copyright, mask work right, or any other intellectual property rights in - * or to any products. NXP Semiconductors reserves the right to make changes - * in the software without notification. NXP Semiconductors also makes no - * representation or warranty that such application will be suitable for the - * specified use without further testing or modification. - * - * @par - * Permission to use, copy, modify, and distribute this software and its - * documentation is hereby granted, under NXP Semiconductors' and its - * licensor's relevant copyrights in the software, without fee, provided that it - * is used in conjunction with NXP Semiconductors microcontrollers. This - * copyright, permission, and disclaimer notice must appear in all copies of - * this code. - */ +* $Id$ lpc18xx_43xx_systick_arch.c 2011-11-20 +*//** +* @file lpc18xx_43xx_systick_arch.c +* @brief Setups up the system tick to generate a reference timebase +* @version 1.0 +* @date 20. Nov. 2011 +* @author NXP MCU SW Application Team +* +* Copyright(C) 2011, NXP Semiconductor +* All rights reserved. +* +*********************************************************************** +* Software that is described herein is for illustrative purposes only +* which provides customers with programming information regarding the +* products. This software is supplied "AS IS" without any warranties. +* NXP Semiconductors assumes no responsibility or liability for the +* use of the software, conveys no license or title under any patent, +* copyright, or mask work right to the product. NXP Semiconductors +* reserves the right to make changes in the software without +* notification. NXP Semiconductors also make no representation or +* warranty that such application will be suitable for the specified +* use without further testing or modification. +**********************************************************************/ #include "lwip/opt.h" #if NO_SYS == 1 -#include "chip.h" +#ifdef LPC43XX +#include "lpc43xx_cgu.h" +#else +#ifdef LPC43XX +#include "lpc18xx_cgu.h" +#else +#error LPC18XX or LPC43XX for target system not defined! +#endif +#endif #include "lpc_arch.h" -/** @ingroup NET_LWIP_ARCH +/** @defgroup LPC18xx_43xx_systick LPC18xx_43xx LWIP (standalone) timer base + * @ingroup LPC18xx_43xx * @{ */ -/***************************************************************************** - * Private types/enumerations/variables - ****************************************************************************/ - -/* Saved reference period foe standalone mode */ +/* Saved reference period */ static uint32_t saved_period; - -#if (defined(CHIP_LPC43XX) && defined(CORE_M0)) - -#define RITIMER_IRQn_PRI (255) - -/* RITimer Reload value */ -static uint32_t reload_val; -#endif - + /* Saved total time in mS since timer was enabled */ static volatile u32_t systick_timems; -/***************************************************************************** - * Public types/enumerations/variables - ****************************************************************************/ - -/* Current system clock rate, mainly used for sysTick */ -extern uint32_t SystemCoreClock; - -/***************************************************************************** - * Private functions - ****************************************************************************/ - -/***************************************************************************** - * Public functions - ****************************************************************************/ - -#if (defined(CHIP_LPC43XX) && defined(CORE_M0)) - -/* Enable LWIP tick and interrupt */ +/* Enable systick rate and interrupt */ void SysTick_Enable(uint32_t period) { saved_period = period; - - /* Clear any pending interrupt */ - Chip_RIT_ClearInt(LPC_RITIMER); - - /* Calculate reload value */ - reload_val = ( SystemCoreClock / ( 1000 / period ) ); - Chip_RIT_SetCOMPVAL(LPC_RITIMER, Chip_RIT_GetCounter(LPC_RITIMER) + reload_val);/* Let it tick */ - - /* Set the priority and enable the interrupt */ - NVIC_SetPriority((IRQn_Type) RITIMER_IRQn, RITIMER_IRQn_PRI); - NVIC_EnableIRQ((IRQn_Type) RITIMER_IRQn); + SysTick_Config(CGU_GetPCLKFrequency(CGU_PERIPHERAL_M4CORE) / (1000 / period)); } -/* Disable LWIP tick */ +/* Disable systick */ void SysTick_Disable(void) { - Chip_RIT_Disable(LPC_RITIMER); + SysTick->CTRL &= ~SysTick_CTRL_ENABLE_Msk; } -/** - * @brief RITimer IRQ handler and timebase management - * @return Nothing - * @note This function keeps a timebase for LWIP that can be - * used for other functions. - */ -void RIT_IRQHandler(void) -{ - /* Clear RITimer Interrupt, Reload counter value */ - Chip_RIT_ClearInt(LPC_RITIMER); - Chip_RIT_SetCOMPVAL(LPC_RITIMER, Chip_RIT_GetCounter(LPC_RITIMER) + reload_val);/* Reload value */ - - /* Increment tick count */ - systick_timems += saved_period; -} - -#else - -/* Enable LWIP tick and interrupt */ -void SysTick_Enable(uint32_t period) -{ - saved_period = period; - SysTick_Config((SystemCoreClock * period) / 1000); -} - -/* Disable LWIP tick */ -void SysTick_Disable(void) -{ - SysTick->CTRL &= ~SysTick_CTRL_ENABLE_Msk; -} - -/** - * @brief SysTick IRQ handler and timebase management - * @return Nothing - * @note This function keeps a timebase for LWIP that can be - * used for other functions. +/** \brief SysTick IRQ handler and timebase management + * + * This function keeps a timebase for the sysTick that can be + * used for other functions. */ void SysTick_Handler(void) { @@ -141,8 +73,6 @@ void SysTick_Handler(void) systick_timems += saved_period; } -#endif - /* Get the current systick time in milliSeconds */ uint32_t SysTick_GetMS(void) { @@ -154,21 +84,12 @@ void msDelay(uint32_t ms) { uint32_t to = ms + systick_timems; - while (to > systick_timems) {} -} - -/** - * @brief LWIP standalone mode time support - * @return Returns the current time in mS - * @note Returns the current time in mS. This is needed for the LWIP timers - */ -u32_t sys_now(void) -{ - return (u32_t) SysTick_GetMS(); + while (to > systick_timems); } +#endif /** * @} */ -#endif /* NO_SYS == 1 */ + /* --------------------------------- End Of File ------------------------------ */ diff --git a/vendor/lwip/lpclwip/arch/lpc_arch.h b/vendor/lwip/lpclwip/arch/lpc_arch.h index 21d56e714..b24b0bc77 100644 --- a/vendor/lwip/lpclwip/arch/lpc_arch.h +++ b/vendor/lwip/lpclwip/arch/lpc_arch.h @@ -1,36 +1,30 @@ -/* - * @brief Architecture specific functions used with the LWIP examples - * - * @note - * Copyright(C) NXP Semiconductors, 2012 - * All rights reserved. - * - * @par - * Software that is described herein is for illustrative purposes only - * which provides customers with programming information regarding the - * LPC products. This software is supplied "AS IS" without any warranties of - * any kind, and NXP Semiconductors and its licensor disclaim any and - * all warranties, express or implied, including all implied warranties of - * merchantability, fitness for a particular purpose and non-infringement of - * intellectual property rights. NXP Semiconductors assumes no responsibility - * or liability for the use of the software, conveys no license or rights under any - * patent, copyright, mask work right, or any other intellectual property rights in - * or to any products. NXP Semiconductors reserves the right to make changes - * in the software without notification. NXP Semiconductors also makes no - * representation or warranty that such application will be suitable for the - * specified use without further testing or modification. - * - * @par - * Permission to use, copy, modify, and distribute this software and its - * documentation is hereby granted, under NXP Semiconductors' and its - * licensor's relevant copyrights in the software, without fee, provided that it - * is used in conjunction with NXP Semiconductors microcontrollers. This - * copyright, permission, and disclaimer notice must appear in all copies of - * this code. - */ +/********************************************************************** +* $Id$ lpc_arch.h 2011-11-20 +*//** +* @file lpc_arch.h +* @brief Architecture specific functions used with the LWIP examples +* @version 1.0 +* @date 20. Nov. 2011 +* @author NXP MCU SW Application Team +* +* Copyright(C) 2011, NXP Semiconductor +* All rights reserved. +* +*********************************************************************** +* Software that is described herein is for illustrative purposes only +* which provides customers with programming information regarding the +* products. This software is supplied "AS IS" without any warranties. +* NXP Semiconductors assumes no responsibility or liability for the +* use of the software, conveys no license or title under any patent, +* copyright, or mask work right to the product. NXP Semiconductors +* reserves the right to make changes in the software without +* notification. NXP Semiconductors also make no representation or +* warranty that such application will be suitable for the specified +* use without further testing or modification. +**********************************************************************/ -#ifndef __LPC_ARCH_H_ -#define __LPC_ARCH_H_ +#ifndef __LPC_ARCH_H +#define __LPC_ARCH_H #include "lwip/opt.h" @@ -39,50 +33,47 @@ extern "C" { #endif -/** @defgroup NET_LWIP_ARCH Architecture specific functions used with the LWIP examples - * @ingroup NET_LWIP - * @{ +/** @ingroup lpc_arch */ #if NO_SYS == 1 -/** - * @brief Enable LWIP tick and interrupt - * @param period : Period of the systick clock - * @return Nothing - * @note This enables the systick interrupt and sets up the systick rate. This - * function is only used in standalone systems. +/** \brief Enable systick rate and interrupt + * + * This enables the systick interrupt and sets up the systick rate. This + * function is only used in standalone systems. + * + * \param[in] period Period of the systick clock */ void SysTick_Enable(uint32_t period); -/** - * @brief Disable LWIP tick - * @return Nothing - * This disables the systick interrupt. This function is only used in - * standalone systems. +/** \brief Disable systick + * + * This disables the systick interrupt. This function is only used in + * standalone systems. */ void SysTick_Disable(void); -/** - * @brief Get the current systick time in milliSeconds - * @return current systick time in milliSeconds - * @note Returns the current systick time in milliSeconds. This function is only - * used in standalone systems. +/** \brief Get the current systick time in milliSeconds + * + * Returns the current systick time in milliSeconds. This function is only + * used in standalone systems. + * + * /returns current systick time in milliSeconds */ uint32_t SysTick_GetMS(void); - #endif -/** - * @brief Delay for the specified number of milliSeconds - * @param ms : Time in milliSeconds to delay - * @return Nothing - * @note For standalone systems. This function will block for the specified - * number of milliSconds. For RTOS based systems, this function will delay - * the task by the specified number of milliSeconds. +/** \brief Delay for the specified number of milliSeconds + * + * For standalone systems. This function will block for the specified + * number of milliSconds. For RTOS based systems, this function will delay + * the task by the specified number of milliSeconds. + * + * \param[in] ms Time in milliSeconds to delay */ void msDelay(uint32_t ms); -/** +/** * @} */ @@ -90,4 +81,6 @@ void msDelay(uint32_t ms); } #endif -#endif /* __LPC_ARCH_H_ */ +#endif /* __LPC_ARCH_H */ + +/* --------------------------------- End Of File ------------------------------ */ diff --git a/vendor/lwip/lpclwip/arch/lpc_debug.c b/vendor/lwip/lpclwip/arch/lpc_debug.c index 13f749c24..08ee3d52f 100644 --- a/vendor/lwip/lpclwip/arch/lpc_debug.c +++ b/vendor/lwip/lpclwip/arch/lpc_debug.c @@ -1,78 +1,63 @@ -/* - * @brief LWIP debug re-direction - * - * @note - * Copyright(C) NXP Semiconductors, 2012 - * All rights reserved. - * - * @par - * Software that is described herein is for illustrative purposes only - * which provides customers with programming information regarding the - * LPC products. This software is supplied "AS IS" without any warranties of - * any kind, and NXP Semiconductors and its licensor disclaim any and - * all warranties, express or implied, including all implied warranties of - * merchantability, fitness for a particular purpose and non-infringement of - * intellectual property rights. NXP Semiconductors assumes no responsibility - * or liability for the use of the software, conveys no license or rights under any - * patent, copyright, mask work right, or any other intellectual property rights in - * or to any products. NXP Semiconductors reserves the right to make changes - * in the software without notification. NXP Semiconductors also makes no - * representation or warranty that such application will be suitable for the - * specified use without further testing or modification. - * - * @par - * Permission to use, copy, modify, and distribute this software and its - * documentation is hereby granted, under NXP Semiconductors' and its - * licensor's relevant copyrights in the software, without fee, provided that it - * is used in conjunction with NXP Semiconductors microcontrollers. This - * copyright, permission, and disclaimer notice must appear in all copies of - * this code. - */ +/********************************************************************** +* $Id$ lpc_debug.c 2011-11-20 +*//** +* @file lpc_debug.c +* @brief LWIP debug re-direction +* @version 1.0 +* @date 20. Nov. 2011 +* @author NXP MCU SW Application Team +* +* Copyright(C) 2011, NXP Semiconductor +* All rights reserved. +* +*********************************************************************** +* Software that is described herein is for illustrative purposes only +* which provides customers with programming information regarding the +* products. This software is supplied "AS IS" without any warranties. +* NXP Semiconductors assumes no responsibility or liability for the +* use of the software, conveys no license or title under any patent, +* copyright, or mask work right to the product. NXP Semiconductors +* reserves the right to make changes in the software without +* notification. NXP Semiconductors also make no representation or +* warranty that such application will be suitable for the specified +* use without further testing or modification. +**********************************************************************/ #include "lwip/opt.h" -/** @defgroup NET_LWIP_DEBUG LWIP debug re-direction - * @ingroup NET_LWIP - * Support functions for debug output for LWIP +/** @ingroup lwip_lpc_debug * @{ */ -#ifdef LWIP_DEBUG - -/***************************************************************************** - * Private types/enumerations/variables - ****************************************************************************/ +#ifdef LWIP_DEBUG -/***************************************************************************** - * Public types/enumerations/variables - ****************************************************************************/ +/** \brief Displays an error message on assertion -/***************************************************************************** - * Private functions - ****************************************************************************/ + This function will display an error message on an assertion + to the debug output. -/***************************************************************************** - * Public functions - ****************************************************************************/ - -/* Displays an error message on assertion */ + \param[in] msg Error message to display + \param[in] line Line number in file with error + \param[in] file Filename with error + */ void assert_printf(char *msg, int line, char *file) { if (msg) { LWIP_DEBUGF(LWIP_DBG_ON, ("%s:%d in file %s\n", msg, line, file)); + while (1) { + /* Fast LED flash */ + led_set(0); + msDelay(100); + led_set(1); + msDelay(100); + } } - while (1) {} } -#else -/* LWIP optimized assertion loop (no LWIP_DEBUG) */ -void assert_loop(void) -{ - while (1) {} -} - - #endif /* LWIP_DEBUG */ +#endif /* LWIP_DEBUG */ /** * @} */ + +/* --------------------------------- End Of File ------------------------------ */ diff --git a/vendor/lwip/lpclwip/arch/sys_arch_freertos.c b/vendor/lwip/lpclwip/arch/sys_arch_freertos.c index 2e834bb38..d46917a91 100644 --- a/vendor/lwip/lpclwip/arch/sys_arch_freertos.c +++ b/vendor/lwip/lpclwip/arch/sys_arch_freertos.c @@ -38,7 +38,14 @@ #include "lpc_arch.h" #include <stdio.h> - #if NO_SYS==0 + #if NO_SYS==1 +/* Returns the current time in mS. This is needed for the LWIP timers */ +//u32_t sys_now(void) +//{ +// return (u32_t) SysTick_GetMS(); +//} + +#else /* ------------------------ System architecture includes ----------------------------- */ #include "arch/sys_arch.h" diff --git a/vendor/lwip/lpclwip/lpc_phy.h b/vendor/lwip/lpclwip/lpc_phy.h new file mode 100644 index 000000000..795e76fc6 --- /dev/null +++ b/vendor/lwip/lpclwip/lpc_phy.h @@ -0,0 +1,151 @@ +/********************************************************************** +* $Id$ lpc_phy.h 2011-11-20 +*//** +* @file lpc_phy.h +* @brief Common PHY definitions used with all PHYs +* @version 1.0 +* @date 20 Nov. 2011 +* @author NXP MCU SW Application Team +* +* Copyright(C) 2011, NXP Semiconductor +* All rights reserved. +* +*********************************************************************** +* Software that is described herein is for illustrative purposes only +* which provides customers with programming information regarding the +* products. This software is supplied "AS IS" without any warranties. +* NXP Semiconductors assumes no responsibility or liability for the +* use of the software, conveys no license or title under any patent, +* copyright, or mask work right to the product. NXP Semiconductors +* reserves the right to make changes in the software without +* notification. NXP Semiconductors also make no representation or +* warranty that such application will be suitable for the specified +* use without further testing or modification. +**********************************************************************/ + +#ifndef __LPC_PHY_H_ +#define __LPC_PHY_H_ + +#include "lwip/opt.h" +#include "lwip/err.h" +#include "lwip/netif.h" + +#ifdef __cplusplus +extern "C" +{ +#endif + +/* These PHY functions are usually part of the EMAC driver */ + +/** \brief Phy status update state machine + * + * This function provides a state machine for maintaining the PHY + * status without blocking. It must be occasionally called for the + * PHY status to be maintained. + * + * \param[in] netif NETIF structure + */ +s32_t lpc_phy_sts_sm(struct netif *netif); + +/** \brief Initialize the PHY + * + * This function initializes the PHY. It will block until complete. + * This function is called as part of the EMAC driver + * initialization. Configuration of the PHY at startup is + * controlled by setting up configuration defines in lpc_phy.h. + * + * \param[in] netif NETIF structure + * \param[in] rmii If set, configures the PHY for RMII mode + * \return ERR_OK if the setup was successful, otherwise ERR_TIMEOUT + */ +err_t lpc_phy_init(struct netif *netif, int rmii); + +/** \brief Write a value via the MII link (non-blocking) + * + * This function will write a value on the MII link interface to a PHY + * or a connected device. The function will return immediately without + * a status. Status needs to be polled later to determine if the write + * was successful. + * + * \param[in] PhyReg PHY register to write to + * \param[in] Value Value to write + */ +void lpc_mii_write_noblock(u32_t PhyReg, u32_t Value); + +/** \brief Write a value via the MII link (blocking) + * + * This function will write a value on the MII link interface to a PHY + * or a connected device. The function will block until complete. + * + * \param[in] PhyReg PHY register to write to + * \param[in] Value Value to write + * \returns 0 if the write was successful, otherwise !0 + */ +err_t lpc_mii_write(u32_t PhyReg, u32_t Value); + +/** \brief Reads current MII link busy status + * + * This function will return the current MII link busy status and is meant to + * be used with non-blocking functions for monitor PHY status such as + * connection state. + * + * \returns !0 if the MII link is busy, otherwise 0 + */ +u32_t lpc_mii_is_busy(void); + +/** \brief Starts a read operation via the MII link (non-blocking) + * + * This function returns the current value in the MII data register. It is + * meant to be used with the non-blocking oeprations. This value should + * only be read after a non-block read command has been issued and the + * MII status has been determined to be good. + * + * \returns The current value in the MII value register + */ +u32_t lpc_mii_read_data(void); + +/** \brief Starts a read operation via the MII link (non-blocking) + * + * This function will start a read operation on the MII link interface + * from a PHY or a connected device. The function will not block and + * the status mist be polled until complete. Once complete, the data + * can be read. + * + * \param[in] PhyReg PHY register to read from + */ +err_t lpc_mii_read(u32_t PhyReg, u32_t *data); + +/** \brief Read a value via the MII link (blocking) + * + * This function will read a value on the MII link interface from a PHY + * or a connected device. The function will block until complete. + * + * \param[in] PhyReg PHY register to read from + * \param[in] data Pointer to where to save data read via MII + * \returns 0 if the read was successful, otherwise !0 + */ +void lpc_mii_read_noblock(u32_t PhyReg); + +/** + * This function provides a method for the PHY to setup the EMAC + * for the PHY negotiated duplex mode. + * + * @param[in] full_duplex 0 = half duplex, 1 = full duplex + */ +void lpc_emac_set_duplex(int full_duplex); + +/** + * This function provides a method for the PHY to setup the EMAC + * for the PHY negotiated bit rate. + * + * @param[in] mbs_100 0 = 10mbs mode, 1 = 100mbs mode + */ +void lpc_emac_set_speed(int mbs_100); + +#ifdef __cplusplus +} +#endif + +#endif /* __LPC_PHY_H_ */ + +/* --------------------------------- End Of File ------------------------------ */ diff --git a/vendor/lwip/lpclwip/lpc_phy_lan8720.c b/vendor/lwip/lpclwip/lpc_phy_lan8720.c new file mode 100644 index 000000000..0a47332b3 --- /dev/null +++ b/vendor/lwip/lpclwip/lpc_phy_lan8720.c @@ -0,0 +1,300 @@ +/********************************************************************** +* $Id$ lpc_phy_lan8720.c 2011-11-20 +*//** +* @file lpc_phy_lan8720.c +* @brief LAN8720 PHY status and control. +* @version 1.0 +* @date 20 Nov. 2011 +* @author NXP MCU SW Application Team +* +* Copyright(C) 2011, NXP Semiconductor +* All rights reserved. +* +*********************************************************************** +* Software that is described herein is for illustrative purposes only +* which provides customers with programming information regarding the +* products. This software is supplied "AS IS" without any warranties. +* NXP Semiconductors assumes no responsibility or liability for the +* use of the software, conveys no license or title under any patent, +* copyright, or mask work right to the product. NXP Semiconductors +* reserves the right to make changes in the software without +* notification. NXP Semiconductors also make no representation or +* warranty that such application will be suitable for the specified +* use without further testing or modification. +**********************************************************************/ + +#include "lwip/opt.h" +#include "lwip/err.h" +#include "lwip/tcpip.h" +#include "lwip/snmp.h" + +#include "boards/board.h" +#include "lpc_phy.h" + +/** @defgroup lan8720_phy PHY status and control for the LAN8720. + * @ingroup lwip_phy + * + * Various functions for controlling and monitoring the status of the + * LAN8720 PHY. In polled (standalone) systems, the PHY state must be + * monitored as part of the application. In a threaded (RTOS) system, + * the PHY state is monitored by the PHY handler thread. The MAC + * driver will not transmit unless the PHY link is active. + * @{ + */ + +/** \brief LAN8720 PHY register offsets */ +#define LAN8_BCR_REG 0x0 /**< Basic Control Register */ +#define LAN8_BSR_REG 0x1 /**< Basic Status Reg */ +#define LAN8_PHYID1_REG 0x2 /**< PHY ID 1 Reg */ +#define LAN8_PHYID2_REG 0x3 /**< PHY ID 2 Reg */ +#define LAN8_PHYSPLCTL_REG 0x1F /**< PHY special control/status Reg */ + +/* LAN8720 BCR register definitions */ +#define LAN8_RESET (1 << 15) /**< 1= S/W Reset */ +#define LAN8_LOOPBACK (1 << 14) /**< 1=loopback Enabled */ +#define LAN8_SPEED_SELECT (1 << 13) /**< 1=Select 100MBps */ +#define LAN8_AUTONEG (1 << 12) /**< 1=Enable auto-negotiation */ +#define LAN8_POWER_DOWN (1 << 11) /**< 1=Power down PHY */ +#define LAN8_ISOLATE (1 << 10) /**< 1=Isolate PHY */ +#define LAN8_RESTART_AUTONEG (1 << 9) /**< 1=Restart auto-negoatiation */ +#define LAN8_DUPLEX_MODE (1 << 8) /**< 1=Full duplex mode */ + +/* LAN8720 BSR register definitions */ +#define LAN8_100BASE_T4 (1 << 15) /**< T4 mode */ +#define LAN8_100BASE_TX_FD (1 << 14) /**< 100MBps full duplex */ +#define LAN8_100BASE_TX_HD (1 << 13) /**< 100MBps half duplex */ +#define LAN8_10BASE_T_FD (1 << 12) /**< 100Bps full duplex */ +#define LAN8_10BASE_T_HD (1 << 11) /**< 10MBps half duplex */ +#define LAN8_AUTONEG_COMP (1 << 5) /**< Auto-negotation complete */ +#define LAN8_RMT_FAULT (1 << 4) /**< Fault */ +#define LAN8_AUTONEG_ABILITY (1 << 3) /**< Auto-negotation supported */ +#define LAN8_LINK_STATUS (1 << 2) /**< 1=Link active */ +#define LAN8_JABBER_DETECT (1 << 1) /**< Jabber detect */ +#define LAN8_EXTEND_CAPAB (1 << 0) /**< Supports extended capabilities */ + +/* LAN8720 PHYSPLCTL status definitions */ +#define LAN8_SPEEDMASK (7 << 2) /**< Speed and duplex mask */ +#define LAN8_SPEED100F (6 << 2) /**< 100BT full duplex */ +#define LAN8_SPEED10F (5 << 2) /**< 10BT full duplex */ +#define LAN8_SPEED100H (2 << 2) /**< 100BT half duplex */ +#define LAN8_SPEED10H (1 << 2) /**< 10BT half duplex */ + +/* LAN8720 PHY ID 1/2 register definitions */ +#define LAN8_PHYID1_OUI 0x0007 /**< Expected PHY ID1 */ +#define LAN8_PHYID2_OUI 0xC0F0 /**< Expected PHY ID2, except last 4 bits */ + +/** + * @brief PHY status structure used to indicate current status of PHY. + */ +typedef struct { + u32_t phy_speed_100mbs:2; /**< 10/100 MBS connection speed flag. */ + u32_t phy_full_duplex:2; /**< Half/full duplex connection speed flag. */ + u32_t phy_link_active:2; /**< Phy link active flag. */ +} PHY_STATUS_TYPE; + +/** \brief PHY update flags */ +static PHY_STATUS_TYPE physts; + +/** \brief Last PHY update flags, used for determing if something has changed */ +static PHY_STATUS_TYPE olddphysts; + +/** \brief PHY update counter for state machine */ +static s32_t phyustate; + +/** \brief Update PHY status from passed value + * + * This function updates the current PHY status based on the + * passed PHY status word. The PHY status indicate if the link + * is active, the connection speed, and duplex. + * + * \param[in] netif NETIF structure + * \param[in] linksts Status word with link state + * \param[in] sdsts Status word with speed and duplex states + * \return 1 if the status has changed, otherwise 0 + */ +static s32_t lpc_update_phy_sts(struct netif *netif, u32_t linksts, u32_t sdsts) +{ + s32_t changed = 0; + + /* Update link active status */ + if (linksts & LAN8_LINK_STATUS) + physts.phy_link_active = 1; + else + physts.phy_link_active = 0; + + switch (sdsts & LAN8_SPEEDMASK) { + case LAN8_SPEED100F: + default: + physts.phy_speed_100mbs = 1; + physts.phy_full_duplex = 1; + break; + + case LAN8_SPEED10F: + physts.phy_speed_100mbs = 0; + physts.phy_full_duplex = 1; + break; + + case LAN8_SPEED100H: + physts.phy_speed_100mbs = 1; + physts.phy_full_duplex = 0; + break; + + case LAN8_SPEED10H: + physts.phy_speed_100mbs = 0; + physts.phy_full_duplex = 0; + break; + } + + if (physts.phy_speed_100mbs != olddphysts.phy_speed_100mbs) { + changed = 1; + if (physts.phy_speed_100mbs) { + /* 100MBit mode. */ + lpc_emac_set_speed(1); + + NETIF_INIT_SNMP(netif, snmp_ifType_ethernet_csmacd, 100000000); + } + else { + /* 10MBit mode. */ + lpc_emac_set_speed(0); + + NETIF_INIT_SNMP(netif, snmp_ifType_ethernet_csmacd, 10000000); + } + + olddphysts.phy_speed_100mbs = physts.phy_speed_100mbs; + } + + if (physts.phy_full_duplex != olddphysts.phy_full_duplex) { + changed = 1; + if (physts.phy_full_duplex) + lpc_emac_set_duplex(1); + else + lpc_emac_set_duplex(0); + + olddphysts.phy_full_duplex = physts.phy_full_duplex; + } + + if (physts.phy_link_active != olddphysts.phy_link_active) { + changed = 1; +#if NO_SYS == 1 + if (physts.phy_link_active) + netif_set_link_up(netif); + else + netif_set_link_down(netif); +#else + if (physts.phy_link_active) + tcpip_callback_with_block((tcpip_callback_fn) netif_set_link_up, + (void*) netif, 1); + else + tcpip_callback_with_block((tcpip_callback_fn) netif_set_link_down, + (void*) netif, 1); +#endif + + olddphysts.phy_link_active = physts.phy_link_active; + } + + return changed; +} + +/** \brief Initialize the LAN8720 PHY. + * + * This function initializes the LAN8720 PHY. It will block until + * complete. This function is called as part of the EMAC driver + * initialization. Configuration of the PHY at startup is + * controlled by setting up configuration defines in + * lpc_emac_config.h. + * + * \param[in] netif NETIF structure + * \param[in] rmii If set, configures the PHY for RMII mode + * \return ERR_OK if the setup was successful, otherwise ERR_TIMEOUT + */ +err_t lpc_phy_init(struct netif *netif, int rmii) +{ + u32_t tmp, tmp1; + s32_t i; + + physts.phy_speed_100mbs = olddphysts.phy_speed_100mbs = 2; + physts.phy_full_duplex = olddphysts.phy_full_duplex = 2; + physts.phy_link_active = olddphysts.phy_link_active = 2; + phyustate = 0; + + /* Only first read and write are checked for failure */ + /* Put the LAN8720 in reset mode and wait for completion */ + if (lpc_mii_write(LAN8_BCR_REG, LAN8_RESET) != 0) + return ERR_TIMEOUT; + i = 400; + while (i > 0) { + msDelay(1); /* 1 ms */ + if (lpc_mii_read(LAN8_BCR_REG, &tmp) != 0) + return ERR_TIMEOUT; + + if (!(tmp & (LAN8_RESET | LAN8_POWER_DOWN))) + i = -1; + else + i--; + } + /* Timeout? */ + if (i == 0) + return ERR_TIMEOUT; + + /* Setup link based on configuration options */ +#if PHY_USE_AUTONEG==1 + tmp = LAN8_AUTONEG; +#else + tmp = 0; +#endif +#if PHY_USE_100MBS==1 + tmp |= LAN8_SPEED_SELECT; +#endif +#if PHY_USE_FULL_DUPLEX==1 + tmp |= LAN8_DUPLEX_MODE; +#endif + lpc_mii_write(LAN8_BCR_REG, tmp); + + /* The link is not set active at this point, but will be detected + later */ + + return ERR_OK; +} + +/* Phy status update state machine */ +s32_t lpc_phy_sts_sm(struct netif *netif) +{ + static u32_t sts; + s32_t changed = 0; + + switch (phyustate) { + default: + case 0: + /* Read BMSR to clear faults */ + lpc_mii_read_noblock(LAN8_BSR_REG); + phyustate = 1; + break; + + case 1: + /* Wait for read status state */ + if (!lpc_mii_is_busy()) { + /* Get PHY status with link state */ + sts = lpc_mii_read_data(); + lpc_mii_read_noblock(LAN8_PHYSPLCTL_REG); + phyustate = 2; + } + break; + + case 2: + /* Wait for read status state */ + if (!lpc_mii_is_busy()) { + /* Update PHY status */ + changed = lpc_update_phy_sts(netif, sts, lpc_mii_read_data()); + phyustate = 0; + } + break; + } + + return changed; +} + +/** + * @} + */ + +/* --------------------------------- End Of File ------------------------------ */ |
