/*
* @briefSimple ethernet example
*
* @note
* Copyright(C) NXP Semiconductors, 2014
* All rights reserved.
*
* @par
* Software that is described herein is for illustrative purposes only
* which provides customers with programming information regarding the
* LPC products. This software is supplied "AS IS" without any warranties of
* any kind, and NXP Semiconductors and its licensor disclaim any and
* all warranties, express or implied, including all implied warranties of
* merchantability, fitness for a particular purpose and non-infringement of
* intellectual property rights. NXP Semiconductors assumes no responsibility
* or liability for the use of the software, conveys no license or rights under any
* patent, copyright, mask work right, or any other intellectual property rights in
* or to any products. NXP Semiconductors reserves the right to make changes
* in the software without notification. NXP Semiconductors also makes no
* representation or warranty that such application will be suitable for the
* specified use without further testing or modification.
*
* @par
* Permission to use, copy, modify, and distribute this software and its
* documentation is hereby granted, under NXP Semiconductors' and its
* licensor's relevant copyrights in the software, without fee, provided that it
* is used in conjunction with NXP Semiconductors microcontrollers. This
* copyright, permission, and disclaimer notice must appear in all copies of
* this code.
*/
#include "board.h"
#include <stdio.h>
#include <string.h>
/*****************************************************************************
* Private types/enumerations/variables
****************************************************************************/
#define ENET_NUM_TX_DESC 4
#define ENET_NUM_RX_DESC 4
#if defined(CHIP_LPC175X_6X)
#define ENET_RX_DESC_BASE (0x2007C000)
#else
/* The Ethernet Block can only access Peripheral SRAM and External Memory. In this example,
Peripheral SRAM is selected for storing descriptors, status arrays and send/receive buffers.*/
#define ENET_RX_DESC_BASE (0x20000000UL)
#endif
#define ENET_RX_STAT_BASE (ENET_RX_DESC_BASE + ENET_NUM_RX_DESC * sizeof(ENET_RXDESC_T))
#define ENET_TX_DESC_BASE (ENET_RX_STAT_BASE + ENET_NUM_RX_DESC * sizeof(ENET_RXSTAT_T))
#define ENET_TX_STAT_BASE (ENET_TX_DESC_BASE + ENET_NUM_TX_DESC * sizeof(ENET_TXDESC_T))
#define ENET_RX_BUF_BASE (ENET_TX_STAT_BASE + ENET_NUM_TX_DESC * sizeof(ENET_TXSTAT_T))
#define ENET_TX_BUF_BASE (ENET_RX_BUF_BASE + ENET_NUM_RX_DESC * ENET_ETH_MAX_FLEN)
#define ENET_RX_BUF(i) (ENET_RX_BUF_BASE + ENET_ETH_MAX_FLEN * i)
#define ENET_TX_BUF(i) (ENET_TX_BUF_BASE + ENET_ETH_MAX_FLEN * i)
STATIC ENET_RXDESC_T *pRXDescs = (ENET_RXDESC_T *) ENET_RX_DESC_BASE;
STATIC ENET_RXSTAT_T *pRXStats = (ENET_RXSTAT_T *) ENET_RX_STAT_BASE;
STATIC ENET_TXDESC_T *pTXDescs = (ENET_TXDESC_T *) ENET_TX_DESC_BASE;
STATIC ENET_TXSTAT_T *pTXStats = (ENET_TXSTAT_T *) ENET_TX_STAT_BASE;
/* Transmit/receive buffers and indices */
STATIC int32_t rxConsumeIdx;
STATIC int32_t txProduceIdx;
/*****************************************************************************
* Public types/enumerations/variables
****************************************************************************/
/*****************************************************************************
* Private functions
****************************************************************************/
/* Local delay function used by the ENET or PHY drivers . This can be
replaced with something more accurate if needed. */
STATIC void localMsDelay(uint32_t ms)
{
ms = ms * 40000;
while (ms > 0) {
ms--;
}
}
/* Initialize MAC descriptors for simple packet receive/transmit */
STATIC void InitDescriptors(void)
{
int i;
/* Setup the descriptor list to a default state */
memset(pTXDescs, 0, ENET_NUM_TX_DESC * sizeof(ENET_TXDESC_T));
memset(pTXStats, 0, ENET_NUM_TX_DESC * sizeof(ENET_TXSTAT_T));
memset(pRXDescs, 0, ENET_NUM_RX_DESC * sizeof(ENET_RXDESC_T));
memset(pRXStats, 0, ENET_NUM_RX_DESC * sizeof(ENET_RXSTAT_T));
rxConsumeIdx = 0;
rxConsumeIdx = 0;
/* Build linked list, CPU is owner of descriptors */
for (i = 0; i < ENET_NUM_RX_DESC; i++) {
pRXDescs.Packet = (uint32_t) ENET_RX_BUF(i);
pRXDescs.Control = ENET_RCTRL_SIZE(ENET_ETH_MAX_FLEN);
pRXStats.StatusInfo = 0;
pRXStats.StatusHashCRC = 0;
}
for (i = 0; i < ENET_NUM_TX_DESC; i++) {
pTXDescs.Packet = (uint32_t) ENET_TX_BUF(i);
pTXDescs.Control = 0;
pTXStats.StatusInfo = 0;
}
/* Setup list pointers in Ethernet controller */
Chip_ENET_InitTxDescriptors(LPC_ETHERNET, pTXDescs, pTXStats, ENET_NUM_TX_DESC);
Chip_ENET_InitRxDescriptors(LPC_ETHERNET, pRXDescs, pRXStats, ENET_NUM_RX_DESC);
}
/* Get the pointer to the Rx buffer storing new received frame */
STATIC void *ENET_RXGet(int32_t *bytes)
{
uint16_t produceIdx;
void *buffer;
produceIdx = Chip_ENET_GetRXProduceIndex(LPC_ETHERNET);
/* This doesn't check status of the received packet */
if (Chip_ENET_GetBufferStatus(LPC_ETHERNET, produceIdx, rxConsumeIdx, ENET_NUM_RX_DESC) != ENET_BUFF_EMPTY) {
/* CPU owns descriptor, so a packet was received */
buffer = (void *) pRXDescs[rxConsumeIdx].Packet;
*bytes = (int32_t) (ENET_RINFO_SIZE(pRXStats[rxConsumeIdx].StatusInfo) - 4);/* Remove CRC */
}
else {
/* Nothing received */
*bytes = 0;
buffer = NULL;
}
return buffer;
}
/* Release Rx Buffer */
STATIC void ENET_RXBuffClaim(void)
{
rxConsumeIdx = Chip_ENET_IncRXConsumeIndex(LPC_ETHERNET);
}
/* Get Tx Buffer for the next transmission */
STATIC void *ENET_TXBuffGet(void)
{
uint16_t consumeIdx = Chip_ENET_GetTXConsumeIndex(LPC_ETHERNET);
if (Chip_ENET_GetBufferStatus(LPC_ETHERNET, txProduceIdx, consumeIdx, ENET_NUM_TX_DESC) != ENET_BUFF_FULL) {
return (void *) pTXDescs[txProduceIdx].Packet;
}
return NULL;
}
/* Queue a new frame for transmission */
STATIC void ENET_TXQueue(int32_t bytes)
{
if (bytes > 0) {
pTXDescs[txProduceIdx].Control = ENET_TCTRL_SIZE(bytes) | ENET_TCTRL_LAST;
txProduceIdx = Chip_ENET_IncTXProduceIndex(LPC_ETHERNET);
}
}
/* Check if tranmission finished */
STATIC bool ENET_IsTXFinish(void)
{
uint16_t consumeIdx = Chip_ENET_GetTXConsumeIndex(LPC_ETHERNET);
if (Chip_ENET_GetBufferStatus(LPC_ETHERNET, txProduceIdx, consumeIdx, ENET_NUM_TX_DESC) == ENET_BUFF_EMPTY) {
return true;
}
return false;
}
/*****************************************************************************
* Public functions
****************************************************************************/
/**
* @briefHandle interrupt from ethernet
* @returnNothing
*/
void ETH_IRQHandler(void)
{
/* This demo is entirely polled, so the IRQ isn't really needed */
}
/**
* @briefmain routine for ENET example
* @returnNothing (function should not exit)
*/
int main(void)
{
uint8_t macaddr[6], *workbuff;
uint32_t physts = 0;
int32_t rxBytes, i;
bool ethpkttgl = true;
volatile int k = 1;
SystemCoreClockUpdate();
Board_Init();
/* LED0 is used for the link status, on = PHY cable detected */
/* Initial LED state is off to show an unconnected cable state */
Board_LED_Set(0, false);
/* Setup ethernet and PHY */
#if defined(USE_RMII)
Chip_ENET_Init(LPC_ETHERNET, true);
#else
Chip_ENET_Init(LPC_ETHERNET, false);
#endif
/* Setup MII clock rate and PHY address */
Chip_ENET_SetupMII(LPC_ETHERNET, Chip_ENET_FindMIIDiv(LPC_ETHERNET, 2500000), 1);
lpc_phy_init(true, localMsDelay);
/* Setup MAC address for device */
Board_ENET_GetMacADDR(macaddr);
Chip_ENET_SetADDR(LPC_ETHERNET, macaddr);
/* Setup descriptors */
InitDescriptors();
/* Enable RX/TX after descriptors are setup */
Chip_ENET_TXEnable(LPC_ETHERNET);
Chip_ENET_RXEnable(LPC_ETHERNET);
while (k) {
/* Check for receive packets */
workbuff = ENET_RXGet(&rxBytes);
if (workbuff) {
/* Packet was received. Dump some info from the packet */
DEBUGOUT("Packet received: ");
ethpkttgl = (bool) !ethpkttgl;
/* Toggle LED2 on each packet received */
Board_LED_Set(1, ethpkttgl);
/* Destination and source MAC addresses */
DEBUGOUT("-Dest MAC: %02x:%02x:%02x:%02x:%02x:%02x-",
workbuff[0], workbuff[1], workbuff[2], workbuff[3], workbuff[4], workbuff[5]);
DEBUGOUT("-Source MAC: %02x:%02x:%02x:%02x:%02x:%02x-",
workbuff[6], workbuff[7], workbuff[8], workbuff[9], workbuff[10], workbuff[11]);
/* Length of received packet and embedded len/type */
DEBUGOUT("-Packet len: %d", rxBytes);
DEBUGOUT("-Type: %04x\r\n", ((((uint32_t) workbuff[12]) << 8) | (((uint32_t) workbuff[13]))));
ENET_RXBuffClaim();
}
/* Send a 'dummy' broadcast packet on a keypress. You'll only see this
if your using a tool such as WireShark and the packet will not have
a checksum */
if (DEBUGIN() != EOF) {
/* Only if link detected */
if (physts & PHY_LINK_CONNECTED) {
workbuff = ENET_TXBuffGet();
if (workbuff) {
/* Destination is broadcast */
for (i = 0; i < 6; i++) {
workbuff = 0xFF;
}
/* Source is this MAC address */
memcpy(&workbuff[6], macaddr, 6);
/* Size will be 128 bytes (total) */
workbuff[12] = 0;
workbuff[13] = 128;
/* Some dummy data, fill beyond end of packet */
for (i = 0; i < 128; i++) {
workbuff[i + 14] = (uint8_t) (i & 0xFF);
}
ENET_TXQueue(128);
DEBUGOUT("Packet sent! \r\n");
Board_LED_Set(1, true);
}
}
}
if (ENET_IsTXFinish()) {
Board_LED_Set(1, false);
}
/* PHY status state machine, LED on when connected. This function will
not block. */
physts = lpcPHYStsPoll();
/* Only check for connection state when the PHY status has changed */
if (physts & PHY_LINK_CHANGED) {
if (physts & PHY_LINK_CONNECTED) {
Board_LED_Set(0, true);
/* Set interface speed and duplex */
if(physts & PHY_LINK_FULLDUPLX)
Chip_ENET_SetFullDuplex(LPC_ETHERNET);
else
Chip_ENET_SetHalfDuplex(LPC_ETHERNET);
if(physts & PHY_LINK_SPEED100)
Chip_ENET_Set100Mbps(LPC_ETHERNET);
else
Chip_ENET_Set10Mbps(LPC_ETHERNET);
}
else {
Board_LED_Set(0, false);
}
DEBUGOUT("Link connect status: %d\r\n", ((physts & PHY_LINK_CONNECTED) != 0));
}
}
/* Never returns, for warning only */
return 0;
}
/**
* @}
*/
|