Import Mbed OS hard-float snapshot
This commit is contained in:
@@ -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 ------------------------------ */
|
||||
@@ -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
|
||||
@@ -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 ------------------------------ */
|
||||
@@ -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 ------------------------------ */
|
||||
@@ -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 ------------------------------ */
|
||||
@@ -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 ------------------------------ */
|
||||
@@ -0,0 +1,3 @@
|
||||
{
|
||||
"name": "lpc17-emac"
|
||||
}
|
||||
Reference in New Issue
Block a user