Import Mbed OS hard-float snapshot

This commit is contained in:
Beslan
2026-06-01 20:15:04 +03:00
commit d3738e2f89
16278 changed files with 10628036 additions and 0 deletions

View File

@@ -0,0 +1,941 @@
/**********************************************************************
* $Id$ lpc17_emac.c 2011-11-20
*//**
* @file lpc17_emac.c
* @brief LPC17 ethernet driver 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.
**********************************************************************/
#include <stdlib.h>
#include <string.h>
#include "cmsis_os.h"
#include "mbed_interface.h"
#include "mbed_assert.h"
#include "netsocket/nsapi_types.h"
#include "lpc_emac_config.h"
#include "lpc17_emac.h"
#include "lpc17xx_emac.h"
#include "lpc_phy.h"
#include "mbed_interface.h"
#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
#endif
#if LPC_NUM_BUFF_RXDESCS < 3
#error LPC_NUM_BUFF_RXDESCS must be at least 3
#endif
/** @defgroup lwip17xx_emac_DRIVER lpc17 EMAC driver for LWIP
* @ingroup lwip_emac
*
* @{
*/
/** \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 LEIP_DEBUG enabled, the priorities might be better
* the same. */
#define RX_PRIORITY (osPriorityNormal)
#define TX_PRIORITY (osPriorityNormal)
#define PHY_PRIORITY (osPriorityNormal)
/** \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
/** \brief Receive group interrupts
*/
#define RXINTGROUP (EMAC_INT_RX_OVERRUN | EMAC_INT_RX_ERR | EMAC_INT_RX_DONE)
/** \brief Transmit group interrupts
*/
#define TXINTGROUP (EMAC_INT_TX_UNDERRUN | EMAC_INT_TX_ERR | EMAC_INT_TX_DONE)
/** \brief Signal used for ethernet ISR to signal packet_rx() thread.
*/
#define RX_SIGNAL 1
/** \brief Structure of a TX/RX descriptor
*/
typedef struct
{
volatile uint32_t packet; /**< Pointer to buffer */
volatile uint32_t control; /**< Control word */
} LPC_TXRX_DESC_T;
/** \brief Structure of a RX status entry
*/
typedef struct
{
volatile uint32_t statusinfo; /**< RX status word */
volatile uint32_t statushashcrc; /**< RX hash CRC */
} LPC_TXRX_STATUS_T;
/* LPC EMAC driver data structure */
struct lpc_enetdata {
/* prxs must be 8 byte aligned! */
LPC_TXRX_STATUS_T prxs[LPC_NUM_BUFF_RXDESCS]; /**< Pointer to RX statuses */
LPC_TXRX_DESC_T ptxd[LPC_NUM_BUFF_TXDESCS]; /**< Pointer to TX descriptor list */
LPC_TXRX_STATUS_T ptxs[LPC_NUM_BUFF_TXDESCS]; /**< Pointer to TX statuses */
LPC_TXRX_DESC_T prxd[LPC_NUM_BUFF_RXDESCS]; /**< Pointer to RX descriptor list */
emac_mem_buf_t *rxb[LPC_NUM_BUFF_RXDESCS]; /**< RX pbuf pointer list, zero-copy mode */
uint32_t rx_fill_desc_index; /**< RX descriptor next available index */
volatile uint32_t rx_free_descs; /**< Count of free RX descriptors */
emac_mem_buf_t *txb[LPC_NUM_BUFF_TXDESCS]; /**< TX pbuf pointer list, zero-copy mode */
uint32_t lpc_last_tx_idx; /**< TX last descriptor index, zero-copy mode */
uint32_t lpc_reserved_tx_num; /**< Number of reserved TX descriptors, zero-copy mode */
};
#if defined(TARGET_LPC1768)
/** \brief Group LPC17xx processors into one definition
*/
#define TARGET_LPC17XX
#endif
#if defined(TARGET_LPC17XX)
# if defined(TOOLCHAIN_GCC_ARM) || defined(TOOLCHAIN_ARM)
# define ETHMEM_SECTION __attribute__((section("AHBSRAM1"),aligned))
# endif
#endif
#ifndef ETHMEM_SECTION
#define ETHMEM_SECTION
#endif
/** \brief LPC EMAC driver work data
*/
#if defined (__ICCARM__)
#pragma location = ".ethusbram"
#pragma data_alignment = 8
#endif
ETHMEM_SECTION struct lpc_enetdata lpc_enetdata;
#if defined (__ICCARM__)
#pragma location = ".ethusbram"
#pragma data_alignment = 8
#endif
ETHMEM_SECTION uint8_t rx_thread_stack[DEFAULT_THREAD_STACKSIZE];
#if defined (__ICCARM__)
#pragma location = ".ethusbram"
#pragma data_alignment = 8
#endif
ETHMEM_SECTION uint8_t tx_clean_thread_stack[DEFAULT_THREAD_STACKSIZE];
#if defined (__ICCARM__)
#pragma location = ".ethusbram"
#pragma data_alignment = 8
#endif
ETHMEM_SECTION uint8_t phy_thread_stack[DEFAULT_THREAD_STACKSIZE];
static osThreadId_t create_new_thread(const char *threadName, void (*thread)(void *arg), void *arg, void *stack_ptr, int stacksize, osPriority_t priority, mbed_rtos_storage_thread_t *thread_cb)
{
osThreadAttr_t attr = {0};
attr.name = threadName;
attr.stack_mem = stack_ptr;
attr.cb_mem = thread_cb;
attr.stack_size = stacksize;
attr.cb_size = sizeof(mbed_rtos_storage_thread_t);
attr.priority = priority;
return osThreadNew(thread, arg, &attr);
}
/** \brief Queues a memory buffer into the RX descriptor list
*
* \param[in] p Pointer to buffer to queue
*/
void LPC17_EMAC::lpc_rxqueue_pbuf(emac_mem_buf_t *p)
{
uint32_t idx;
/* Get next free descriptor index */
idx = lpc_enetdata.rx_fill_desc_index;
/* Setup descriptor and clear statuses */
lpc_enetdata.prxd[idx].control = EMAC_RCTRL_INT | ((uint32_t) (memory_manager->get_len(p) - 1));
lpc_enetdata.prxd[idx].packet = (uint32_t) memory_manager->get_ptr(p);
lpc_enetdata.prxs[idx].statusinfo = 0xFFFFFFFF;
lpc_enetdata.prxs[idx].statushashcrc = 0xFFFFFFFF;
/* Save pbuf pointer for push to network layer later */
lpc_enetdata.rxb[idx] = p;
/* Wrap at end of descriptor list */
idx++;
if (idx >= LPC_NUM_BUFF_RXDESCS) {
idx = 0;
}
/* Queue descriptor(s) */
lpc_enetdata.rx_free_descs -= 1;
lpc_enetdata.rx_fill_desc_index = idx;
LPC_EMAC->RxConsumeIndex = idx;
}
/** \brief Attempt to allocate and requeue a new memory buffer for RX
*
* \returns >= 1 if a packet or packets were allocated and requeued, otherwise 0
*/
int32_t LPC17_EMAC::lpc_rx_queue()
{
//struct lpc_enetdata *lpc_enetif = netif->state;
emac_mem_buf_t *p;
int32_t queued = 0;
/* Attempt to requeue as many packets as possible */
while (lpc_enetdata.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 = memory_manager->alloc_heap(EMAC_ETH_MAX_FLEN, 0);
if (p == NULL) {
return queued;
}
/* Queue packet */
lpc_rxqueue_pbuf(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.
*
* \returns Always returns ERR_OK
*/
bool LPC17_EMAC::lpc_rx_setup()
{
/* Setup pointers to RX structures */
LPC_EMAC->RxDescriptor = (uint32_t) &lpc_enetdata.prxd[0];
LPC_EMAC->RxStatus = (uint32_t) &lpc_enetdata.prxs[0];
LPC_EMAC->RxDescriptorNumber = LPC_NUM_BUFF_RXDESCS - 1;
lpc_enetdata.rx_free_descs = LPC_NUM_BUFF_RXDESCS;
lpc_enetdata.rx_fill_desc_index = 0;
/* Build RX buffer and descriptors */
lpc_rx_queue();
return true;
}
/** \brief Allocates a memory buffer and returns the data from the incoming packet.
*
* \return a buffer filled with the received packet (including MAC header)
* NULL on memory error
*/
emac_mem_buf_t *LPC17_EMAC::lpc_low_level_input()
{
emac_mem_buf_t *p = NULL;
uint32_t idx, length;
uint16_t origLength;
#ifdef LOCK_RX_THREAD
TXLockMutex.lock();
#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 (LPC_EMAC->IntStatus & EMAC_INT_RX_OVERRUN) {
/* Temporarily disable RX */
LPC_EMAC->MAC1 &= ~EMAC_MAC1_REC_EN;
/* Reset the RX side */
LPC_EMAC->MAC1 |= EMAC_MAC1_RES_RX;
LPC_EMAC->IntClear = EMAC_INT_RX_OVERRUN;
/* De-allocate all queued RX pbufs */
for (idx = 0; idx < LPC_NUM_BUFF_RXDESCS; idx++) {
if (lpc_enetdata.rxb[idx] != NULL) {
memory_manager->free(lpc_enetdata.rxb[idx]);
lpc_enetdata.rxb[idx] = NULL;
}
}
/* Start RX side again */
lpc_rx_setup();
/* Re-enable RX */
LPC_EMAC->MAC1 |= EMAC_MAC1_REC_EN;
#ifdef LOCK_RX_THREAD
TXLockMutex.unlock();
#endif
return NULL;
}
/* Determine if a frame has been received */
length = 0;
idx = LPC_EMAC->RxConsumeIndex;
if (LPC_EMAC->RxProduceIndex != idx) {
/* Handle errors */
if (lpc_enetdata.prxs[idx].statusinfo & (EMAC_RINFO_CRC_ERR |
EMAC_RINFO_SYM_ERR | EMAC_RINFO_ALIGN_ERR | EMAC_RINFO_LEN_ERR)) {
/* Re-queue the buffer for receive */
lpc_enetdata.rx_free_descs++;
p = lpc_enetdata.rxb[idx];
lpc_enetdata.rxb[idx] = NULL;
lpc_rxqueue_pbuf(p);
p = NULL;
} else {
/* A packet is waiting, get length */
length = (lpc_enetdata.prxs[idx].statusinfo & 0x7FF) + 1;
length -= 4;
/* Zero-copy */
p = lpc_enetdata.rxb[idx];
origLength = memory_manager->get_len(p);
memory_manager->set_len(p, length);
/* Free buffer from descriptor */
lpc_enetdata.rxb[idx] = NULL;
lpc_enetdata.rx_free_descs++;
/* Attempt to queue new buffer(s) */
if (lpc_rx_queue() == 0) {
/* Re-queue the buffer for receive */
memory_manager->set_len(p, origLength);
lpc_rxqueue_pbuf(p);
#ifdef LOCK_RX_THREAD
TXLockMutex.unlock();
#endif
return NULL;
}
}
}
#ifdef LOCK_RX_THREAD
TXLockMutex.unlock();
#endif
return p;
}
/** \brief Attempt to read a packet from the EMAC interface.
*
*/
void LPC17_EMAC::lpc_enetif_input()
{
emac_mem_buf_t *p;
/* move received packet into a new memory buffer */
p = lpc_low_level_input();
if (p == NULL) {
return;
}
emac_link_input_cb(p);
}
/** \brief Determine if the passed address is usable for the ethernet
* DMA controller.
*
* \param[in] addr Address of packet to check for DMA safe operation
* \return 1 if the packet address is not safe, otherwise 0
*/
int32_t LPC17_EMAC::lpc_packet_addr_notsafe(void *addr)
{
/* Check for legal address ranges */
#if defined(TARGET_LPC17XX)
if ((((uint32_t) addr >= 0x2007C000) && ((uint32_t) addr < 0x20083FFF))) {
#endif
return 0;
}
return 1;
}
/** \brief Sets up the TX descriptor ring buffers.
*
* This function sets up the descriptor list used for transmit packets.
*/
bool LPC17_EMAC::lpc_tx_setup()
{
int32_t idx;
/* Build TX descriptors for local buffers */
for (idx = 0; idx < LPC_NUM_BUFF_TXDESCS; idx++) {
lpc_enetdata.ptxd[idx].control = 0;
lpc_enetdata.ptxs[idx].statusinfo = 0xFFFFFFFF;
}
/* Setup pointers to TX structures */
LPC_EMAC->TxDescriptor = (uint32_t) &lpc_enetdata.ptxd[0];
LPC_EMAC->TxStatus = (uint32_t) &lpc_enetdata.ptxs[0];
LPC_EMAC->TxDescriptorNumber = LPC_NUM_BUFF_TXDESCS - 1;
lpc_enetdata.lpc_last_tx_idx = 0;
lpc_enetdata.lpc_reserved_tx_num = 0;
return true;
}
/** \brief Free TX buffers that are complete
*
* \param[in] cidx EMAC current descriptor comsumer index
*/
void LPC17_EMAC::lpc_tx_reclaim_st(uint32_t cidx)
{
TXLockMutex.lock();
// If consume index not last freed index or all descriptors in use
while (cidx != lpc_enetdata.lpc_last_tx_idx || lpc_enetdata.lpc_reserved_tx_num == LPC_NUM_BUFF_TXDESCS) {
if (lpc_enetdata.txb[lpc_enetdata.lpc_last_tx_idx] != NULL) {
memory_manager->free(lpc_enetdata.txb[lpc_enetdata.lpc_last_tx_idx]);
lpc_enetdata.txb[lpc_enetdata.lpc_last_tx_idx] = NULL;
}
xTXDCountSem.release();
lpc_enetdata.lpc_last_tx_idx++;
if (lpc_enetdata.lpc_last_tx_idx >= LPC_NUM_BUFF_TXDESCS) {
lpc_enetdata.lpc_last_tx_idx = 0;
}
lpc_enetdata.lpc_reserved_tx_num--;
}
TXLockMutex.unlock();
}
/** \brief User call for freeingTX buffers that are complete
*
*/
void LPC17_EMAC::lpc_tx_reclaim()
{
lpc_tx_reclaim_st(LPC_EMAC->TxConsumeIndex);
}
/** \brief Polls if an available TX descriptor is ready. Can be used to
* determine if the low level transmit function will block.
*
* \return 0 if no descriptors are read, or >0
*/
int32_t LPC17_EMAC::lpc_tx_ready()
{
int32_t fb;
uint32_t idx, cidx;
cidx = LPC_EMAC->TxConsumeIndex;
idx = LPC_EMAC->TxProduceIndex;
/* Determine number of free buffers */
if (idx == cidx) {
fb = LPC_NUM_BUFF_TXDESCS;
} else if (cidx > idx) {
fb = (LPC_NUM_BUFF_TXDESCS - 1) -
((idx + LPC_NUM_BUFF_TXDESCS) - cidx);
} else {
fb = (LPC_NUM_BUFF_TXDESCS - 1) - (cidx - idx);
}
return fb;
}
/** \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] p 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
*/
bool LPC17_EMAC::link_out(emac_mem_buf_t *p)
{
emac_mem_buf_t *q;
uint32_t idx, notdmasafe = 0;
emac_mem_buf_t *np;
int32_t dn;
/* Zero-copy TX buffers may be fragmented across a memory buffer chain. Determine
the number of descriptors needed for the transfer and 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! */
dn = 0;
for (q = p; q != NULL; q = memory_manager->get_next(q)) {
++dn;
void *ptr = memory_manager->get_ptr(q);
notdmasafe += lpc_packet_addr_notsafe(ptr);
}
#if LPC_TX_PBUF_BOUNCE_EN==1
/* If the buffer chain is not DMA safe, a new bounce buffer will be
created that will be used instead. This requires an copy from the
non-safe DMA region to the new buffer. */
if (notdmasafe) {
/* Allocate a buffer in DMA memory.
MEMORY MANAGER HEAP MUST BE IN DMA SAFE MEMORY. */
np = memory_manager->alloc_heap(memory_manager->get_total_len(p), 0);
if (np == NULL) {
memory_manager->free(p);
return false;
}
memory_manager->copy(np, p);
/* use the new buffer for descriptor queueing. The original buffer will
be de-allocated. */
memory_manager->free(p);
p = np;
dn = 1;
}
#else
if (notdmasafe) {
MBED_ASSERT(0);
}
#endif
/* Wait until enough descriptors are available for the transfer. */
/* THIS WILL BLOCK UNTIL THERE ARE ENOUGH DESCRIPTORS AVAILABLE */
for (int32_t count = 0; count < dn; count++) {
xTXDCountSem.acquire();
}
MBED_ASSERT(dn <= lpc_tx_ready());
TXLockMutex.lock();
/* Get free TX buffer index */
idx = LPC_EMAC->TxProduceIndex;
/* 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_enetdata.ptxd[idx].control = (memory_manager->get_len(q) - 1) | EMAC_TCTRL_INT |
EMAC_TCTRL_LAST;
lpc_enetdata.txb[idx] = p;
}
else {
/* Save size of packet, descriptor is not last */
lpc_enetdata.ptxd[idx].control = (memory_manager->get_len(q) - 1) | EMAC_TCTRL_INT;
lpc_enetdata.txb[idx] = NULL;
}
lpc_enetdata.ptxd[idx].packet = (uint32_t) memory_manager->get_ptr(q);
q = memory_manager->get_next(q);
idx++;
if (idx >= LPC_NUM_BUFF_TXDESCS) {
idx = 0;
}
lpc_enetdata.lpc_reserved_tx_num++;
}
LPC_EMAC->TxProduceIndex = idx;
TXLockMutex.unlock();
return true;
}
/** \brief LPC EMAC interrupt handler.
*
* This function handles the transmit, receive, and error interrupt of
* the LPC177x_8x. This is meant to be used when NO_SYS=0.
*/
void LPC17xxEthernetHandler(void)
{
LPC17_EMAC &emac = LPC17_EMAC::get_instance();
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 = LPC_EMAC->IntStatus;
if (ints & RXINTGROUP) {
/* RX group interrupt(s): Give signal to wakeup RX receive task.*/
osThreadFlagsSet(emac.RxThread, RX_SIGNAL);
}
if (ints & TXINTGROUP) {
/* TX group interrupt(s): Give semaphore to wakeup TX cleanup task. */
emac.TxCleanSem.release();
}
/* Clear pending interrupts */
LPC_EMAC->IntClear = ints;
}
/** \brief Packet reception task
*
* This task is called when a packet is received. It will
* pass the packet to the IP stacks core.
*
* \param[in] pvParameters Not used yet
*/
void LPC17_EMAC::packet_rx(void* pvParameters)
{
LPC17_EMAC *lpc17_emac = static_cast<LPC17_EMAC *>(pvParameters);
while (1) {
/* Wait for receive task to wakeup */
osThreadFlagsWait(RX_SIGNAL, 0, osWaitForever);
/* Process packets until all empty */
while (LPC_EMAC->RxConsumeIndex != LPC_EMAC->RxProduceIndex) {
lpc17_emac->lpc_enetif_input();
}
}
}
/** \brief Transmit cleanup task
*
* This task is called when a transmit interrupt occurs and
* reclaims the memory buffer and descriptor used for the packet once
* the packet has been transferred.
*
* \param[in] pvParameters Not used yet
*/
void LPC17_EMAC::packet_tx(void* pvParameters)
{
LPC17_EMAC *lpc17_emac = static_cast<LPC17_EMAC *>(pvParameters);
int32_t idx;
while (1) {
/* Wait for transmit cleanup task to wakeup */
lpc17_emac->TxCleanSem.acquire();
/* 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 (LPC_EMAC->IntStatus & EMAC_INT_TX_UNDERRUN) {
lpc17_emac->TXLockMutex.lock();
/* Reset the TX side */
LPC_EMAC->MAC1 |= EMAC_MAC1_RES_TX;
LPC_EMAC->IntClear = EMAC_INT_TX_UNDERRUN;
/* De-allocate all queued TX buffers */
for (idx = 0; idx < LPC_NUM_BUFF_TXDESCS; idx++) {
if (lpc_enetdata.txb[idx] != NULL) {
lpc17_emac->memory_manager->free(lpc_enetdata.txb[idx]);
lpc_enetdata.txb[idx] = NULL;
}
}
lpc17_emac->TXLockMutex.unlock();
/* Start TX side again */
lpc17_emac->lpc_tx_setup();
} else {
/* Free TX buffers that are done sending */
lpc17_emac->lpc_tx_reclaim();
}
}
}
/** \brief Low level init of the MAC and PHY.
*
*/
bool LPC17_EMAC::low_level_init()
{
bool err = true;
/* Enable MII clocking */
LPC_SC->PCONP |= CLKPWR_PCONP_PCENET;
#if defined(TARGET_LPC17XX)
LPC_PINCON->PINSEL2 = 0x50150105; /* Enable P1 Ethernet Pins. */
LPC_PINCON->PINSEL3 = (LPC_PINCON->PINSEL3 & ~0x0000000F) | 0x00000005;
#endif
/* Reset all MAC logic */
LPC_EMAC->MAC1 = EMAC_MAC1_RES_TX | EMAC_MAC1_RES_MCS_TX |
EMAC_MAC1_RES_RX | EMAC_MAC1_RES_MCS_RX | EMAC_MAC1_SIM_RES |
EMAC_MAC1_SOFT_RES;
LPC_EMAC->Command = EMAC_CR_REG_RES | EMAC_CR_TX_RES | EMAC_CR_RX_RES |
EMAC_CR_PASS_RUNT_FRM;
osDelay(10);
/* Initial MAC initialization */
LPC_EMAC->MAC1 = EMAC_MAC1_PASS_ALL;
LPC_EMAC->MAC2 = EMAC_MAC2_CRC_EN | EMAC_MAC2_PAD_EN |
EMAC_MAC2_VLAN_PAD_EN;
LPC_EMAC->MAXF = EMAC_ETH_MAX_FLEN;
/* Set RMII management clock rate to lowest speed */
LPC_EMAC->MCFG = EMAC_MCFG_CLK_SEL(11) | EMAC_MCFG_RES_MII;
LPC_EMAC->MCFG &= ~EMAC_MCFG_RES_MII;
/* Maximum number of retries, 0x37 collision window, gap */
LPC_EMAC->CLRT = EMAC_CLRT_DEF;
LPC_EMAC->IPGR = EMAC_IPGR_P1_DEF | EMAC_IPGR_P2_DEF;
#if LPC_EMAC_RMII
/* RMII setup */
LPC_EMAC->Command = EMAC_CR_PASS_RUNT_FRM | EMAC_CR_RMII;
#else
/* MII setup */
LPC_EMAC->CR = EMAC_CR_PASS_RUNT_FRM;
#endif
/* Initialize the PHY and reset */
err = lpc_phy_init(this, LPC_EMAC_RMII);
if (err == false) {
return false;
}
/* Save station address */
LPC_EMAC->SA2 = (uint32_t) hwaddr[0] |
(((uint32_t) hwaddr[1]) << 8);
LPC_EMAC->SA1 = (uint32_t) hwaddr[2] |
(((uint32_t) hwaddr[3]) << 8);
LPC_EMAC->SA0 = (uint32_t) hwaddr[4] |
(((uint32_t) hwaddr[5]) << 8);
/* Setup transmit and receive descriptors */
if (lpc_tx_setup() != true) {
return false;
}
if (lpc_rx_setup() != true) {
return false;
}
/* Enable packet reception */
LPC_EMAC->RxFilterCtrl = EMAC_RFC_PERFECT_EN | EMAC_RFC_BCAST_EN | EMAC_RFC_MCAST_EN;
/* Clear and enable rx/tx interrupts */
LPC_EMAC->IntClear = 0xFFFF;
LPC_EMAC->IntEnable = RXINTGROUP | TXINTGROUP;
/* Enable RX and TX */
LPC_EMAC->Command |= EMAC_CR_RX_EN | EMAC_CR_TX_EN;
LPC_EMAC->MAC1 |= EMAC_MAC1_REC_EN;
return err;
}
/* 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)
{
if (full_duplex) {
LPC_EMAC->MAC2 |= EMAC_MAC2_FULL_DUP;
LPC_EMAC->Command |= EMAC_CR_FULL_DUP;
LPC_EMAC->IPGT = EMAC_IPGT_FULL_DUP;
} else {
LPC_EMAC->MAC2 &= ~EMAC_MAC2_FULL_DUP;
LPC_EMAC->Command &= ~EMAC_CR_FULL_DUP;
LPC_EMAC->IPGT = EMAC_IPGT_HALF_DUP;
}
}
/* 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)
{
if (mbs_100) {
LPC_EMAC->SUPP = EMAC_SUPP_SPEED;
} else {
LPC_EMAC->SUPP = 0;
}
}
/* periodic PHY status update */
void LPC17_EMAC::phy_update(void *nif)
{
LPC17_EMAC *lpc17_emac = static_cast<LPC17_EMAC *>(nif);
while (true) {
lpc_phy_sts_sm(lpc17_emac);
osDelay(250);
}
}
void LPC17_EMAC::update_link_status(bool up)
{
emac_link_state_cb(up);
}
void LPC17_EMAC::eth_arch_enable_interrupts(void) {
NVIC_SetVector(ENET_IRQn, (uint32_t)LPC17xxEthernetHandler);
NVIC_SetPriority(ENET_IRQn, ((0x01 << 3) | 0x01));
NVIC_EnableIRQ(ENET_IRQn);
}
void LPC17_EMAC::eth_arch_disable_interrupts(void) {
NVIC_DisableIRQ(ENET_IRQn);
}
/**
* 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().
*
* @return ERR_OK if the loopif is initialized
* ERR_MEM if private data couldn't be allocated
* any other err_t on error
*/
bool LPC17_EMAC::power_up()
{
bool err = low_level_init();
if (err != true) {
return false;
}
RxThread = create_new_thread("lpc17_emac_rx_thread", LPC17_EMAC::packet_rx, this, rx_thread_stack, DEFAULT_THREAD_STACKSIZE, RX_PRIORITY, &RxThread_cb);
TxCleanThread = create_new_thread("lpc17_emac_txclean_thread", LPC17_EMAC::packet_tx, this, tx_clean_thread_stack, DEFAULT_THREAD_STACKSIZE, TX_PRIORITY, &TxCleanThread_cb);
PhyThread = create_new_thread("lpc17_emac_phy_thread", LPC17_EMAC::phy_update, this, phy_thread_stack, DEFAULT_THREAD_STACKSIZE, TX_PRIORITY, &PhyThread_cb);
/* Allow the PHY task to detect the initial link state and set up the proper flags */
osDelay(10);
eth_arch_enable_interrupts();
return true;
}
uint32_t LPC17_EMAC::get_mtu_size() const
{
return 1500;
}
uint32_t LPC17_EMAC::get_align_preference() const
{
return 0;
}
void LPC17_EMAC::get_ifname(char *name, uint8_t size) const
{
memcpy(name, LPC17_ETH_IF_NAME, (size < sizeof(LPC17_ETH_IF_NAME)) ? size : sizeof(LPC17_ETH_IF_NAME));
}
uint8_t LPC17_EMAC::get_hwaddr_size() const
{
return LPC17_ETH_HWADDR_SIZE;
}
bool LPC17_EMAC::get_hwaddr(uint8_t *addr) const
{
return false;
}
void LPC17_EMAC::set_hwaddr(const uint8_t *addr)
{
memcpy(hwaddr, addr, LPC17_ETH_HWADDR_SIZE);
/* Save station address */
LPC_EMAC->SA2 = (uint32_t) hwaddr[0] |
(((uint32_t) hwaddr[1]) << 8);
LPC_EMAC->SA1 = (uint32_t) hwaddr[2] |
(((uint32_t) hwaddr[3]) << 8);
LPC_EMAC->SA0 = (uint32_t) hwaddr[4] |
(((uint32_t) hwaddr[5]) << 8);
}
void LPC17_EMAC::set_link_input_cb(emac_link_input_cb_t input_cb)
{
emac_link_input_cb = input_cb;
}
void LPC17_EMAC::set_link_state_cb(emac_link_state_change_cb_t state_cb)
{
emac_link_state_cb = state_cb;
}
void LPC17_EMAC::add_multicast_group(const uint8_t *addr)
{
/* No-op at this stage */
}
void LPC17_EMAC::remove_multicast_group(const uint8_t *address)
{
/* No-op at this stage */
}
void LPC17_EMAC::set_all_multicast(bool all)
{
/* No-op at this stage */
}
void LPC17_EMAC::power_down()
{
/* No-op at this stage */
}
LPC17_EMAC::LPC17_EMAC()
: RxThread(),
RxThread_cb(),
TxCleanSem(),
hwaddr(),
TxCleanThread(),
TxCleanThread_cb(),
PhyThread(),
PhyThread_cb(),
TXLockMutex(),
xTXDCountSem(LPC_NUM_BUFF_TXDESCS),
emac_link_input_cb(0),
emac_link_state_cb(0),
memory_manager(0)
{
}
void LPC17_EMAC::set_memory_manager(EMACMemoryManager &mem_mngr)
{
memory_manager = &mem_mngr;
}
LPC17_EMAC &LPC17_EMAC::get_instance() {
static LPC17_EMAC emac;
return emac;
}
// Weak so a module can override
MBED_WEAK EMAC &EMAC::get_default_instance() {
return LPC17_EMAC::get_instance();
}
/* --------------------------------- End Of File ------------------------------ */

