Open Model Railroad Network (OpenMRN)
Loading...
Searching...
No Matches
Tiva1294Ethernet.cxx
Go to the documentation of this file.
1
35#if !defined(PART_TM4C1294NCPDT)
36#error "This driver is only valid for the TM4C1294NCPDT"
37#endif
38
39#define TraceNet 0
40
41#include <stdint.h>
42#include <new>
43#include <stdio.h>
44
45#include "inc/hw_types.h"
46#include "inc/hw_memmap.h"
47#include "inc/hw_ints.h"
48#include "inc/hw_gpio.h"
49#include "inc/hw_emac.h"
50#include "inc/hw_flash.h"
51
52#include "driverlib/rom.h"
53#include "driverlib/rom_map.h"
54#include "driverlib/sysctl.h"
55#include "driverlib/gpio.h"
56#include "driverlib/timer.h"
57#include "driverlib/interrupt.h"
58#include "driverlib/pin_map.h"
59#include "driverlib/emac.h"
60#include "driverlib/flash.h"
61
62#include "FreeRTOSConfig.h"
63#include "FreeRTOS.h"
64#include "task.h"
65#include "queue.h"
66#include "semphr.h"
67#include "timers.h"
68
69#include "Tiva1294Ethernet.hxx"
70#include "FreeRTOSIPConfig.h"
71#include "FreeRTOS_IP.h"
72#include "NetworkInterface.h"
73#include "NetworkBufferManagement.h"
74#include "FreeRTOS_IP_Private.h"
75#include "FreeRTOS_Sockets.h"
76
77extern const long unsigned cm3_cpu_clock_hz;
78
79// empty debugging routines
80void PrintBuffer(uint8_t *Buffer, size_t Len)
81{
82}
83void PrintStr(const char *Str)
84{
85}
86void PrintHex(uint32_t Val)
87{
88}
89void Print(char ch)
90{
91}
92
93typedef struct
94{
95 tEMACDMADescriptor DMA;
96 volatile uint32_t Flags;
98
99const int EMACIODescriptorExtra =
100 (sizeof(EMACIODescriptor) - sizeof(tEMACDMADescriptor) + 3) / 4;
101
102// Values for Flags in EMACIODescriptor
103#define IOBUSY 0x01 //< IO presently active
104
105#define NUM_TX_DESCRIPTORS 3
106#define NUM_RX_DESCRIPTORS 5
107static EMACIODescriptor RxDescriptor[NUM_RX_DESCRIPTORS],
108 TxDescriptor[NUM_TX_DESCRIPTORS];
109static uint16_t RxDescIndex, TxDescIndex;
110
111static QueueHandle_t TxBufferQueue = NULL;
112
113static QueueHandle_t xEMACEventQueue = NULL;
114
115static TaskHandle_t xDIHTask = NULL;
116
117static bool LinkDown, Initialised = false;
118
119#ifdef STATIC_BUFFERS
120#define BUFFER_SIZE (ipTOTAL_ETHERNET_FRAME_SIZE + ipBUFFER_PADDING)
121#define BUFFER_SIZE_ROUNDED_UP ((BUFFER_SIZE + 7) & ~0x07UL)
122
123uint8_t __attribute__((aligned(4)))
124Buffers[ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS][BUFFER_SIZE_ROUNDED_UP];
125
126void vNetworkInterfaceAllocateRAMToBuffers(NetworkBufferDescriptor_t
127 pxNetworkBuffers[ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS]);
128
129uint8_t RxBuffers[NUM_RX_DESCRIPTORS][ipTOTAL_ETHERNET_FRAME_SIZE],
130 TxBuffers[NUM_TX_DESCRIPTORS][ipTOTAL_ETHERNET_FRAME_SIZE];
131#else
132#error "This implementation requires use of STATIC_BUFFERS"
133#endif
134
135static bool get_mac_address(uint8_t MACAddr[6]);
136bool network_layer_preinit(void);
137static bool InitialiseEthernet(void);
138static bool InitialiseDIH(void);
139static EMACIODescriptor *GetNextRxDescriptor(void);
140static void SendData(EMACIODescriptor *pxTxIOD, uint32_t DataLength);
141
142extern "C" void prvEMACDeferredInterruptHandlerTask(void *pvParameters);
143
144int FramesRecv = 0, FrameLen = 0;
145unsigned char *Frame;
146
147static bool get_mac_address(uint8_t MACAddr[6])
148{
149 uint32_t User0, User1;
150 FlashUserGet(&User0, &User1);
151 if ((User0 == 0xffffffff) || (User1 == 0xffffffff))
152 {
153 // MAC address not programmed
154 MACAddr[0] = 0x00;
155 MACAddr[1] = 0x11;
156 MACAddr[2] = 0x22;
157 MACAddr[3] = 0x33;
158 MACAddr[4] = 0x44;
159 MACAddr[5] = 0x55;
160 return (true);
161 }
162 else
163 {
164 // pack into MACAddr
165 MACAddr[0] = (User0 >> 0) & 0xff;
166 MACAddr[1] = (User0 >> 8) & 0xff;
167 MACAddr[2] = (User0 >> 16) & 0xff;
168 MACAddr[3] = (User1 >> 0) & 0xff;
169 MACAddr[4] = (User1 >> 8) & 0xff;
170 MACAddr[5] = (User1 >> 16) & 0xff;
171 return (false);
172 }
173}
174
176{
177 static const uint8_t IPAddr[4] = {192, 168, 0, 100},
178 NetMask[4] = {255, 255, 255, 0},
179 Gateway[4] = {192, 168, 0, 1},
180 DNSAddr[4] = {192, 168, 0, 1};
181 uint8_t MACAddr[6];
182
183 get_mac_address(MACAddr);
184
185 if (FreeRTOS_IPInit(IPAddr, NetMask, Gateway, DNSAddr, MACAddr) != pdPASS)
186 {
187 return (true);
188 }
189 return (false);
190}
191
192static bool InitialiseDIH(void)
193{
194 // create queue for deferred interrupt routine
195 if (xEMACEventQueue == NULL)
196 xEMACEventQueue =
197 xQueueCreate(ipconfigEVENT_QUEUE_LENGTH, sizeof(uint32_t));
198 if (xEMACEventQueue == NULL)
199 {
200 // couldn't create event queue
201 return (true);
202 }
203
204 // create deferred ISR task
205 if (xDIHTask == NULL)
206 {
207 if (xTaskCreate(prvEMACDeferredInterruptHandlerTask, "EthernetISR",
208 2 * configMINIMAL_STACK_SIZE, &xDIHTask,
209 configMAX_PRIORITIES - 2, NULL) != pdPASS)
210 {
211 return (true);
212 }
213 }
214 return (false);
215}
216
217static bool InitialiseEthernet(void)
218{
219 // Ethernet
220
221 uint8_t PHYAddr = 0;
222 uint8_t MACAddr[6];
223 int x;
224 EMACIODescriptor *TxIOD;
225
226 RxDescIndex = 0;
227 TxDescIndex = NUM_TX_DESCRIPTORS - 1;
228
229 if (!Initialised)
230 {
231 // start deferred interrupt handler task
232 if (InitialiseDIH())
233 {
234 // failed to initiate
235 return (true);
236 }
237
238 // create transmit buffer queue
239 if (TxBufferQueue == 0)
240 TxBufferQueue =
241 xQueueCreate(NUM_TX_DESCRIPTORS, sizeof(EMACIODescriptor *));
242 if (TxBufferQueue == 0)
243 {
244 // failed to create transmit buffer queue
245 return (true);
246 }
247
248 // note initialised
249 Initialised = true;
250 }
251 else
252 {
253 // reset the device
254 EMACReset(EMAC0_BASE);
255
256 // reset transmit buffer queue
257 xQueueReset(TxBufferQueue);
258 }
259
260 // now run with interrupts disabled
261 taskDISABLE_INTERRUPTS();
262
263 // obtain MAC address
264 if (get_mac_address(MACAddr))
265 {
266 // address not programmed - use default
267 ;
268 }
269
270 // set up LEDs
271 MAP_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOF);
272 MAP_GPIOPinConfigure(GPIO_PF0_EN0LED0);
273 GPIOPinTypeEthernetLED(GPIO_PORTF_BASE, GPIO_PIN_0);
274 MAP_GPIOPinConfigure(GPIO_PF4_EN0LED1);
275 GPIOPinTypeEthernetLED(GPIO_PORTF_BASE, GPIO_PIN_4);
276
277 // setup up MAC and PHY
278 MAP_SysCtlPeripheralEnable(SYSCTL_PERIPH_EMAC0);
279 MAP_SysCtlPeripheralEnable(SYSCTL_PERIPH_EPHY0);
280 MAP_SysCtlPeripheralReset(SYSCTL_PERIPH_EMAC0);
281 MAP_SysCtlPeripheralReset(SYSCTL_PERIPH_EPHY0);
282
283 // wait for ready
284 while (!MAP_SysCtlPeripheralReady(SYSCTL_PERIPH_EMAC0))
285 {
286 ;
287 }
288 // configure for use with internal PHY
289 EMACPHYConfigSet(EMAC0_BASE, EMAC_PHY_TYPE_INTERNAL | EMAC_PHY_INT_MDIX_EN |
290 EMAC_PHY_AN_100B_T_FULL_DUPLEX);
291
292 // enable linkstate interrupts
293 EMACPHYWrite(EMAC0_BASE, PHYAddr, EPHY_MISR1, EPHY_MISR1_LINKSTATEN);
294 // enable PHY interrupts
295 EMACPHYWrite(EMAC0_BASE, PHYAddr, EPHY_SCR, EPHY_SCR_INTEN);
296 // enable PHY Interrupt Mask
297 HWREG(EMAC0_BASE + EMAC_O_EPHYIM) = 1;
298 // clear any outstanding interrupts
299 HWREG(EMAC0_BASE + EMAC_O_EPHYMISC) = 1;
300
301 // reset the MAC to latch the PHY
302 EMACReset(EMAC0_BASE);
303 // initialize the MAC and set to DMA mode
304 EMACInit(EMAC0_BASE, cm3_cpu_clock_hz,
305 EMAC_BCONFIG_MIXED_BURST | EMAC_BCONFIG_PRIORITY_FIXED, 4, 4,
306 EMACIODescriptorExtra);
307 // set MAC configuration options
308 EMACConfigSet(EMAC0_BASE, EMAC_CONFIG_FULL_DUPLEX |
309 EMAC_CONFIG_CHECKSUM_OFFLOAD | EMAC_CONFIG_7BYTE_PREAMBLE |
310 EMAC_CONFIG_IF_GAP_96BITS | EMAC_CONFIG_USE_MACADDR0 |
311 EMAC_CONFIG_SA_FROM_DESCRIPTOR | EMAC_CONFIG_BO_LIMIT_1024,
312 EMAC_MODE_RX_STORE_FORWARD | EMAC_MODE_TX_STORE_FORWARD |
313 EMAC_MODE_TX_THRESHOLD_64_BYTES | EMAC_MODE_RX_THRESHOLD_64_BYTES,
314 0);
315 // initialise DMA descriptors
316 for (x = 0; x < NUM_TX_DESCRIPTORS; x++)
317 {
318 TxIOD = &TxDescriptor[x];
319 TxIOD->DMA.ui32Count = 0;
320 TxIOD->DMA.DES3.pLink =
321 (tEMACDMADescriptor *)((x == NUM_TX_DESCRIPTORS - 1)
322 ? TxDescriptor
323 : &TxDescriptor[x + 1]);
324 TxIOD->DMA.ui32CtrlStatus = DES0_TX_CTRL_LAST_SEG |
325 DES0_TX_CTRL_FIRST_SEG | DES0_TX_CTRL_INTERRUPT |
326 DES0_TX_CTRL_CHAINED |
327 0; // checksums dont seem to work DES0_TX_CTRL_IP_ALL_CKHSUMS;
328 TxIOD->DMA.pvBuffer1 = TxBuffers[x];
329 TxIOD->Flags = 0;
330 if (xQueueSend(TxBufferQueue, &TxIOD, 0) != pdTRUE)
331 {
332 /* error insert buffer into available queue
333 *
334 */
335 }
336 }
337 for (x = 0; x < NUM_RX_DESCRIPTORS; x++)
338 {
339 RxDescriptor[x].DMA.ui32CtrlStatus = 0;
340 RxDescriptor[x].DMA.ui32Count = DES1_RX_CTRL_CHAINED |
341 (ipTOTAL_ETHERNET_FRAME_SIZE << DES1_RX_CTRL_BUFF1_SIZE_S);
342 RxDescriptor[x].DMA.pvBuffer1 = RxBuffers[x];
343 RxDescriptor[x].DMA.DES3.pLink =
344 (tEMACDMADescriptor *)((x == NUM_RX_DESCRIPTORS - 1)
345 ? RxDescriptor
346 : &RxDescriptor[x + 1]);
347 RxDescriptor[x].Flags = 0;
348 }
349 // set DMA descriptors in hardware
350 EMACRxDMADescriptorListSet(EMAC0_BASE, (tEMACDMADescriptor *)RxDescriptor);
351 EMACTxDMADescriptorListSet(EMAC0_BASE, (tEMACDMADescriptor *)TxDescriptor);
352 // set hardware with MAC address
353 EMACAddrSet(EMAC0_BASE, 0, MACAddr);
354 // wait for link to become active: this is expected by IP
355 LinkDown = true;
356 while (
357 (EMACPHYRead(EMAC0_BASE, PHYAddr, EPHY_BMSR) & EPHY_BMSR_LINKSTAT) == 0)
358 {
359 vTaskDelay(pdMS_TO_TICKS(50));
360 }
361 LinkDown = false;
362 // set MAC filtering options: self, broadcast, multicast
363 EMACFrameFilterSet(EMAC0_BASE,
364#if 0 // accept all frames
365 EMAC_FRMFILTER_RX_ALL);
366#else
367
368 EMAC_FRMFILTER_SADDR | EMAC_FRMFILTER_PASS_MULTICAST |
369 EMAC_FRMFILTER_PASS_NO_CTRL);
370#endif
371
372 // clear any pending interrupts
373 EMACIntClear(EMAC0_BASE,EMACIntStatus(EMAC0_BASE,false));
374 // mark all receive buffers as available for DMA
375 for (x = 0; x < NUM_RX_DESCRIPTORS; x++)
376 {
377 RxDescriptor[x].DMA.ui32CtrlStatus = DES0_RX_CTRL_OWN;
378 }
379 // enable transmitter and receiver
380 EMACTxEnable(EMAC0_BASE);
381 EMACRxEnable(EMAC0_BASE);
382 // enable ethernet interrupt
383 MAP_IntPrioritySet(INT_EMAC0, 0xa0);
384 IntEnable(INT_EMAC0);
385 // enable ethernet interrupts
386 EMACIntEnable(EMAC0_BASE,
387 EMAC_INT_RECEIVE |
388 EMAC_INT_TRANSMIT |
389 EMAC_INT_BUS_ERROR |
390 EMAC_INT_RX_WATCHDOG |
391 EMAC_INT_RX_STOPPED |
392 EMAC_INT_TX_UNDERFLOW |
393 EMAC_INT_RX_OVERFLOW |
394 EMAC_INT_TX_JABBER |
395 EMAC_INT_TX_STOPPED |
396 EMAC_INT_PHY);
397
398 // reenable interrupts
399 taskENABLE_INTERRUPTS();
400
401 return(false);
402}
403
404#ifdef STATIC_BUFFERS
405void vNetworkInterfaceAllocateRAMToBuffers(NetworkBufferDescriptor_t
406 pxNetworkBuffers[ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS])
407{
408 for (int x = 0; x < ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS; x++)
409 {
410 // set the buffer point to point past the padding area
411 pxNetworkBuffers[x].pucEthernetBuffer = &(Buffers[x][ipBUFFER_PADDING]);
412 // set the pointer with the buffer back to the NetworkBuffer
413 *((uint32_t *)&Buffers[x][0]) = (uint32_t) & (pxNetworkBuffers[x]);
414 }
415}
416#endif
417
418BaseType_t xNetworkInterfaceInitialise(void)
419{
420 if (InitialiseEthernet())
421 return (pdFAIL);
422 else
423 return (pdPASS);
424}
425
426static EMACIODescriptor *GetNextRxDescriptor(void)
427{
428 uint16_t inx = RxDescIndex;
429 taskENTER_CRITICAL();
430 while (RxDescriptor[inx].DMA.ui32CtrlStatus & DES0_RX_CTRL_OWN)
431 {
432 inx++;
433 if (inx >= NUM_RX_DESCRIPTORS)
434 inx = 0;
435 if (inx == RxDescIndex)
436 {
437 taskEXIT_CRITICAL();
438 return (NULL);
439 }
440 }
441 RxDescIndex = (inx == NUM_RX_DESCRIPTORS - 1) ? 0 : (inx + 1);
442 taskEXIT_CRITICAL();
443 return (&RxDescriptor[inx]);
444}
445
446static void SendData(EMACIODescriptor *pxTxIOD, uint32_t DataLength)
447{
448 if (TraceNet)
449 PrintBuffer((uint8_t *)pxTxIOD->DMA.pvBuffer1, DataLength);
450 pxTxIOD->DMA.ui32Count = // DES1_TX_CTRL_SADDR_INSERT |
451 (DataLength) << DES1_TX_CTRL_BUFF1_SIZE_S;
452 pxTxIOD->DMA.ui32CtrlStatus = DES0_TX_CTRL_LAST_SEG |
453 DES0_TX_CTRL_FIRST_SEG | DES0_TX_CTRL_INTERRUPT |
454 // DES0_TX_CTRL_IP_HDR_CHKSUM | //DES0_TX_CTRL_IP_HDR_PAY_CHKSUM |
455 // //DES0_TX_CTRL_IP_ALL_CKHSUMS |
456 DES0_TX_CTRL_CHAINED | DES0_TX_CTRL_OWN;
457 EMACTxDMAPollDemand(EMAC0_BASE);
458}
459
460BaseType_t xNetworkInterfaceOutput(
461 NetworkBufferDescriptor_t *const pxDescriptor, BaseType_t xReleaseAfterSend)
462{
463 EMACIODescriptor *pxTxIOD;
464
465 /* Obtain a DMA transmit descriptor */
466 if (xQueueReceive(TxBufferQueue, &pxTxIOD, pdMS_TO_TICKS(5)) != pdTRUE)
467 {
468 // no buffer available
469 return pdFALSE;
470 }
471 /* mark buffer as busy */
472 pxTxIOD->Flags = IOBUSY;
473
474 /* copy data to dedicated TxBuffer */
475 memcpy(pxTxIOD->DMA.pvBuffer1, pxDescriptor->pucEthernetBuffer,
476 pxDescriptor->xDataLength);
477
478 /* Send the data */
479 SendData(pxTxIOD, pxDescriptor->xDataLength);
480
481 /* Call the standard trace macro to log the send event. */
482 iptraceNETWORK_INTERFACE_TRANSMIT();
483
484 if (xReleaseAfterSend != pdFALSE)
485 {
486 /* Release the NetworkBufferDescriptor
487 */
488 vReleaseNetworkBufferAndDescriptor(pxDescriptor);
489 // PrintStr("No wait\n");
490 }
491
492 return pdTRUE;
493}
494
495void prvEMACDeferredInterruptHandlerTask(void *pvParameters)
496{
497 uint32_t IntStatus, CtrlStatus;
498 NetworkBufferDescriptor_t *pxDescriptor;
499 EMACIODescriptor *pxRxIOD;
500
501 IPStackEvent_t xRxEvent;
502
503 for (;;)
504 {
505 /* Wait for the Ethernet MAC interrupt */
506
507 while (
508 xQueueReceive(xEMACEventQueue, &IntStatus, portMAX_DELAY) == pdTRUE)
509 {
510 if (IntStatus & EMAC_INT_RECEIVE)
511 {
512 /* Deal with completed receive DMA descriptors */
513 while ((pxRxIOD = GetNextRxDescriptor()) != NULL)
514 {
515 /* Allocate new NetworkBufferDescriptor with buffer to pass
516 * results IPTask
517 */
518
519 pxDescriptor = pxGetNetworkBufferWithDescriptor(
520 ipTOTAL_ETHERNET_FRAME_SIZE, pdMS_TO_TICKS(50));
521 if (pxDescriptor == NULL)
522 {
523 /* No buffer available: break out of receive while loop
524 */
525 //__asm("BKPT #01");
526 break;
527 }
528
529 CtrlStatus = pxRxIOD->DMA.ui32CtrlStatus;
530 pxDescriptor->xDataLength =
531 (CtrlStatus & DES0_RX_STAT_FRAME_LENGTH_M) >>
532 DES0_RX_STAT_FRAME_LENGTH_S;
533 memcpy(pxDescriptor->pucEthernetBuffer,
534 (uint8_t *)pxRxIOD->DMA.pvBuffer1,
535 pxDescriptor->xDataLength);
536
537 // temp debugging
538 if (TraceNet)
539 {
540 Frame = pxDescriptor->pucEthernetBuffer;
541 FrameLen = pxDescriptor->xDataLength;
542 PrintHex(pxRxIOD->DMA.ui32CtrlStatus);
543 PrintStr("-");
544 PrintBuffer(Frame, FrameLen);
545 }
546
547 // mark as available for DMA
548 pxRxIOD->DMA.ui32CtrlStatus = DES0_RX_CTRL_OWN;
549 // and ensure DMA is active for Rx
550 EMACRxDMAPollDemand(EMAC0_BASE);
551 if (!(CtrlStatus & DES0_RX_STAT_ERR))
552 {
553 // valid frame
554 if (CtrlStatus & DES0_RX_STAT_LAST_DESC)
555 {
556 // last frame
557 if (eConsiderFrameForProcessing(
558 pxDescriptor->pucEthernetBuffer) ==
559 eProcessBuffer)
560 {
561 /* The event about to be sent to the TCP/IP is
562 * an Rx event. */
563 xRxEvent.eEventType = eNetworkRxEvent;
564
565 /* pvData is used to point to the network buffer
566 descriptor that
567 references the received data. */
568 xRxEvent.pvData = (void *)pxDescriptor;
569
570 /* Send the data to the TCP/IP stack. */
571 if (xSendEventStructToIPTask(&xRxEvent, 0) ==
572 pdFALSE)
573 {
574 /* The buffer could not be sent to the IP
575 task so the buffer
576 must be released. */
577 vReleaseNetworkBufferAndDescriptor(
578 pxDescriptor);
579
580 /* Make a call to the standard trace macro
581 to log the
582 occurrence. */
583 iptraceETHERNET_RX_EVENT_LOST();
584 PrintStr("RX Event Lost\n");
585 }
586 else
587 {
588 /* The message was successfully sent to the
589 TCP/IP stack.
590 Call the standard trace macro to log the
591 occurrence. */
592 iptraceNETWORK_INTERFACE_RECEIVE();
593 }
594 }
595 else
596 {
597 /* The Ethernet frame can be dropped, but the
598 Ethernet buffer
599 must be released. */
600 vReleaseNetworkBufferAndDescriptor(
601 pxDescriptor);
602 }
603 }
604 }
605 }
606 }
607
608 if (IntStatus & EMAC_INT_ABNORMAL_INT)
609 {
610 // some sort of error condition occurred
611 PrintStr("EMAC Abnormal Int");
612 PrintHex(IntStatus);
613 PrintStr("\n");
614 }
615
616 if (IntStatus & EMAC_INT_PHY)
617 {
618 // PHY report
619 bool OldState = LinkDown;
620 if ((EMACPHYRead(EMAC0_BASE, 0, EPHY_BMSR) &
621 EPHY_BMSR_LINKSTAT) == 0)
622 {
623 // link down
624 LinkDown = true;
625 }
626 else
627 {
628 // link up
629 LinkDown = false;
630 }
631 // clear PHY interrupt
632 HWREG(EMAC0_BASE + EMAC_O_EPHYMISC) = 1;
633 PrintStr("EMAC PHY Int");
634 if (OldState != LinkDown)
635 {
636 if (LinkDown)
637 {
638 PrintStr(" link down\n");
639 FreeRTOS_NetworkDown();
640 }
641 else
642 {
643 // there is no counterpart to NetworkDown
644 PrintStr(" link up\n");
645 }
646 }
647 else
648 Print('\n');
649 }
650 }
651 }
652}
653
654extern "C" void ethernet_interrupt_handler(void)
655{
656 uint32_t status = EMACIntStatus(EMAC0_BASE, true);
657 BaseType_t TaskWoken = pdFALSE;
658 EMACIODescriptor *pxTxIOD;
659 EMACIntClear(EMAC0_BASE, status);
660 if (status & EMAC_INT_PHY)
661 {
662 // reset the PHY interrupt to avoid recurring interrupts by reading
663 // MISR1
664 uint16_t misr1 = EMACPHYRead(EMAC0_BASE, 0, EPHY_MISR1);
665 (void)misr1;
666 }
667
668 if ((status & EMAC_INT_TRANSMIT) || (status & EMAC_INT_TX_STOPPED))
669 {
670 // process transmit finish here in ISR
671 for (int inx = 0; inx < NUM_TX_DESCRIPTORS; inx++)
672 {
673 pxTxIOD = &TxDescriptor[inx];
674 if (((pxTxIOD->DMA.ui32CtrlStatus & DES0_TX_CTRL_OWN) == 0) &&
675 (pxTxIOD->Flags & IOBUSY))
676 {
677 // completed IO - reset IOBUSY flag
678 pxTxIOD->Flags = 0;
679 xQueueSendFromISR(TxBufferQueue, &pxTxIOD, &TaskWoken);
680 }
681 }
682 status &= ~(EMAC_INT_TRANSMIT | EMAC_INT_TX_STOPPED);
683 }
684
685 if (status != 0)
686 {
687 // still have an interrupt to report
688 xQueueSendFromISR(xEMACEventQueue, &status, &TaskWoken);
689 }
690
691 if (TaskWoken == pdTRUE)
692 taskYIELD();
693}
bool network_layer_preinit(void)
Called before the TCP stack is initialized in FreeRTOS.
Base class for all QMember types that hold data in an expandable format.
Definition Buffer.hxx:195