| 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 * This simple MAC example will listen for all packets on
4 * the ethernet and display some stats via UART when a
5 * packet is received. A dummy packet can also be sent out.
6 * Wireshark can be used to view the outgoing packet.
7 *
8 * @note
9 * Copyright(C) NXP Semiconductors, 2012
10 * All rights reserved.
11 *
12 * @par
13 * Software that is described herein is for illustrative purposes only
14 * which provides customers with programming information regarding the
15 * LPC products. This software is supplied "AS IS" without any warranties of
16 * any kind, and NXP Semiconductors and its licensor disclaim any and
17 * all warranties, express or implied, including all implied warranties of
18 * merchantability, fitness for a particular purpose and non-infringement of
19 * intellectual property rights. NXP Semiconductors assumes no responsibility
20 * or liability for the use of the software, conveys no license or rights under any
21 * patent, copyright, mask work right, or any other intellectual property rights in
22 * or to any products. NXP Semiconductors reserves the right to make changes
23 * in the software without notification. NXP Semiconductors also makes no
24 * representation or warranty that such application will be suitable for the
25 * specified use without further testing or modification.
26 *
27 * @par
28 * Permission to use, copy, modify, and distribute this software and its
29 * documentation is hereby granted, under NXP Semiconductors' and its
30 * licensor's relevant copyrights in the software, without fee, provided that it
31 * is used in conjunction with NXP Semiconductors microcontrollers. This
32 * copyright, permission, and disclaimer notice must appear in all copies of
33 * this code.
34 */
35
36 #include "board.h"
37 #include <stdio.h>
38 #include <string.h>
39
73 /*****************************************************************************
74 * Private types/enumerations/variables
75 ****************************************************************************/
76
77 #define ENET_NUM_TX_DESC 4
78 #define ENET_NUM_RX_DESC 4
79
80 static IP_ENET_001_ENHTXDESC_T TXDescs[ENET_NUM_TX_DESC];
81 static IP_ENET_001_ENHRXDESC_T RXDescs[ENET_NUM_RX_DESC];
82
83 /* Transmit/receive buffers and indices */
84 static uint8_t TXBuffer[ENET_NUM_TX_DESC][EMAC_ETH_MAX_FLEN];
85 static uint8_t RXBuffer[ENET_NUM_RX_DESC][EMAC_ETH_MAX_FLEN];
86 static int32_t rxFill, rxGet, rxAvail, rxNumDescs;
87 static int32_t txFill, txGet, txUsed, txNumDescs;
88
89 /*****************************************************************************
90 * Public types/enumerations/variables
91 ****************************************************************************/
92
93 /*****************************************************************************
94 * Private functions
95 ****************************************************************************/
96
97 /* Local delay function used by the ENET or PHY drivers . This can be
98 replaced with something more accurate if needed. */
99 static void localMsDelay(uint32_t ms)
100 {
101 ms = ms * 50000;
102 while (ms > 0) {
103 ms--;
104 }
105 }
106
107 /* Local index and check function */
108 static __INLINE int32_t incIndex(int32_t index, int32_t max)
109 {
110 index++;
111 if (index >= max) {
112 index = 0;
113 }
114
115 return index;
116 }
117
118 /* Initialize MAC descriptors for simple packet receive/transmit */
119 static void InitDescriptors(
120 IP_ENET_001_ENHTXDESC_T *pTXDescs, int32_t numTXDescs,
121 IP_ENET_001_ENHRXDESC_T *pRXDescs, int32_t numRXDescs)
122 {
123 int i;
124
125 /* Setup the descriptor list to a default state */
126 memset(pTXDescs, 0, numTXDescs * sizeof(*pTXDescs));
127 memset(pTXDescs, 0, numRXDescs * sizeof(*pRXDescs));
128 rxFill = rxGet = 0;
129 rxAvail = rxNumDescs = numRXDescs;
130 txNumDescs = numTXDescs;
131 txUsed = txGet = txFill = 0;
132
133 /* Build linked list, CPU is owner of descriptors */
134 for (i = 0; i < numTXDescs; i++) {
135 pTXDescs[i].CTRLSTAT = 0;
136 pTXDescs[i].B2ADD = (uint32_t) &pTXDescs[i + 1];
137 }
138 pTXDescs[numTXDescs - 1].B2ADD = (uint32_t) &pTXDescs[0];
139 for (i = 0; i < numRXDescs; i++) {
140 pRXDescs[i].STATUS = 0;
141 pRXDescs[i].B2ADD = (uint32_t) &pRXDescs[i + 1];
142 pRXDescs[i].CTRL = RDES_ENH_RCH;
143 }
144 pRXDescs[numRXDescs - 1].B2ADD = (uint32_t) &pRXDescs[0];
145 pRXDescs[numRXDescs - 1].CTRL |= RDES_ENH_RER;
146
147 /* Setup list pointers in Ethernet controller */
148 Chip_ENET_InitDescriptors(LPC_ETHERNET, pTXDescs, pRXDescs);
149 }
150
151 /* Attach a buffer to a descriptor and queue it for reception */
152 static void ENET_RXQueue(void *buffer, int32_t bytes)
153 {
154 if (rxAvail > 0) {
155 /* Queue the next descriptor and start polling */
156 RXDescs[rxFill].B1ADD = (uint32_t) buffer;
157 RXDescs[rxFill].CTRL = RDES_ENH_BS1(bytes) | RDES_ENH_RCH;
158 if (rxFill == (rxNumDescs - 1)) {
159 RXDescs[rxFill].CTRL |= RDES_ENH_RER;
160 }
161 RXDescs[rxFill].STATUS = RDES_OWN;
162 rxAvail--;
163 rxFill = incIndex(rxFill, rxNumDescs);
164
165 /* Start polling */
166 Chip_ENET_RXStart(LPC_ETHERNET);
167 }
168 }
169
170 /* Returns a pointer to a filled ethernet buffer or NULL if none are available */
171 static void *ENET_RXGet(int32_t *bytes)
172 {
173 void *buffer;
174
175 /* This doesn't check status of the received packet */
176 if ((rxAvail < rxNumDescs) && (!(RXDescs[rxGet].STATUS & RDES_OWN))) {
177 /* CPU owns descriptor, so a packet was received */
178 buffer = (void *) RXDescs[rxGet].B1ADD;
179 *bytes = (int32_t) RXDescs[rxGet].STATUS & 0xFFF;
180 rxGet = incIndex(rxGet, rxNumDescs);
181 rxAvail++;
182 }
183 else {
184 /* Nothing received */
185 *bytes = 0;
186 buffer = NULL;
187 }
188
189 return buffer;
190 }
191
192 /* Attaches a buffer to a transmit descriptor and queues it for transmit */
193 static void ENET_TXQueue(void *buffer, int32_t bytes)
194 {
195 if (txUsed < txNumDescs) {
196 /* Queue the next descriptor and start polling */
197 TXDescs[txFill].B1ADD = (uint32_t) buffer;
198 TXDescs[txFill].BSIZE = TDES_ENH_BS1(bytes);
199 TXDescs[txFill].CTRLSTAT = TDES_ENH_FS | TDES_ENH_LS | TDES_ENH_TCH;
200 if (txFill == (txNumDescs - 1)) {
201 TXDescs[txFill].CTRLSTAT |= TDES_ENH_TER;
202 }
203 TXDescs[txFill].CTRLSTAT |= TDES_OWN;
204 txUsed++;
205 txFill = incIndex(txFill, txNumDescs);
206
207 /* Start polling */
208 Chip_ENET_TXStart(LPC_ETHERNET);
209 }
210 }
211
212 /* Returns a pointer to a buffer that has been transmitted */
213 static void *ENET_TXBuffClaim(void)
214 {
215 void *buffer;
216
217 /* Is packet done sending? */
218 if ((txUsed > 0) && (!(TXDescs[txGet].CTRLSTAT & TDES_OWN))) {
219 /* CPU owns descriptor, so the packet completed transmit */
220 buffer = (void *) TXDescs[txGet].B1ADD;
221 txGet = incIndex(txGet, txNumDescs);
222 txUsed--;
223 Board_LED_Set(2, false);
224 }
225 else {
226 buffer = NULL;
227 }
228
229 return buffer;
230 }
231
232 /*****************************************************************************
233 * Public functions
234 ****************************************************************************/
235
240 void ETH_IRQHandler(void)
241 {
242 /* This demo is entirely polled, so the IRQ isn't really needed */
243 }
244
249 int main(void)
250 {
251 uint8_t macaddr[6], *workbuff;
252 uint32_t physts = 0;
253 int32_t rxBytes, i, txNextIndex;
254 bool ethpkttgl = true;
255
256 /* LED0 is used for the link status, on = PHY cable detected */
257 Board_Init();
258
259 /* Initial LED state is off to show an unconnected cable state */
260 Board_LED_Set(0, false);
261
262 /* Setup ethernet and PHY */
263 Chip_ENET_Init(LPC_ETHERNET);
264 #if defined(USE_RMII)
265 lpc_phy_init(true, localMsDelay);
266 #else
267 lpc_phy_init(false, localMsDelay);
268 #endif
269
270 /* Setup MAC address for device */
271 Board_ENET_GetMacADDR(macaddr);
272 Chip_ENET_SetADDR(LPC_ETHERNET, macaddr);
273
274 /* Setup descriptors */
275 InitDescriptors(TXDescs, ENET_NUM_TX_DESC, RXDescs, ENET_NUM_RX_DESC);
276
277 /* Attach a buffer to a RX descriptor and queue it for receive */
278 i = 0;
279 while (i < ENET_NUM_RX_DESC) {
280 ENET_RXQueue(RXBuffer[i], EMAC_ETH_MAX_FLEN);
281 i++;
282 }
283 txNextIndex = 0;
284
285 /* Enable RX/TX after descriptors are setup */
286 Chip_ENET_TXEnable(LPC_ETHERNET);
287 Chip_ENET_RXEnable(LPC_ETHERNET);
288
289 while (1) {
290 /* Check for receive packets */
291 workbuff = ENET_RXGet(&rxBytes);
292 if (workbuff) {
293 /* Packet was received. Dump some info from the packet */
294 DEBUGOUT("Packet received: ");
295 ethpkttgl = (bool) !ethpkttgl;
296
297 /* Toggle LED2 on each packet received */
298 Board_LED_Set(1, ethpkttgl);
299
300 /* Destination and source MAC addresses */
301 DEBUGOUT("-Dest MAC: %02x:%02x:%02x:%02x:%02x:%02x-",
302 workbuff[0], workbuff[1], workbuff[2], workbuff[3], workbuff[4], workbuff[5]);
303 DEBUGOUT("-Source MAC: %02x:%02x:%02x:%02x:%02x:%02x-",
304 workbuff[6], workbuff[7], workbuff[8], workbuff[9], workbuff[10], workbuff[11]);
305
306 /* Length of received packet and embedded len/type */
307 DEBUGOUT("-Packet len: %d", rxBytes);
308 DEBUGOUT("-Type: %04x\r\n", ((((uint32_t) workbuff[12]) << 8) | (((uint32_t) workbuff[13]))));
309
310 /* Re-queue the (same) packet again */
311 ENET_RXQueue(workbuff, EMAC_ETH_MAX_FLEN);
312 }
313
314 /* Send a 'dummy' broadcast packet on a keypress. You'll only see this
315 if your using a tool such as WireShark and the packet will not have
316 a checksum */
317 if (DEBUGIN() != EOF) {
318 /* Only if link detected */
319 if (physts & PHY_LINK_CONNECTED) {
320 /* Get next available TX buffer */
321 workbuff = (uint8_t *) TXBuffer[txNextIndex];
322 txNextIndex = incIndex(txNextIndex, ENET_NUM_TX_DESC);
323 /* Destination is broadcast */
324 for (i = 0; i < 6; i++) {
325 workbuff[i] = 0xFF;
326 }
327
328 /* Source is this MAC address */
329 memcpy(&workbuff[6], macaddr, 6);
330
331 /* Size will be 128 bytes (total) */
332 workbuff[12] = 0;
333 workbuff[13] = 128;
334
335 /* Some dummy data, fill beyond end of packet */
336 for (i = 0; i < 128; i++) {
337 workbuff[i + 14] = (uint8_t) (i & 0xFF);
338 }
339
340 /* Queue TX packet. This is an Ethernet packet, but the payload and
341 hecksum are garbage. The packet will still be viewable with
342 Wireshark */
343 ENET_TXQueue(workbuff, 128);
344 Board_LED_Set(2, true);
345 }
346 }
347
348 /* Transmit buffers are 'zero-copy' buffers with the queue function, so
349 the buffer must remain in memory until the packet has been fully
350 transmitted. Call ENET_TXBuffClaim() to to reclaim a sent
351 packet. If a packet buffer address is return (not NULL), then the
352 packet can be de-allocated. Since the buffers in this examples are
353 static, there isn't too much to do. */
354 ENET_TXBuffClaim();
355
356 /* PHY status state machine, LED on when connected. This function will
357 not block. */
358 physts = lpcPHYStsPoll();
359
360 /* Only check for connection state when the PHY status has changed */
361 if (physts & PHY_LINK_CHANGED) {
362 if (physts & PHY_LINK_CONNECTED) {
363 Board_LED_Set(0, true);
364
365 /* Set interface speed and duplex */
366 Chip_ENET_SetDuplex(LPC_ETHERNET, (bool) (physts & PHY_LINK_FULLDUPLX));
367 Chip_ENET_SetSpeed(LPC_ETHERNET, (bool) (physts & PHY_LINK_SPEED100));
368 }
369 else {
370 Board_LED_Set(0, false);
371 }
372
373 DEBUGOUT("Link connect status: %d\r\n", ((physts & PHY_LINK_CONNECTED) != 0));
374 }
375 }
376
377 /* Never returns, for warning only */
378 return 0;
379 }
380