View File

@@ -0,0 +1,191 @@
/* Copyright (c) 2018 ARM Limited
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef LPC17_EMAC_H_
#define LPC17_EMAC_H_
#include "EMAC.h"
#include "rtos/Semaphore.h"
#include "rtos/Mutex.h"
#include "lpc_emac_config.h"
class LPC17_EMAC : public EMAC {
public:
LPC17_EMAC();
static LPC17_EMAC &get_instance();
/**
* Return maximum transmission unit
*
* @return MTU in bytes
*/
virtual uint32_t get_mtu_size() const;
/**
* Gets memory buffer alignment preference
*
* Gets preferred memory buffer alignment of the Emac device. IP stack may or may not
* align link out memory buffer chains using the alignment.
*
* @return Memory alignment requirement in bytes
*/
virtual uint32_t get_align_preference() const;
/**
* Return interface name
*
* @param name Pointer to where the name should be written
* @param size Maximum number of character to copy
*/
virtual void get_ifname(char *name, uint8_t size) const;
/**
* Returns size of the underlying interface HW address size.
*
* @return HW address size in bytes
*/
virtual uint8_t get_hwaddr_size() const;
/**
* Return interface-supplied HW address
*
* Copies HW address to provided memory, @param addr has to be of correct size see @a get_hwaddr_size
*
* HW address need not be provided if this interface does not have its own HW
* address configuration; stack will choose address from central system
* configuration if the function returns false and does not write to addr.
*
* @param addr HW address for underlying interface
* @return true if HW address is available
*/
virtual bool get_hwaddr(uint8_t *addr) const;
/**
* Set HW address for interface
*
* Provided address has to be of correct size, see @a get_hwaddr_size
*
* Called to set the MAC address to actually use - if @a get_hwaddr is provided
* the stack would normally use that, but it could be overridden, eg for test
* purposes.
*
* @param addr Address to be set
*/
virtual void set_hwaddr(const uint8_t *addr);
/**
* Sends the packet over the link
*
* That can not be called from an interrupt context.
*
* @param buf Packet to be send
* @return True if the packet was send successfully, False otherwise
*/
virtual bool link_out(emac_mem_buf_t *buf);
/**
* Initializes the HW
*
* @return True on success, False in case of an error.
*/
virtual bool power_up();
/**
* Deinitializes the HW
*
*/
virtual void power_down();
/**
* Sets a callback that needs to be called for packets received for that interface
*
* @param input_cb Function to be register as a callback
*/
virtual void set_link_input_cb(emac_link_input_cb_t input_cb);
/**
* Sets a callback that needs to be called on link status changes for given interface
*
* @param state_cb Function to be register as a callback
*/
virtual void set_link_state_cb(emac_link_state_change_cb_t state_cb);
/** Add device to a multicast group
*
* @param address A multicast group hardware address
*/
virtual void add_multicast_group(const uint8_t *address);
/** Remove device from a multicast group
*
* @param address A multicast group hardware address
*/
virtual void remove_multicast_group(const uint8_t *address);
/** Request reception of all multicast packets
*
* @param all True to receive all multicasts
* False to receive only multicasts addressed to specified groups
*/
virtual void set_all_multicast(bool all);
/** Sets memory manager that is used to handle memory buffers
*
* @param mem_mngr Pointer to memory manager
*/
virtual void set_memory_manager(EMACMemoryManager &mem_mngr);
void update_link_status(bool up);
osThreadId_t RxThread;
mbed_rtos_storage_thread_t RxThread_cb;
rtos::Semaphore TxCleanSem;
private:
void lpc_rxqueue_pbuf(emac_mem_buf_t *p);
int32_t lpc_rx_queue();
bool lpc_rx_setup();
emac_mem_buf_t *lpc_low_level_input();
void lpc_enetif_input();
int32_t lpc_packet_addr_notsafe(void *addr);
bool lpc_tx_setup();
void lpc_tx_reclaim_st(uint32_t cidx);
void lpc_tx_reclaim();
int32_t lpc_tx_ready();
static void packet_rx(void* pvParameters);
static void packet_tx(void* pvParameters);
bool low_level_init();
static void phy_update(void *nif);
bool eth_arch_enetif_init();
void eth_arch_enable_interrupts();
void eth_arch_disable_interrupts();
uint8_t hwaddr[6];
osThreadId_t TxCleanThread;
mbed_rtos_storage_thread_t TxCleanThread_cb;
osThreadId_t PhyThread;
mbed_rtos_storage_thread_t PhyThread_cb;
rtos::Mutex TXLockMutex;
rtos::Semaphore xTXDCountSem;
emac_link_input_cb_t emac_link_input_cb; /**< Callback for incoming data */
emac_link_state_change_cb_t emac_link_state_cb; /**< Link state change callback */
EMACMemoryManager *memory_manager; /**< Memory manager */
};
#endif

