| LPCOpen Platform v1.03 LPCOpen Platform for NXP LPC Microcontrollers

- Main Page
- Modules
- Data Structures
- Files
- Related Pages

- File List
- Globals

All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
enet.c
Go to the documentation of this file.
1 /*
2 * @brief Simple ethernet example
3 *
4 * @note
5 * Copyright(C) NXP Semiconductors, 2012
6 * All rights reserved.
7 *
8 * @par
9 * Software that is described herein is for illustrative purposes only
10 * which provides customers with programming information regarding the
11 * LPC products. This software is supplied "AS IS" without any warranties of
12 * any kind, and NXP Semiconductors and its licensor disclaim any and
13 * all warranties, express or implied, including all implied warranties of
14 * merchantability, fitness for a particular purpose and non-infringement of
15 * intellectual property rights. NXP Semiconductors assumes no responsibility
16 * or liability for the use of the software, conveys no license or rights under any
17 * patent, copyright, mask work right, or any other intellectual property rights in
18 * or to any products. NXP Semiconductors reserves the right to make changes
19 * in the software without notification. NXP Semiconductors also makes no
20 * representation or warranty that such application will be suitable for the
21 * specified use without further testing or modification.
22 *
23 * @par
24 * Permission to use, copy, modify, and distribute this software and its
25 * documentation is hereby granted, under NXP Semiconductors' and its
26 * licensor's relevant copyrights in the software, without fee, provided that it
27 * is used in conjunction with NXP Semiconductors microcontrollers. This
28 * copyright, permission, and disclaimer notice must appear in all copies of
29 * this code.
30 */
31
32 #include "board.h"
33 #include <stdio.h>
34 #include <string.h>
35
73 /*****************************************************************************
74 * Private types/enumerations/variables
75 ****************************************************************************/
76
77 #define ENET_NUM_TX_DESC 4
78 #define ENET_NUM_RX_DESC 4
79
80 #if defined(CHIP_LPC175X_6X)
81 #define ENET_RX_DESC_BASE (0x2007C000)
82 #else
83 /* The Ethernet Block can only access Peripheral SRAM and External Memory. In this example,
84 Peripheral SRAM is selected for storing descriptors, status arrays and send/receive buffers.*/
85 #define ENET_RX_DESC_BASE (0x20000000UL)
86 #endif
87 #define ENET_RX_STAT_BASE (ENET_RX_DESC_BASE + ENET_NUM_RX_DESC * sizeof(ENET_RXDESC_T))
88 #define ENET_TX_DESC_BASE (ENET_RX_STAT_BASE + ENET_NUM_RX_DESC * sizeof(ENET_RXSTAT_T))
89 #define ENET_TX_STAT_BASE (ENET_TX_DESC_BASE + ENET_NUM_TX_DESC * sizeof(ENET_TXDESC_T))
90 #define ENET_RX_BUF_BASE (ENET_TX_STAT_BASE + ENET_NUM_TX_DESC * sizeof(ENET_TXSTAT_T))
91 #define ENET_TX_BUF_BASE (ENET_RX_BUF_BASE + ENET_NUM_RX_DESC * ENET_ETH_MAX_FLEN)
92 #define ENET_RX_BUF(i) (ENET_RX_BUF_BASE + ENET_ETH_MAX_FLEN * i)
93 #define ENET_TX_BUF(i) (ENET_TX_BUF_BASE + ENET_ETH_MAX_FLEN * i)
94
95 STATIC ENET_RXDESC_T *pRXDescs = (ENET_RXDESC_T *) ENET_RX_DESC_BASE;
96 STATIC ENET_RXSTAT_T *pRXStats = (ENET_RXSTAT_T *) ENET_RX_STAT_BASE;
97 STATIC ENET_TXDESC_T *pTXDescs = (ENET_TXDESC_T *) ENET_TX_DESC_BASE;
98 STATIC ENET_TXSTAT_T *pTXStats = (ENET_TXSTAT_T *) ENET_TX_STAT_BASE;
99
100 /* Transmit/receive buffers and indices */
101 STATIC int32_t rxConsumeIdx;
102 STATIC int32_t txProduceIdx;
103
104 /*****************************************************************************
105 * Public types/enumerations/variables
106 ****************************************************************************/
107
108 /*****************************************************************************
109 * Private functions
110 ****************************************************************************/
111
112 /* Local delay function used by the ENET or PHY drivers . This can be
113 replaced with something more accurate if needed. */
114 STATIC void localMsDelay(uint32_t ms)
115 {
116 ms = ms * 40000;
117 while (ms > 0) {
118 ms--;
119 }
120 }
121
122 /* Initialize MAC descriptors for simple packet receive/transmit */
123 STATIC void InitDescriptors(void)
124 {
125 int i;
126
127 /* Setup the descriptor list to a default state */
128 memset(pTXDescs, 0, ENET_NUM_TX_DESC * sizeof(ENET_TXDESC_T));
129 memset(pTXStats, 0, ENET_NUM_TX_DESC * sizeof(ENET_TXSTAT_T));
130 memset(pRXDescs, 0, ENET_NUM_RX_DESC * sizeof(ENET_RXDESC_T));
131 memset(pRXStats, 0, ENET_NUM_RX_DESC * sizeof(ENET_RXSTAT_T));
132
133 rxConsumeIdx = 0;
134 rxConsumeIdx = 0;
135
136 /* Build linked list, CPU is owner of descriptors */
137 for (i = 0; i < ENET_NUM_RX_DESC; i++) {
138 pRXDescs[i].Packet = (uint32_t) ENET_RX_BUF(i);
139 pRXDescs[i].Control = ENET_RCTRL_SIZE(ENET_ETH_MAX_FLEN);
140 pRXStats[i].StatusInfo = 0;
141 pRXStats[i].StatusHashCRC = 0;
142 }
143 for (i = 0; i < ENET_NUM_TX_DESC; i++) {
144 pTXDescs[i].Packet = (uint32_t) ENET_TX_BUF(i);
145 pTXDescs[i].Control = 0;
146 pTXStats[i].StatusInfo = 0;
147 }
148
149 /* Setup list pointers in Ethernet controller */
150 Chip_ENET_InitTxDescriptors(LPC_ETHERNET, pTXDescs, pTXStats, ENET_NUM_TX_DESC);
151 Chip_ENET_InitRxDescriptors(LPC_ETHERNET, pRXDescs, pRXStats, ENET_NUM_RX_DESC);
152 }
153
154 /* Get the pointer to the Rx buffer storing new received frame */
155 STATIC void *ENET_RXGet(int32_t *bytes)
156 {
157 uint16_t produceIdx;
158 void *buffer;
159
160 produceIdx = Chip_ENET_GetRXProduceIndex(LPC_ETHERNET);
161 /* This doesn't check status of the received packet */
162 if (Chip_ENET_GetBufferStatus(LPC_ETHERNET, produceIdx, rxConsumeIdx, ENET_NUM_RX_DESC) != ENET_BUFF_EMPTY) {
163 /* CPU owns descriptor, so a packet was received */
164 buffer = (void *) pRXDescs[rxConsumeIdx].Packet;
165 *bytes = (int32_t) (ENET_RINFO_SIZE(pRXStats[rxConsumeIdx].StatusInfo) - 4);/* Remove CRC */
166 }
167 else {
168 /* Nothing received */
169 *bytes = 0;
170 buffer = NULL;
171 }
172
173 return buffer;
174 }
175
176 /* Release Rx Buffer */
177 STATIC void ENET_RXBuffClaim(void)
178 {
179 rxConsumeIdx = Chip_ENET_IncRXConsumeIndex(LPC_ETHERNET);
180 }
181
182 /* Get Tx Buffer for the next transmission */
183 STATIC void *ENET_TXBuffGet(void)
184 {
185 uint16_t consumeIdx = Chip_ENET_GetTXConsumeIndex(LPC_ETHERNET);
186
187 if (Chip_ENET_GetBufferStatus(LPC_ETHERNET, txProduceIdx, consumeIdx, ENET_NUM_TX_DESC) != ENET_BUFF_FULL) {
188 return (void *) pTXDescs[txProduceIdx].Packet;
189 }
190 return NULL;
191 }
192
193 /* Queue a new frame for transmission */
194 STATIC void ENET_TXQueue(int32_t bytes)
195 {
196 if (bytes > 0) {
197 pTXDescs[txProduceIdx].Control = ENET_TCTRL_SIZE(bytes) | ENET_TCTRL_LAST;
198 txProduceIdx = Chip_ENET_IncTXProduceIndex(LPC_ETHERNET);
199 }
200 }
201
202 /* Check if tranmission finished */
203 STATIC bool ENET_IsTXFinish(void)
204 {
205 uint16_t consumeIdx = Chip_ENET_GetTXConsumeIndex(LPC_ETHERNET);
206
207 if (Chip_ENET_GetBufferStatus(LPC_ETHERNET, txProduceIdx, consumeIdx, ENET_NUM_TX_DESC) == ENET_BUFF_EMPTY) {
208 return true;
209 }
210 return false;
211 }
212
213 /*****************************************************************************
214 * Public functions
215 ****************************************************************************/
216
221 void ETH_IRQHandler(void)
222 {
223 /* This demo is entirely polled, so the IRQ isn't really needed */
224 }
225
230 int main(void)
231 {
232 uint8_t macaddr[6], *workbuff;
233 uint32_t physts = 0;
234 int32_t rxBytes, i;
235 bool ethpkttgl = true;
236 volatile int k = 1;
237
238 /* LED0 is used for the link status, on = PHY cable detected */
239 Board_Init();
240
241 /* Initial LED state is off to show an unconnected cable state */
242 Board_LED_Set(0, false);
243
244 /* Setup ethernet and PHY */
245 Chip_ENET_Init(LPC_ETHERNET);
246
247 /* Setup MII clock rate and PHY address */
248 Chip_ENET_SetupMII(LPC_ETHERNET, Chip_ENET_FindMIIDiv(LPC_ETHERNET, 2500000), 1);
249
250 lpc_phy_init(true, localMsDelay);
251
252 /* Setup MAC address for device */
253 Board_ENET_GetMacADDR(macaddr);
254 Chip_ENET_SetADDR(LPC_ETHERNET, macaddr);
255
256 /* Setup descriptors */
257 InitDescriptors();
258
259 /* Enable RX/TX after descriptors are setup */
260 Chip_ENET_TXEnable(LPC_ETHERNET);
261 Chip_ENET_RXEnable(LPC_ETHERNET);
262
263 while (k) {
264 /* Check for receive packets */
265 workbuff = ENET_RXGet(&rxBytes);
266 if (workbuff) {
267 /* Packet was received. Dump some info from the packet */
268 DEBUGOUT("Packet received: ");
269 ethpkttgl = (bool) !ethpkttgl;
270
271 /* Toggle LED2 on each packet received */
272 Board_LED_Set(1, ethpkttgl);
273
274 /* Destination and source MAC addresses */
275 DEBUGOUT("-Dest MAC: %02x:%02x:%02x:%02x:%02x:%02x-",
276 workbuff[0], workbuff[1], workbuff[2], workbuff[3], workbuff[4], workbuff[5]);
277 DEBUGOUT("-Source MAC: %02x:%02x:%02x:%02x:%02x:%02x-",
278 workbuff[6], workbuff[7], workbuff[8], workbuff[9], workbuff[10], workbuff[11]);
279
280 /* Length of received packet and embedded len/type */
281 DEBUGOUT("-Packet len: %d", rxBytes);
282 DEBUGOUT("-Type: %04x\r\n", ((((uint32_t) workbuff[12]) << 8) | (((uint32_t) workbuff[13]))));
283 ENET_RXBuffClaim();
284 }
285
286 /* Send a 'dummy' broadcast packet on a keypress. You'll only see this
287 if your using a tool such as WireShark and the packet will not have
288 a checksum */
289 if (DEBUGIN() != EOF) {
290 /* Only if link detected */
291 if (physts & PHY_LINK_CONNECTED) {
292 workbuff = ENET_TXBuffGet();
293 if (workbuff) {
294 /* Destination is broadcast */
295 for (i = 0; i < 6; i++) {
296 workbuff[i] = 0xFF;
297 }
298
299 /* Source is this MAC address */
300 memcpy(&workbuff[6], macaddr, 6);
301
302 /* Size will be 128 bytes (total) */
303 workbuff[12] = 0;
304 workbuff[13] = 128;
305
306 /* Some dummy data, fill beyond end of packet */
307 for (i = 0; i < 128; i++) {
308 workbuff[i + 14] = (uint8_t) (i & 0xFF);
309 }
310
311 ENET_TXQueue(128);
312 DEBUGOUT("Packet sent! \r\n");
313 Board_LED_Set(1, true);
314 }
315 }
316 }
317 if (ENET_IsTXFinish()) {
318 Board_LED_Set(1, false);
319 }
320 /* PHY status state machine, LED on when connected. This function will
321 not block. */
322 physts = lpcPHYStsPoll();
323
324 /* Only check for connection state when the PHY status has changed */
325 if (physts & PHY_LINK_CHANGED) {
326 if (physts & PHY_LINK_CONNECTED) {
327 Board_LED_Set(0, true);
328
329 /* Set interface speed and duplex */
330 if(physts & PHY_LINK_FULLDUPLX)
331 Chip_ENET_SetFullDuplex(LPC_ETHERNET);
332 else
333 Chip_ENET_SetHalfDuplex(LPC_ETHERNET);
334 if(physts & PHY_LINK_SPEED100)
335 Chip_ENET_Set100Mbps(LPC_ETHERNET);
336 else
337 Chip_ENET_Set10Mbps(LPC_ETHERNET);
338 }
339 else {
340 Board_LED_Set(0, false);
341 }
342
343 DEBUGOUT("Link connect status: %d\r\n", ((physts & PHY_LINK_CONNECTED) != 0));
344 }
345 }
346
347 /* Never returns, for warning only */
348 return 0;
349 }
350