View File

@@ -0,0 +1,665 @@
/**********************************************************************
* $Id$ lpc17xx_emac.h 2010-05-21
*//**
* @file lpc17xx_emac.h
* @brief Contains all macro definitions and function prototypes
* support for Ethernet MAC firmware library on LPC17xx
* @version 2.0
* @date 21. May. 2010
* @author NXP MCU SW Application Team
*
* Copyright(C) 2010, 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.
**********************************************************************/
/* Peripheral group ----------------------------------------------------------- */
/** @defgroup EMAC EMAC (Ethernet Media Access Controller)
* @ingroup LPC1700CMSIS_FwLib_Drivers
* @{
*/
#ifndef LPC17XX_EMAC_H_
#define LPC17XX_EMAC_H_
/* Includes ------------------------------------------------------------------- */
#include "cmsis.h"
#ifdef __cplusplus
extern "C"
{
#endif
#define MCB_LPC_1768
//#define IAR_LPC_1768
/* Public Macros -------------------------------------------------------------- */
/** @defgroup EMAC_Public_Macros EMAC Public Macros
* @{
*/
/* EMAC PHY status type definitions */
#define EMAC_PHY_STAT_LINK (0) /**< Link Status */
#define EMAC_PHY_STAT_SPEED (1) /**< Speed Status */
#define EMAC_PHY_STAT_DUP (2) /**< Duplex Status */
/* EMAC PHY device Speed definitions */
#define EMAC_MODE_AUTO (0) /**< Auto-negotiation mode */
#define EMAC_MODE_10M_FULL (1) /**< 10Mbps FullDuplex mode */
#define EMAC_MODE_10M_HALF (2) /**< 10Mbps HalfDuplex mode */
#define EMAC_MODE_100M_FULL (3) /**< 100Mbps FullDuplex mode */
#define EMAC_MODE_100M_HALF (4) /**< 100Mbps HalfDuplex mode */
/**
* @}
*/
/* Private Macros ------------------------------------------------------------- */
/** @defgroup EMAC_Private_Macros EMAC Private Macros
* @{
*/
/* EMAC Memory Buffer configuration for 16K Ethernet RAM */
#define EMAC_NUM_RX_FRAG 4 /**< Num.of RX Fragments 4*1536= 6.0kB */
#define EMAC_NUM_TX_FRAG 3 /**< Num.of TX Fragments 3*1536= 4.6kB */
#define EMAC_ETH_MAX_FLEN 1536 /**< Max. Ethernet Frame Size */
#define EMAC_TX_FRAME_TOUT 0x00100000 /**< Frame Transmit timeout count */
/* --------------------- BIT DEFINITIONS -------------------------------------- */
/*********************************************************************//**
* Macro defines for MAC Configuration Register 1
**********************************************************************/
#define EMAC_MAC1_REC_EN 0x00000001 /**< Receive Enable */
#define EMAC_MAC1_PASS_ALL 0x00000002 /**< Pass All Receive Frames */
#define EMAC_MAC1_RX_FLOWC 0x00000004 /**< RX Flow Control */
#define EMAC_MAC1_TX_FLOWC 0x00000008 /**< TX Flow Control */
#define EMAC_MAC1_LOOPB 0x00000010 /**< Loop Back Mode */
#define EMAC_MAC1_RES_TX 0x00000100 /**< Reset TX Logic */
#define EMAC_MAC1_RES_MCS_TX 0x00000200 /**< Reset MAC TX Control Sublayer */
#define EMAC_MAC1_RES_RX 0x00000400 /**< Reset RX Logic */
#define EMAC_MAC1_RES_MCS_RX 0x00000800 /**< Reset MAC RX Control Sublayer */
#define EMAC_MAC1_SIM_RES 0x00004000 /**< Simulation Reset */
#define EMAC_MAC1_SOFT_RES 0x00008000 /**< Soft Reset MAC */
/*********************************************************************//**
* Macro defines for MAC Configuration Register 2
**********************************************************************/
#define EMAC_MAC2_FULL_DUP 0x00000001 /**< Full-Duplex Mode */
#define EMAC_MAC2_FRM_LEN_CHK 0x00000002 /**< Frame Length Checking */
#define EMAC_MAC2_HUGE_FRM_EN 0x00000004 /**< Huge Frame Enable */
#define EMAC_MAC2_DLY_CRC 0x00000008 /**< Delayed CRC Mode */
#define EMAC_MAC2_CRC_EN 0x00000010 /**< Append CRC to every Frame */
#define EMAC_MAC2_PAD_EN 0x00000020 /**< Pad all Short Frames */
#define EMAC_MAC2_VLAN_PAD_EN 0x00000040 /**< VLAN Pad Enable */
#define EMAC_MAC2_ADET_PAD_EN 0x00000080 /**< Auto Detect Pad Enable */
#define EMAC_MAC2_PPREAM_ENF 0x00000100 /**< Pure Preamble Enforcement */
#define EMAC_MAC2_LPREAM_ENF 0x00000200 /**< Long Preamble Enforcement */
#define EMAC_MAC2_NO_BACKOFF 0x00001000 /**< No Backoff Algorithm */
#define EMAC_MAC2_BACK_PRESSURE 0x00002000 /**< Backoff Presurre / No Backoff */
#define EMAC_MAC2_EXCESS_DEF 0x00004000 /**< Excess Defer */
/*********************************************************************//**
* Macro defines for Back-to-Back Inter-Packet-Gap Register
**********************************************************************/
/** Programmable field representing the nibble time offset of the minimum possible period
* between the end of any transmitted packet to the beginning of the next */
#define EMAC_IPGT_BBIPG(n) (n&0x7F)
/** Recommended value for Full Duplex of Programmable field representing the nibble time
* offset of the minimum possible period between the end of any transmitted packet to the
* beginning of the next */
#define EMAC_IPGT_FULL_DUP (EMAC_IPGT_BBIPG(0x15))
/** Recommended value for Half Duplex of Programmable field representing the nibble time
* offset of the minimum possible period between the end of any transmitted packet to the
* beginning of the next */
#define EMAC_IPGT_HALF_DUP (EMAC_IPGT_BBIPG(0x12))
/*********************************************************************//**
* Macro defines for Non Back-to-Back Inter-Packet-Gap Register
**********************************************************************/
/** Programmable field representing the Non-Back-to-Back Inter-Packet-Gap */
#define EMAC_IPGR_NBBIPG_P2(n) (n&0x7F)
/** Recommended value for Programmable field representing the Non-Back-to-Back Inter-Packet-Gap Part 1 */
#define EMAC_IPGR_P2_DEF (EMAC_IPGR_NBBIPG_P2(0x12))
/** Programmable field representing the optional carrierSense window referenced in
* IEEE 802.3/4.2.3.2.1 'Carrier Deference' */
#define EMAC_IPGR_NBBIPG_P1(n) ((n&0x7F)<<8)
/** Recommended value for Programmable field representing the Non-Back-to-Back Inter-Packet-Gap Part 2 */
#define EMAC_IPGR_P1_DEF EMAC_IPGR_NBBIPG_P1(0x0C)
/*********************************************************************//**
* Macro defines for Collision Window/Retry Register
**********************************************************************/
/** Programmable field specifying the number of retransmission attempts following a collision before
* aborting the packet due to excessive collisions */
#define EMAC_CLRT_MAX_RETX(n) (n&0x0F)
/** Programmable field representing the slot time or collision window during which collisions occur
* in properly configured networks */
#define EMAC_CLRT_COLL(n) ((n&0x3F)<<8)
/** Default value for Collision Window / Retry register */
#define EMAC_CLRT_DEF ((EMAC_CLRT_MAX_RETX(0x0F))|(EMAC_CLRT_COLL(0x37)))
/*********************************************************************//**
* Macro defines for Maximum Frame Register
**********************************************************************/
/** Represents a maximum receive frame of 1536 octets */
#define EMAC_MAXF_MAXFRMLEN(n) (n&0xFFFF)
/*********************************************************************//**
* Macro defines for PHY Support Register
**********************************************************************/
#define EMAC_SUPP_SPEED 0x00000100 /**< Reduced MII Logic Current Speed */
#define EMAC_SUPP_RES_RMII 0x00000800 /**< Reset Reduced MII Logic */
/*********************************************************************//**
* Macro defines for Test Register
**********************************************************************/
#define EMAC_TEST_SHCUT_PQUANTA 0x00000001 /**< Shortcut Pause Quanta */
#define EMAC_TEST_TST_PAUSE 0x00000002 /**< Test Pause */
#define EMAC_TEST_TST_BACKP 0x00000004 /**< Test Back Pressure */
/*********************************************************************//**
* Macro defines for MII Management Configuration Register
**********************************************************************/
#define EMAC_MCFG_SCAN_INC 0x00000001 /**< Scan Increment PHY Address */
#define EMAC_MCFG_SUPP_PREAM 0x00000002 /**< Suppress Preamble */
#define EMAC_MCFG_CLK_SEL(n) ((n&0x0F)<<2) /**< Clock Select Field */
#define EMAC_MCFG_RES_MII 0x00008000 /**< Reset MII Management Hardware */
#define EMAC_MCFG_MII_MAXCLK 2500000UL /**< MII Clock max */
/*********************************************************************//**
* Macro defines for MII Management Command Register
**********************************************************************/
#define EMAC_MCMD_READ 0x00000001 /**< MII Read */
#define EMAC_MCMD_SCAN 0x00000002 /**< MII Scan continuously */
#define EMAC_MII_WR_TOUT 0x00050000 /**< MII Write timeout count */
#define EMAC_MII_RD_TOUT 0x00050000 /**< MII Read timeout count */
/*********************************************************************//**
* Macro defines for MII Management Address Register
**********************************************************************/
#define EMAC_MADR_REG_ADR(n) (n&0x1F) /**< MII Register Address field */
#define EMAC_MADR_PHY_ADR(n) ((n&0x1F)<<8) /**< PHY Address Field */
/*********************************************************************//**
* Macro defines for MII Management Write Data Register
**********************************************************************/
#define EMAC_MWTD_DATA(n) (n&0xFFFF) /**< Data field for MMI Management Write Data register */
/*********************************************************************//**
* Macro defines for MII Management Read Data Register
**********************************************************************/
#define EMAC_MRDD_DATA(n) (n&0xFFFF) /**< Data field for MMI Management Read Data register */
/*********************************************************************//**
* Macro defines for MII Management Indicators Register
**********************************************************************/
#define EMAC_MIND_BUSY 0x00000001 /**< MII is Busy */
#define EMAC_MIND_SCAN 0x00000002 /**< MII Scanning in Progress */
#define EMAC_MIND_NOT_VAL 0x00000004 /**< MII Read Data not valid */
#define EMAC_MIND_MII_LINK_FAIL 0x00000008 /**< MII Link Failed */
/* Station Address 0 Register */
/* Station Address 1 Register */
/* Station Address 2 Register */
/* Control register definitions --------------------------------------------------------------------------- */
/*********************************************************************//**
* Macro defines for Command Register
**********************************************************************/
#define EMAC_CR_RX_EN 0x00000001 /**< Enable Receive */
#define EMAC_CR_TX_EN 0x00000002 /**< Enable Transmit */
#define EMAC_CR_REG_RES 0x00000008 /**< Reset Host Registers */
#define EMAC_CR_TX_RES 0x00000010 /**< Reset Transmit Datapath */
#define EMAC_CR_RX_RES 0x00000020 /**< Reset Receive Datapath */
#define EMAC_CR_PASS_RUNT_FRM 0x00000040 /**< Pass Runt Frames */
#define EMAC_CR_PASS_RX_FILT 0x00000080 /**< Pass RX Filter */
#define EMAC_CR_TX_FLOW_CTRL 0x00000100 /**< TX Flow Control */
#define EMAC_CR_RMII 0x00000200 /**< Reduced MII Interface */
#define EMAC_CR_FULL_DUP 0x00000400 /**< Full Duplex */
/*********************************************************************//**
* Macro defines for Status Register
**********************************************************************/
#define EMAC_SR_RX_EN 0x00000001 /**< Enable Receive */
#define EMAC_SR_TX_EN 0x00000002 /**< Enable Transmit */
/*********************************************************************//**
* Macro defines for Transmit Status Vector 0 Register
**********************************************************************/
#define EMAC_TSV0_CRC_ERR 0x00000001 /**< CRC error */
#define EMAC_TSV0_LEN_CHKERR 0x00000002 /**< Length Check Error */
#define EMAC_TSV0_LEN_OUTRNG 0x00000004 /**< Length Out of Range */
#define EMAC_TSV0_DONE 0x00000008 /**< Tramsmission Completed */
#define EMAC_TSV0_MCAST 0x00000010 /**< Multicast Destination */
#define EMAC_TSV0_BCAST 0x00000020 /**< Broadcast Destination */
#define EMAC_TSV0_PKT_DEFER 0x00000040 /**< Packet Deferred */
#define EMAC_TSV0_EXC_DEFER 0x00000080 /**< Excessive Packet Deferral */
#define EMAC_TSV0_EXC_COLL 0x00000100 /**< Excessive Collision */
#define EMAC_TSV0_LATE_COLL 0x00000200 /**< Late Collision Occured */
#define EMAC_TSV0_GIANT 0x00000400 /**< Giant Frame */
#define EMAC_TSV0_UNDERRUN 0x00000800 /**< Buffer Underrun */
#define EMAC_TSV0_BYTES 0x0FFFF000 /**< Total Bytes Transferred */
#define EMAC_TSV0_CTRL_FRAME 0x10000000 /**< Control Frame */
#define EMAC_TSV0_PAUSE 0x20000000 /**< Pause Frame */
#define EMAC_TSV0_BACK_PRESS 0x40000000 /**< Backpressure Method Applied */
#define EMAC_TSV0_VLAN 0x80000000 /**< VLAN Frame */
/*********************************************************************//**
* Macro defines for Transmit Status Vector 1 Register
**********************************************************************/
#define EMAC_TSV1_BYTE_CNT 0x0000FFFF /**< Transmit Byte Count */
#define EMAC_TSV1_COLL_CNT 0x000F0000 /**< Transmit Collision Count */
/*********************************************************************//**
* Macro defines for Receive Status Vector Register
**********************************************************************/
#define EMAC_RSV_BYTE_CNT 0x0000FFFF /**< Receive Byte Count */
#define EMAC_RSV_PKT_IGNORED 0x00010000 /**< Packet Previously Ignored */
#define EMAC_RSV_RXDV_SEEN 0x00020000 /**< RXDV Event Previously Seen */
#define EMAC_RSV_CARR_SEEN 0x00040000 /**< Carrier Event Previously Seen */
#define EMAC_RSV_REC_CODEV 0x00080000 /**< Receive Code Violation */
#define EMAC_RSV_CRC_ERR 0x00100000 /**< CRC Error */
#define EMAC_RSV_LEN_CHKERR 0x00200000 /**< Length Check Error */
#define EMAC_RSV_LEN_OUTRNG 0x00400000 /**< Length Out of Range */
#define EMAC_RSV_REC_OK 0x00800000 /**< Frame Received OK */
#define EMAC_RSV_MCAST 0x01000000 /**< Multicast Frame */
#define EMAC_RSV_BCAST 0x02000000 /**< Broadcast Frame */
#define EMAC_RSV_DRIB_NIBB 0x04000000 /**< Dribble Nibble */
#define EMAC_RSV_CTRL_FRAME 0x08000000 /**< Control Frame */
#define EMAC_RSV_PAUSE 0x10000000 /**< Pause Frame */
#define EMAC_RSV_UNSUPP_OPC 0x20000000 /**< Unsupported Opcode */
#define EMAC_RSV_VLAN 0x40000000 /**< VLAN Frame */
/*********************************************************************//**
* Macro defines for Flow Control Counter Register
**********************************************************************/
#define EMAC_FCC_MIRR_CNT(n) (n&0xFFFF) /**< Mirror Counter */
#define EMAC_FCC_PAUSE_TIM(n) ((n&0xFFFF)<<16) /**< Pause Timer */
/*********************************************************************//**
* Macro defines for Flow Control Status Register
**********************************************************************/
#define EMAC_FCS_MIRR_CNT(n) (n&0xFFFF) /**< Mirror Counter Current */
/* Receive filter register definitions -------------------------------------------------------- */
/*********************************************************************//**
* Macro defines for Receive Filter Control Register
**********************************************************************/
#define EMAC_RFC_UCAST_EN 0x00000001 /**< Accept Unicast Frames Enable */
#define EMAC_RFC_BCAST_EN 0x00000002 /**< Accept Broadcast Frames Enable */
#define EMAC_RFC_MCAST_EN 0x00000004 /**< Accept Multicast Frames Enable */
#define EMAC_RFC_UCAST_HASH_EN 0x00000008 /**< Accept Unicast Hash Filter Frames */
#define EMAC_RFC_MCAST_HASH_EN 0x00000010 /**< Accept Multicast Hash Filter Fram.*/
#define EMAC_RFC_PERFECT_EN 0x00000020 /**< Accept Perfect Match Enable */
#define EMAC_RFC_MAGP_WOL_EN 0x00001000 /**< Magic Packet Filter WoL Enable */
#define EMAC_RFC_PFILT_WOL_EN 0x00002000 /**< Perfect Filter WoL Enable */
/*********************************************************************//**
* Macro defines for Receive Filter WoL Status/Clear Registers
**********************************************************************/
#define EMAC_WOL_UCAST 0x00000001 /**< Unicast Frame caused WoL */
#define EMAC_WOL_BCAST 0x00000002 /**< Broadcast Frame caused WoL */
#define EMAC_WOL_MCAST 0x00000004 /**< Multicast Frame caused WoL */
#define EMAC_WOL_UCAST_HASH 0x00000008 /**< Unicast Hash Filter Frame WoL */
#define EMAC_WOL_MCAST_HASH 0x00000010 /**< Multicast Hash Filter Frame WoL */
#define EMAC_WOL_PERFECT 0x00000020 /**< Perfect Filter WoL */
#define EMAC_WOL_RX_FILTER 0x00000080 /**< RX Filter caused WoL */
#define EMAC_WOL_MAG_PACKET 0x00000100 /**< Magic Packet Filter caused WoL */
#define EMAC_WOL_BITMASK 0x01BF /**< Receive Filter WoL Status/Clear bitmasl value */
/* Module control register definitions ---------------------------------------------------- */
/*********************************************************************//**
* Macro defines for Interrupt Status/Enable/Clear/Set Registers
**********************************************************************/
#define EMAC_INT_RX_OVERRUN 0x00000001 /**< Overrun Error in RX Queue */
#define EMAC_INT_RX_ERR 0x00000002 /**< Receive Error */
#define EMAC_INT_RX_FIN 0x00000004 /**< RX Finished Process Descriptors */
#define EMAC_INT_RX_DONE 0x00000008 /**< Receive Done */
#define EMAC_INT_TX_UNDERRUN 0x00000010 /**< Transmit Underrun */
#define EMAC_INT_TX_ERR 0x00000020 /**< Transmit Error */
#define EMAC_INT_TX_FIN 0x00000040 /**< TX Finished Process Descriptors */
#define EMAC_INT_TX_DONE 0x00000080 /**< Transmit Done */
#define EMAC_INT_SOFT_INT 0x00001000 /**< Software Triggered Interrupt */
#define EMAC_INT_WAKEUP 0x00002000 /**< Wakeup Event Interrupt */
/*********************************************************************//**
* Macro defines for Power Down Register
**********************************************************************/
#define EMAC_PD_POWER_DOWN 0x80000000 /**< Power Down MAC */
/* Descriptor and status formats ---------------------------------------------------- */
/*********************************************************************//**
* Macro defines for RX Descriptor Control Word
**********************************************************************/
#define EMAC_RCTRL_SIZE(n) (n&0x7FF) /**< Buffer size field */
#define EMAC_RCTRL_INT 0x80000000 /**< Generate RxDone Interrupt */
/*********************************************************************//**
* Macro defines for RX Status Hash CRC Word
**********************************************************************/
#define EMAC_RHASH_SA 0x000001FF /**< Hash CRC for Source Address */
#define EMAC_RHASH_DA 0x001FF000 /**< Hash CRC for Destination Address */
/*********************************************************************//**
* Macro defines for RX Status Information Word
**********************************************************************/
#define EMAC_RINFO_SIZE 0x000007FF /**< Data size in bytes */
#define EMAC_RINFO_CTRL_FRAME 0x00040000 /**< Control Frame */
#define EMAC_RINFO_VLAN 0x00080000 /**< VLAN Frame */
#define EMAC_RINFO_FAIL_FILT 0x00100000 /**< RX Filter Failed */
#define EMAC_RINFO_MCAST 0x00200000 /**< Multicast Frame */
#define EMAC_RINFO_BCAST 0x00400000 /**< Broadcast Frame */
#define EMAC_RINFO_CRC_ERR 0x00800000 /**< CRC Error in Frame */
#define EMAC_RINFO_SYM_ERR 0x01000000 /**< Symbol Error from PHY */
#define EMAC_RINFO_LEN_ERR 0x02000000 /**< Length Error */
#define EMAC_RINFO_RANGE_ERR 0x04000000 /**< Range Error (exceeded max. size) */
#define EMAC_RINFO_ALIGN_ERR 0x08000000 /**< Alignment Error */
#define EMAC_RINFO_OVERRUN 0x10000000 /**< Receive overrun */
#define EMAC_RINFO_NO_DESCR 0x20000000 /**< No new Descriptor available */
#define EMAC_RINFO_LAST_FLAG 0x40000000 /**< Last Fragment in Frame */
#define EMAC_RINFO_ERR 0x80000000 /**< Error Occured (OR of all errors) */
#define EMAC_RINFO_ERR_MASK (EMAC_RINFO_FAIL_FILT | EMAC_RINFO_CRC_ERR | EMAC_RINFO_SYM_ERR | \
EMAC_RINFO_LEN_ERR | EMAC_RINFO_ALIGN_ERR | EMAC_RINFO_OVERRUN)
/*********************************************************************//**
* Macro defines for TX Descriptor Control Word
**********************************************************************/
#define EMAC_TCTRL_SIZE 0x000007FF /**< Size of data buffer in bytes */
#define EMAC_TCTRL_OVERRIDE 0x04000000 /**< Override Default MAC Registers */
#define EMAC_TCTRL_HUGE 0x08000000 /**< Enable Huge Frame */
#define EMAC_TCTRL_PAD 0x10000000 /**< Pad short Frames to 64 bytes */
#define EMAC_TCTRL_CRC 0x20000000 /**< Append a hardware CRC to Frame */
#define EMAC_TCTRL_LAST 0x40000000 /**< Last Descriptor for TX Frame */
#define EMAC_TCTRL_INT 0x80000000 /**< Generate TxDone Interrupt */
/*********************************************************************//**
* Macro defines for TX Status Information Word
**********************************************************************/
#define EMAC_TINFO_COL_CNT 0x01E00000 /**< Collision Count */
#define EMAC_TINFO_DEFER 0x02000000 /**< Packet Deferred (not an error) */
#define EMAC_TINFO_EXCESS_DEF 0x04000000 /**< Excessive Deferral */
#define EMAC_TINFO_EXCESS_COL 0x08000000 /**< Excessive Collision */
#define EMAC_TINFO_LATE_COL 0x10000000 /**< Late Collision Occured */
#define EMAC_TINFO_UNDERRUN 0x20000000 /**< Transmit Underrun */
#define EMAC_TINFO_NO_DESCR 0x40000000 /**< No new Descriptor available */
#define EMAC_TINFO_ERR 0x80000000 /**< Error Occured (OR of all errors) */
#ifdef MCB_LPC_1768
/* DP83848C PHY definition ------------------------------------------------------------ */
/** PHY device reset time out definition */
#define EMAC_PHY_RESP_TOUT 0x100000UL
/* ENET Device Revision ID */
#define EMAC_OLD_EMAC_MODULE_ID 0x39022000 /**< Rev. ID for first rev '-' */
/*********************************************************************//**
* Macro defines for DP83848C PHY Registers
**********************************************************************/
#define EMAC_PHY_REG_BMCR 0x00 /**< Basic Mode Control Register */
#define EMAC_PHY_REG_BMSR 0x01 /**< Basic Mode Status Register */
#define EMAC_PHY_REG_IDR1 0x02 /**< PHY Identifier 1 */
#define EMAC_PHY_REG_IDR2 0x03 /**< PHY Identifier 2 */
#define EMAC_PHY_REG_ANAR 0x04 /**< Auto-Negotiation Advertisement */
#define EMAC_PHY_REG_ANLPAR 0x05 /**< Auto-Neg. Link Partner Abitily */
#define EMAC_PHY_REG_ANER 0x06 /**< Auto-Neg. Expansion Register */
#define EMAC_PHY_REG_ANNPTR 0x07 /**< Auto-Neg. Next Page TX */
#define EMAC_PHY_REG_LPNPA 0x08
/*********************************************************************//**
* Macro defines for PHY Extended Registers
**********************************************************************/
#define EMAC_PHY_REG_STS 0x10 /**< Status Register */
#define EMAC_PHY_REG_MICR 0x11 /**< MII Interrupt Control Register */
#define EMAC_PHY_REG_MISR 0x12 /**< MII Interrupt Status Register */
#define EMAC_PHY_REG_FCSCR 0x14 /**< False Carrier Sense Counter */
#define EMAC_PHY_REG_RECR 0x15 /**< Receive Error Counter */
#define EMAC_PHY_REG_PCSR 0x16 /**< PCS Sublayer Config. and Status */
#define EMAC_PHY_REG_RBR 0x17 /**< RMII and Bypass Register */
#define EMAC_PHY_REG_LEDCR 0x18 /**< LED Direct Control Register */
#define EMAC_PHY_REG_PHYCR 0x19 /**< PHY Control Register */
#define EMAC_PHY_REG_10BTSCR 0x1A /**< 10Base-T Status/Control Register */
#define EMAC_PHY_REG_CDCTRL1 0x1B /**< CD Test Control and BIST Extens. */
#define EMAC_PHY_REG_EDCR 0x1D /**< Energy Detect Control Register */
/*********************************************************************//**
* Macro defines for PHY Basic Mode Control Register
**********************************************************************/
#define EMAC_PHY_BMCR_RESET (1<<15) /**< Reset bit */
#define EMAC_PHY_BMCR_LOOPBACK (1<<14) /**< Loop back */
#define EMAC_PHY_BMCR_SPEED_SEL (1<<13) /**< Speed selection */
#define EMAC_PHY_BMCR_AN (1<<12) /**< Auto Negotiation */
#define EMAC_PHY_BMCR_POWERDOWN (1<<11) /**< Power down mode */
#define EMAC_PHY_BMCR_ISOLATE (1<<10) /**< Isolate */
#define EMAC_PHY_BMCR_RE_AN (1<<9) /**< Restart auto negotiation */
#define EMAC_PHY_BMCR_DUPLEX (1<<8) /**< Duplex mode */
/*********************************************************************//**
* Macro defines for PHY Basic Mode Status Status Register
**********************************************************************/
#define EMAC_PHY_BMSR_100BE_T4 (1<<15) /**< 100 base T4 */
#define EMAC_PHY_BMSR_100TX_FULL (1<<14) /**< 100 base full duplex */
#define EMAC_PHY_BMSR_100TX_HALF (1<<13) /**< 100 base half duplex */
#define EMAC_PHY_BMSR_10BE_FULL (1<<12) /**< 10 base T full duplex */
#define EMAC_PHY_BMSR_10BE_HALF (1<<11) /**< 10 base T half duplex */
#define EMAC_PHY_BMSR_NOPREAM (1<<6) /**< MF Preamable Supress */
#define EMAC_PHY_BMSR_AUTO_DONE (1<<5) /**< Auto negotiation complete */
#define EMAC_PHY_BMSR_REMOTE_FAULT (1<<4) /**< Remote fault */
#define EMAC_PHY_BMSR_NO_AUTO (1<<3) /**< Auto Negotiation ability */
#define EMAC_PHY_BMSR_LINK_ESTABLISHED (1<<2) /**< Link status */
/*********************************************************************//**
* Macro defines for PHY Status Register
**********************************************************************/
#define EMAC_PHY_SR_REMOTE_FAULT (1<<6) /**< Remote Fault */
#define EMAC_PHY_SR_JABBER (1<<5) /**< Jabber detect */
#define EMAC_PHY_SR_AUTO_DONE (1<<4) /**< Auto Negotiation complete */
#define EMAC_PHY_SR_LOOPBACK (1<<3) /**< Loop back status */
#define EMAC_PHY_SR_DUP (1<<2) /**< Duplex status */
#define EMAC_PHY_SR_SPEED (1<<1) /**< Speed status */
#define EMAC_PHY_SR_LINK (1<<0) /**< Link Status */
#define EMAC_PHY_FULLD_100M 0x2100 /**< Full Duplex 100Mbit */
#define EMAC_PHY_HALFD_100M 0x2000 /**< Half Duplex 100Mbit */
#define EMAC_PHY_FULLD_10M 0x0100 /**< Full Duplex 10Mbit */
#define EMAC_PHY_HALFD_10M 0x0000 /**< Half Duplex 10MBit */
#define EMAC_PHY_AUTO_NEG 0x3000 /**< Select Auto Negotiation */
#define EMAC_DEF_ADR 0x0100 /**< Default PHY device address */
#define EMAC_DP83848C_ID 0x20005C90 /**< PHY Identifier */
#define EMAC_PHY_SR_100_SPEED ((1<<14)|(1<<13))
#define EMAC_PHY_SR_FULL_DUP ((1<<14)|(1<<12))
#define EMAC_PHY_BMSR_LINK_STATUS (1<<2) /**< Link status */
#elif defined(IAR_LPC_1768)
/* KSZ8721BL PHY definition ------------------------------------------------------------ */
/** PHY device reset time out definition */
#define EMAC_PHY_RESP_TOUT 0x100000UL
/* ENET Device Revision ID */
#define EMAC_OLD_EMAC_MODULE_ID 0x39022000 /**< Rev. ID for first rev '-' */
/*********************************************************************//**
* Macro defines for KSZ8721BL PHY Registers
**********************************************************************/
#define EMAC_PHY_REG_BMCR 0x00 /**< Basic Mode Control Register */
#define EMAC_PHY_REG_BMSR 0x01 /**< Basic Mode Status Register */
#define EMAC_PHY_REG_IDR1 0x02 /**< PHY Identifier 1 */
#define EMAC_PHY_REG_IDR2 0x03 /**< PHY Identifier 2 */
#define EMAC_PHY_REG_ANAR 0x04 /**< Auto-Negotiation Advertisement */
#define EMAC_PHY_REG_ANLPAR 0x05 /**< Auto-Neg. Link Partner Abitily */
#define EMAC_PHY_REG_ANER 0x06 /**< Auto-Neg. Expansion Register */
#define EMAC_PHY_REG_ANNPTR 0x07 /**< Auto-Neg. Next Page TX */
#define EMAC_PHY_REG_LPNPA 0x08 /**< Link Partner Next Page Ability */
#define EMAC_PHY_REG_REC 0x15 /**< RXError Counter Register */
#define EMAC_PHY_REG_ISC 0x1b /**< Interrupt Control/Status Register */
#define EMAC_PHY_REG_100BASE 0x1f /**< 100BASE-TX PHY Control Register */
/*********************************************************************//**
* Macro defines for PHY Basic Mode Control Register
**********************************************************************/
#define EMAC_PHY_BMCR_RESET (1<<15) /**< Reset bit */
#define EMAC_PHY_BMCR_LOOPBACK (1<<14) /**< Loop back */
#define EMAC_PHY_BMCR_SPEED_SEL (1<<13) /**< Speed selection */
#define EMAC_PHY_BMCR_AN (1<<12) /**< Auto Negotiation */
#define EMAC_PHY_BMCR_POWERDOWN (1<<11) /**< Power down mode */
#define EMAC_PHY_BMCR_ISOLATE (1<<10) /**< Isolate */
#define EMAC_PHY_BMCR_RE_AN (1<<9) /**< Restart auto negotiation */
#define EMAC_PHY_BMCR_DUPLEX (1<<8) /**< Duplex mode */
#define EMAC_PHY_BMCR_COLLISION (1<<7) /**< Collision test */
#define EMAC_PHY_BMCR_TXDIS (1<<0) /**< Disable transmit */
/*********************************************************************//**
* Macro defines for PHY Basic Mode Status Register
**********************************************************************/
#define EMAC_PHY_BMSR_100BE_T4 (1<<15) /**< 100 base T4 */
#define EMAC_PHY_BMSR_100TX_FULL (1<<14) /**< 100 base full duplex */
#define EMAC_PHY_BMSR_100TX_HALF (1<<13) /**< 100 base half duplex */
#define EMAC_PHY_BMSR_10BE_FULL (1<<12) /**< 10 base T full duplex */
#define EMAC_PHY_BMSR_10BE_HALF (1<<11) /**< 10 base T half duplex */
#define EMAC_PHY_BMSR_NOPREAM (1<<6) /**< MF Preamable Supress */
#define EMAC_PHY_BMSR_AUTO_DONE (1<<5) /**< Auto negotiation complete */
#define EMAC_PHY_BMSR_REMOTE_FAULT (1<<4) /**< Remote fault */
#define EMAC_PHY_BMSR_NO_AUTO (1<<3) /**< Auto Negotiation ability */
#define EMAC_PHY_BMSR_LINK_STATUS (1<<2) /**< Link status */
#define EMAC_PHY_BMSR_JABBER_DETECT (1<<1) /**< Jabber detect */
#define EMAC_PHY_BMSR_EXTEND (1<<0) /**< Extended support */
/*********************************************************************//**
* Macro defines for PHY Identifier
**********************************************************************/
/* PHY Identifier 1 bitmap definitions */
#define EMAC_PHY_IDR1(n) (n & 0xFFFF) /**< PHY ID1 Number */
/* PHY Identifier 2 bitmap definitions */
#define EMAC_PHY_IDR2(n) (n & 0xFFFF) /**< PHY ID2 Number */
/*********************************************************************//**
* Macro defines for Auto-Negotiation Advertisement
**********************************************************************/
#define EMAC_PHY_AN_NEXTPAGE (1<<15) /**< Next page capable */
#define EMAC_PHY_AN_REMOTE_FAULT (1<<13) /**< Remote Fault support */
#define EMAC_PHY_AN_PAUSE (1<<10) /**< Pause support */
#define EMAC_PHY_AN_100BASE_T4 (1<<9) /**< T4 capable */
#define EMAC_PHY_AN_100BASE_TX_FD (1<<8) /**< TX with Full-duplex capable */
#define EMAC_PHY_AN_100BASE_TX (1<<7) /**< TX capable */
#define EMAC_PHY_AN_10BASE_T_FD (1<<6) /**< 10Mbps with full-duplex capable */
#define EMAC_PHY_AN_10BASE_T (1<<5) /**< 10Mbps capable */
#define EMAC_PHY_AN_FIELD(n) (n & 0x1F) /**< Selector Field */
#define EMAC_PHY_FULLD_100M 0x2100 /**< Full Duplex 100Mbit */
#define EMAC_PHY_HALFD_100M 0x2000 /**< Half Duplex 100Mbit */
#define EMAC_PHY_FULLD_10M 0x0100 /**< Full Duplex 10Mbit */
#define EMAC_PHY_HALFD_10M 0x0000 /**< Half Duplex 10MBit */
#define EMAC_PHY_AUTO_NEG 0x3000 /**< Select Auto Negotiation */
#define EMAC_PHY_SR_100_SPEED ((1<<14)|(1<<13))
#define EMAC_PHY_SR_FULL_DUP ((1<<14)|(1<<12))
#define EMAC_DEF_ADR (0x01<<8) /**< Default PHY device address */
#define EMAC_KSZ8721BL_ID ((0x22 << 16) | 0x1619 ) /**< PHY Identifier */
#endif
/**
* @}
*/
/* Public Types --------------------------------------------------------------- */
/** @defgroup EMAC_Public_Types EMAC Public Types
* @{
*/
/* Descriptor and status formats ---------------------------------------------- */
/**
* @brief RX Descriptor structure type definition
*/
typedef struct {
uint32_t Packet; /**< Receive Packet Descriptor */
uint32_t Ctrl; /**< Receive Control Descriptor */
} RX_Desc;
/**
* @brief RX Status structure type definition
*/
typedef struct {
uint32_t Info; /**< Receive Information Status */
uint32_t HashCRC; /**< Receive Hash CRC Status */
} RX_Stat;
/**
* @brief TX Descriptor structure type definition
*/
typedef struct {
uint32_t Packet; /**< Transmit Packet Descriptor */
uint32_t Ctrl; /**< Transmit Control Descriptor */
} TX_Desc;
/**
* @brief TX Status structure type definition
*/
typedef struct {
uint32_t Info; /**< Transmit Information Status */
} TX_Stat;
/**
* @brief TX Data Buffer structure definition
*/
typedef struct {
uint32_t ulDataLen; /**< Data length */
uint32_t *pbDataBuf; /**< A word-align data pointer to data buffer */
} EMAC_PACKETBUF_Type;
/**
* @brief EMAC configuration structure definition
*/
typedef struct {
uint32_t Mode; /**< Supported EMAC PHY device speed, should be one of the following:
- EMAC_MODE_AUTO
- EMAC_MODE_10M_FULL
- EMAC_MODE_10M_HALF
- EMAC_MODE_100M_FULL
- EMAC_MODE_100M_HALF
*/
uint8_t *pbEMAC_Addr; /**< Pointer to EMAC Station address that contains 6-bytes
of MAC address, it must be sorted in order (bEMAC_Addr[0]..[5])
*/
} EMAC_CFG_Type;
/** Ethernet block power/clock control bit*/
#define CLKPWR_PCONP_PCENET ((uint32_t)(1<<30))
#ifdef __cplusplus
}
#endif
#endif /* LPC17XX_EMAC_H_ */
/**
* @}
*/
/**
* @}
*/
/* --------------------------------- End Of File ------------------------------ */

View File

@@ -0,0 +1,104 @@
/**********************************************************************
* $Id$ lpc_emac_config.h 2011-11-20
*//**
* @file lpc_emac_config.h
* @brief PHY and EMAC configuration file
* @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_EMAC_CONFIG_H
#define __LPC_EMAC_CONFIG_H
#define LPC17_ETH_IF_NAME "lpc"
#define LPC17_ETH_HWADDR_SIZE 6
#define DEFAULT_THREAD_STACKSIZE 512
/** @defgroup lwip_phy_config PHY configuration
* @ingroup lwip_phy
*
* Configuration options for the PHY connected to the LPC EMAC.
* @{
*/
/** \brief The PHY address connected the to MII/RMII
*/
#define LPC_PHYDEF_PHYADDR 1 /**< The PHY address on the PHY device. */
/** \brief Enable autonegotiation mode.
* If this is enabled, the PHY will attempt to auto-negotiate the
* best link mode if the PHY supports it. If this is not enabled,
* the PHY_USE_FULL_DUPLEX and PHY_USE_100MBS defines will be
* used to select the link mode. Note that auto-negotiation may
* take a few seconds to complete.
*/
#define PHY_USE_AUTONEG 1 /**< Enables auto-negotiation mode. */
/** \brief Sets up the PHY interface to either full duplex operation or
* half duplex operation if PHY_USE_AUTONEG is not enabled.
*/
#define PHY_USE_FULL_DUPLEX 1 /**< Sets duplex mode to full. */
/** \brief Sets up the PHY interface to either 100MBS operation or 10MBS
* operation if PHY_USE_AUTONEG is not enabled.
*/
#define PHY_USE_100MBS 1 /**< Sets data rate to 100Mbps. */
/**
* @}
*/
/** @defgroup emac_config EMAC configuration
*
* Configuration options for the LPC EMAC.
* @{
*/
/** \brief Selects RMII or MII connection type in the EMAC peripheral
*/
#define LPC_EMAC_RMII 1 /**< Use the RMII or MII driver variant .*/
/** \brief Defines the number of descriptors used for RX. This
* must be a minimum value of 2.
*/
#define LPC_NUM_BUFF_RXDESCS 4
/** \brief Defines the number of descriptors used for TX. Must
* be a minimum value of 2.
*/
#define LPC_NUM_BUFF_TXDESCS 9
/** \brief Set this define to 1 to enable bounce buffers for transmit memory
* buffers that cannot be sent via the zero-copy method. Some chained
* buffers may have a payload address that links to an area of memory that
* cannot be used for transmit DMA operations. If this define is
* set to 1, an extra check will be made with the buffers. If a buffer
* is determined to be non-usable for zero-copy, a temporary bounce
* buffer will be created and used instead.
*/
#define LPC_TX_PBUF_BOUNCE_EN 1
/**
* @}
*/
#endif /* __LPC_EMAC_CONFIG_H */
/* --------------------------------- End Of File ------------------------------ */

View File

@@ -0,0 +1,140 @@
/**********************************************************************
* $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_
/* 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] lpc17_emac LPC17 EMAC
*/
int32_t lpc_phy_sts_sm(LPC17_EMAC *lpc17_emac);
/** \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] lpc17_emac LPC17 EMAC
* \param[in] rmii If set, configures the PHY for RMII mode
* \return ERR_OK if the setup was successful, otherwise ERR_TIMEOUT
*/
bool lpc_phy_init(LPC17_EMAC *lpc17_emac, 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(uint32_t PhyReg, uint32_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
*/
bool lpc_mii_write(uint32_t PhyReg, uint32_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
*/
uint32_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
*/
uint32_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
* \param[in] data Pointer to where to save data read via MII
* \returns 0 if the read was successful, otherwise !0
*
*/
bool lpc_mii_read(uint32_t PhyReg, uint32_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
*/
void lpc_mii_read_noblock(uint32_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);
#endif /* __LPC_PHY_H_ */
/* --------------------------------- End Of File ------------------------------ */

View File

@@ -0,0 +1,433 @@
/**********************************************************************
* $Id$ lpc_phy_dp83848.c 2011-11-20
*//**
* @file lpc_phy_dp83848.c
* @brief DP83848C 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 "netsocket/nsapi_types.h"
#include "lpc_emac_config.h"
#include "lpc17_emac.h"
#include "lpc_phy.h"
#include "lpc17xx_emac.h"
/** @defgroup dp83848_phy PHY status and control for the DP83848.
* @ingroup lwip_phy
*
* Various functions for controlling and monitoring the status of the
* DP83848 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 DP83848 PHY register offsets */
#define DP8_BMCR_REG 0x0 /**< Basic Mode Control Register */
#define DP8_BMSR_REG 0x1 /**< Basic Mode Status Reg */
#define DP8_IDR1_REG 0x2 /**< Basic Mode Status Reg */
#define DP8_IDR2_REG 0x3 /**< Basic Mode Status Reg */
#define DP8_ANADV_REG 0x4 /**< Auto_Neg Advt Reg */
#define DP8_ANLPA_REG 0x5 /**< Auto_neg Link Partner Ability Reg */
#define DP8_ANEEXP_REG 0x6 /**< Auto-neg Expansion Reg */
#define DP8_PHY_STAT_REG 0x10 /**< PHY Status Register */
#define DP8_PHY_INT_CTL_REG 0x11 /**< PHY Interrupt Control Register */
#define DP8_PHY_RBR_REG 0x17 /**< PHY RMII and Bypass Register */
#define DP8_PHY_STS_REG 0x19 /**< PHY Status Register */
#define DP8_PHY_SCSR_REG 0x1f /**< PHY Special Control/Status Register (LAN8720) */
/** \brief DP83848 Control register definitions */
#define DP8_RESET (1 << 15) /**< 1= S/W Reset */
#define DP8_LOOPBACK (1 << 14) /**< 1=loopback Enabled */
#define DP8_SPEED_SELECT (1 << 13) /**< 1=Select 100MBps */
#define DP8_AUTONEG (1 << 12) /**< 1=Enable auto-negotiation */
#define DP8_POWER_DOWN (1 << 11) /**< 1=Power down PHY */
#define DP8_ISOLATE (1 << 10) /**< 1=Isolate PHY */
#define DP8_RESTART_AUTONEG (1 << 9) /**< 1=Restart auto-negoatiation */
#define DP8_DUPLEX_MODE (1 << 8) /**< 1=Full duplex mode */
#define DP8_COLLISION_TEST (1 << 7) /**< 1=Perform collsion test */
/** \brief DP83848 Status register definitions */
#define DP8_100BASE_T4 (1 << 15) /**< T4 mode */
#define DP8_100BASE_TX_FD (1 << 14) /**< 100MBps full duplex */
#define DP8_100BASE_TX_HD (1 << 13) /**< 100MBps half duplex */
#define DP8_10BASE_T_FD (1 << 12) /**< 100Bps full duplex */
#define DP8_10BASE_T_HD (1 << 11) /**< 10MBps half duplex */
#define DP8_MF_PREAMB_SUPPR (1 << 6) /**< Preamble suppress */
#define DP8_AUTONEG_COMP (1 << 5) /**< Auto-negotation complete */
#define DP8_RMT_FAULT (1 << 4) /**< Fault */
#define DP8_AUTONEG_ABILITY (1 << 3) /**< Auto-negotation supported */
#define DP8_LINK_STATUS (1 << 2) /**< 1=Link active */
#define DP8_JABBER_DETECT (1 << 1) /**< Jabber detect */
#define DP8_EXTEND_CAPAB (1 << 0) /**< Supports extended capabilities */
/** \brief DP83848 PHY RBR MII dode definitions */
#define DP8_RBR_RMII_MODE (1 << 5) /**< Use RMII mode */
/** \brief DP83848 PHY status definitions */
#define DP8_REMOTEFAULT (1 << 6) /**< Remote fault */
#define DP8_FULLDUPLEX (1 << 2) /**< 1=full duplex */
#define DP8_SPEED10MBPS (1 << 1) /**< 1=10MBps speed */
#define DP8_VALID_LINK (1 << 0) /**< 1=Link active */
/** \brief DP83848 PHY ID register definitions */
#define DP8_PHYID1_OUI 0x2000 /**< Expected PHY ID1 */
#define DP8_PHYID2_OUI 0x5c90 /**< Expected PHY ID2 */
/** \brief LAN8720 PHY Special Control/Status Register */
#define PHY_SCSR_100MBIT 0x0008 /**< Speed: 1=100 MBit, 0=10Mbit */
#define PHY_SCSR_DUPLEX 0x0010 /**< PHY Duplex Mask */
/** \brief Link status bits */
#define LNK_STAT_VALID 0x01
#define LNK_STAT_FULLDUPLEX 0x02
#define LNK_STAT_SPEED10MPS 0x04
/** \brief PHY ID definitions */
#define DP83848C_ID 0x20005C90 /**< PHY Identifier - DP83848C */
#define LAN8720_ID 0x0007C0F0 /**< PHY Identifier - LAN8720 */
#define KSZ8041_ID 0x00221510 /**< PHY Identifier - KSZ8041 */
/** \brief PHY status structure used to indicate current status of PHY.
*/
typedef struct {
unsigned int phy_speed_100mbs:1; /**< 10/100 MBS connection speed flag. */
unsigned int phy_full_duplex:1; /**< Half/full duplex connection speed flag. */
unsigned int phy_link_active:1; /**< 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 int32_t phyustate;
/** \brief Holds the PHY ID */
static uint32_t phy_id;
/** \brief Temporary holder of link status for LAN7420 */
static uint32_t phy_lan7420_sts_tmp;
/* Write a value via the MII link (non-blocking) */
void lpc_mii_write_noblock(uint32_t PhyReg, uint32_t Value)
{
/* Write value at PHY address and register */
LPC_EMAC->MADR = (LPC_PHYDEF_PHYADDR << 8) | PhyReg;
LPC_EMAC->MWTD = Value;
}
/* Write a value via the MII link (blocking) */
bool lpc_mii_write(uint32_t PhyReg, uint32_t Value)
{
uint32_t mst = 250;
int8_t sts = 0;
/* Write value at PHY address and register */
lpc_mii_write_noblock(PhyReg, Value);
/* Wait for unbusy status */
while (mst > 0) {
sts = LPC_EMAC->MIND;
if ((sts & EMAC_MIND_BUSY) == 0)
mst = 0;
else {
mst--;
osDelay(1);
}
}
if (sts != 0)
return false;
return true;
}
/* Reads current MII link busy status */
uint32_t lpc_mii_is_busy(void)
{
return (uint32_t) (LPC_EMAC->MIND & EMAC_MIND_BUSY);
}
/* Starts a read operation via the MII link (non-blocking) */
uint32_t lpc_mii_read_data(void)
{
uint32_t data = LPC_EMAC->MRDD;
LPC_EMAC->MCMD = 0;
return data;
}
/* Starts a read operation via the MII link (non-blocking) */
void lpc_mii_read_noblock(uint32_t PhyReg)
{
/* Read value at PHY address and register */
LPC_EMAC->MADR = (LPC_PHYDEF_PHYADDR << 8) | PhyReg;
LPC_EMAC->MCMD = EMAC_MCMD_READ;
}
/* Read a value via the MII link (blocking) */
bool lpc_mii_read(uint32_t PhyReg, uint32_t *data)
{
uint32_t mst = 250;
int8_t sts = 0;
/* Read value at PHY address and register */
lpc_mii_read_noblock(PhyReg);
/* Wait for unbusy status */
while (mst > 0) {
sts = LPC_EMAC->MIND & ~EMAC_MIND_MII_LINK_FAIL;
if ((sts & EMAC_MIND_BUSY) == 0) {
mst = 0;
*data = LPC_EMAC->MRDD;
} else {
mst--;
osDelay(1);
}
}
LPC_EMAC->MCMD = 0;
if (sts != 0)
return false;
return true;
}
/** \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] lpc17_emac LPC17 EMAC
* \param[in] linksts Status word from PHY
* \return 1 if the status has changed, otherwise 0
*/
static int32_t lpc_update_phy_sts(LPC17_EMAC *lpc17_emac, uint32_t linksts)
{
int32_t changed = 0;
/* Update link active status */
if (linksts & LNK_STAT_VALID)
physts.phy_link_active = 1;
else
physts.phy_link_active = 0;
/* Full or half duplex */
if (linksts & LNK_STAT_FULLDUPLEX)
physts.phy_full_duplex = 1;
else
physts.phy_full_duplex = 0;
/* Configure 100MBit/10MBit mode. */
if (linksts & LNK_STAT_SPEED10MPS)
physts.phy_speed_100mbs = 0;
else
physts.phy_speed_100mbs = 1;
if (physts.phy_speed_100mbs != olddphysts.phy_speed_100mbs) {
changed = 1;
if (physts.phy_speed_100mbs) {
/* 100MBit mode. */
lpc_emac_set_speed(1);
}
else {
/* 10MBit mode. */
lpc_emac_set_speed(0);
}
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 (physts.phy_link_active) {
lpc17_emac->update_link_status(true);
} else {
lpc17_emac->update_link_status(false);
}
olddphysts.phy_link_active = physts.phy_link_active;
}
return changed;
}
/** \brief Initialize the DP83848 PHY.
*
* This function initializes the DP83848 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] lpc17_emac LPC17 EMAC
* \param[in] rmii If set, configures the PHY for RMII mode
* \return ERR_OK if the setup was successful, otherwise ERR_TIMEOUT
*/
bool lpc_phy_init(LPC17_EMAC *lpc17_emac, int rmii)
{
uint32_t tmp;
int32_t i;
physts.phy_speed_100mbs = olddphysts.phy_speed_100mbs = 0;
physts.phy_full_duplex = olddphysts.phy_full_duplex = 0;
physts.phy_link_active = olddphysts.phy_link_active = 0;
phyustate = 0;
/* Only first read and write are checked for failure */
/* Put the DP83848C in reset mode and wait for completion */
if (!lpc_mii_write(DP8_BMCR_REG, DP8_RESET)) {
return false;
}
i = 400;
while (i > 0) {
osDelay(1); /* 1 ms */
if (!lpc_mii_read(DP8_BMCR_REG, &tmp))
return false;
if (!(tmp & (DP8_RESET | DP8_POWER_DOWN)))
i = -1;
else
i--;
}
/* Timeout? */
if (i == 0)
return false;
// read PHY ID
lpc_mii_read(DP8_IDR1_REG, &tmp);
phy_id = (tmp << 16);
lpc_mii_read(DP8_IDR2_REG, &tmp);
phy_id |= (tmp & 0XFFF0);
/* Setup link based on configuration options */
#if PHY_USE_AUTONEG==1
tmp = DP8_AUTONEG;
#else
tmp = 0;
#endif
#if PHY_USE_100MBS==1
tmp |= DP8_SPEED_SELECT;
#endif
#if PHY_USE_FULL_DUPLEX==1
tmp |= DP8_DUPLEX_MODE;
#endif
lpc_mii_write(DP8_BMCR_REG, tmp);
/* Enable RMII mode for PHY */
if (rmii) {
/* Mode is set with config pins on KSZ8041 */
if (phy_id != KSZ8041_ID)
lpc_mii_write(DP8_PHY_RBR_REG, DP8_RBR_RMII_MODE);
}
/* The link is not set active at this point, but will be detected
later */
return true;
}
/** \brief Phy status update state machine
*
* \param[in] lpc17_emac LPC17 EMAC
* \return 1 if the status has changed, otherwise 0
*/
int32_t lpc_phy_sts_sm(LPC17_EMAC *lpc17_emac)
{
int32_t changed = 0;
uint32_t data = 0;
uint32_t tmp;
switch (phyustate) {
default:
case 0:
if (phy_id == DP83848C_ID) {
lpc_mii_read_noblock(DP8_PHY_STAT_REG);
phyustate = 2;
}
else if (phy_id == LAN8720_ID || phy_id == KSZ8041_ID) {
lpc_mii_read_noblock(DP8_PHY_SCSR_REG);
phyustate = 1;
}
break;
case 1:
if (phy_id == LAN8720_ID || phy_id == KSZ8041_ID) {
tmp = lpc_mii_read_data();
// we get speed and duplex here.
phy_lan7420_sts_tmp = (tmp & PHY_SCSR_DUPLEX) ? LNK_STAT_FULLDUPLEX : 0;
phy_lan7420_sts_tmp |= (tmp & PHY_SCSR_100MBIT) ? 0 : LNK_STAT_SPEED10MPS;
//read the status register to get link status
lpc_mii_read_noblock(DP8_BMSR_REG);
phyustate = 2;
}
break;
case 2:
/* Wait for read status state */
if (!lpc_mii_is_busy()) {
/* Update PHY status */
tmp = lpc_mii_read_data();
if (phy_id == DP83848C_ID) {
// STS register contains all needed status bits
data = (tmp & DP8_VALID_LINK) ? LNK_STAT_VALID : 0;
data |= (tmp & DP8_FULLDUPLEX) ? LNK_STAT_FULLDUPLEX : 0;
data |= (tmp & DP8_SPEED10MBPS) ? LNK_STAT_SPEED10MPS : 0;
}
else if (phy_id == LAN8720_ID || phy_id == KSZ8041_ID) {
// we only get the link status here.
phy_lan7420_sts_tmp |= (tmp & DP8_LINK_STATUS) ? LNK_STAT_VALID : 0;
data = phy_lan7420_sts_tmp;
}
changed = lpc_update_phy_sts(lpc17_emac, data);
phyustate = 0;
}
break;
}
return changed;
}
/**
* @}
*/
/* --------------------------------- End Of File ------------------------------ */

View File

@@ -0,0 +1,3 @@
{
"name": "lpc17-emac"
}