35#if !defined(PART_TM4C1294NCPDT)
36#error "This driver is only valid for the TM4C1294NCPDT"
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"
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"
62#include "FreeRTOSConfig.h"
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"
77extern const long unsigned cm3_cpu_clock_hz;
80void PrintBuffer(uint8_t *
Buffer,
size_t Len)
83void PrintStr(
const char *Str)
86void PrintHex(uint32_t Val)
95 tEMACDMADescriptor DMA;
96 volatile uint32_t Flags;
99const int EMACIODescriptorExtra =
105#define NUM_TX_DESCRIPTORS 3
106#define NUM_RX_DESCRIPTORS 5
108 TxDescriptor[NUM_TX_DESCRIPTORS];
109static uint16_t RxDescIndex, TxDescIndex;
111static QueueHandle_t TxBufferQueue = NULL;
113static QueueHandle_t xEMACEventQueue = NULL;
115static TaskHandle_t xDIHTask = NULL;
117static bool LinkDown, Initialised =
false;
120#define BUFFER_SIZE (ipTOTAL_ETHERNET_FRAME_SIZE + ipBUFFER_PADDING)
121#define BUFFER_SIZE_ROUNDED_UP ((BUFFER_SIZE + 7) & ~0x07UL)
123uint8_t __attribute__((aligned(4)))
124Buffers[ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS][BUFFER_SIZE_ROUNDED_UP];
126void vNetworkInterfaceAllocateRAMToBuffers(NetworkBufferDescriptor_t
127 pxNetworkBuffers[ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS]);
129uint8_t RxBuffers[NUM_RX_DESCRIPTORS][ipTOTAL_ETHERNET_FRAME_SIZE],
130 TxBuffers[NUM_TX_DESCRIPTORS][ipTOTAL_ETHERNET_FRAME_SIZE];
132#error "This implementation requires use of STATIC_BUFFERS"
135static bool get_mac_address(uint8_t MACAddr[6]);
137static bool InitialiseEthernet(
void);
138static bool InitialiseDIH(
void);
142extern "C" void prvEMACDeferredInterruptHandlerTask(
void *pvParameters);
144int FramesRecv = 0, FrameLen = 0;
147static bool get_mac_address(uint8_t MACAddr[6])
149 uint32_t User0, User1;
150 FlashUserGet(&User0, &User1);
151 if ((User0 == 0xffffffff) || (User1 == 0xffffffff))
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;
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};
183 get_mac_address(MACAddr);
185 if (FreeRTOS_IPInit(IPAddr, NetMask, Gateway, DNSAddr, MACAddr) != pdPASS)
192static bool InitialiseDIH(
void)
195 if (xEMACEventQueue == NULL)
197 xQueueCreate(ipconfigEVENT_QUEUE_LENGTH,
sizeof(uint32_t));
198 if (xEMACEventQueue == NULL)
205 if (xDIHTask == NULL)
207 if (xTaskCreate(prvEMACDeferredInterruptHandlerTask,
"EthernetISR",
208 2 * configMINIMAL_STACK_SIZE, &xDIHTask,
209 configMAX_PRIORITIES - 2, NULL) != pdPASS)
217static bool InitialiseEthernet(
void)
227 TxDescIndex = NUM_TX_DESCRIPTORS - 1;
239 if (TxBufferQueue == 0)
242 if (TxBufferQueue == 0)
254 EMACReset(EMAC0_BASE);
257 xQueueReset(TxBufferQueue);
261 taskDISABLE_INTERRUPTS();
264 if (get_mac_address(MACAddr))
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);
278 MAP_SysCtlPeripheralEnable(SYSCTL_PERIPH_EMAC0);
279 MAP_SysCtlPeripheralEnable(SYSCTL_PERIPH_EPHY0);
280 MAP_SysCtlPeripheralReset(SYSCTL_PERIPH_EMAC0);
281 MAP_SysCtlPeripheralReset(SYSCTL_PERIPH_EPHY0);
284 while (!MAP_SysCtlPeripheralReady(SYSCTL_PERIPH_EMAC0))
289 EMACPHYConfigSet(EMAC0_BASE, EMAC_PHY_TYPE_INTERNAL | EMAC_PHY_INT_MDIX_EN |
290 EMAC_PHY_AN_100B_T_FULL_DUPLEX);
293 EMACPHYWrite(EMAC0_BASE, PHYAddr, EPHY_MISR1, EPHY_MISR1_LINKSTATEN);
295 EMACPHYWrite(EMAC0_BASE, PHYAddr, EPHY_SCR, EPHY_SCR_INTEN);
297 HWREG(EMAC0_BASE + EMAC_O_EPHYIM) = 1;
299 HWREG(EMAC0_BASE + EMAC_O_EPHYMISC) = 1;
302 EMACReset(EMAC0_BASE);
304 EMACInit(EMAC0_BASE, cm3_cpu_clock_hz,
305 EMAC_BCONFIG_MIXED_BURST | EMAC_BCONFIG_PRIORITY_FIXED, 4, 4,
306 EMACIODescriptorExtra);
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,
316 for (x = 0; x < NUM_TX_DESCRIPTORS; x++)
318 TxIOD = &TxDescriptor[x];
319 TxIOD->DMA.ui32Count = 0;
320 TxIOD->DMA.DES3.pLink =
321 (tEMACDMADescriptor *)((x == NUM_TX_DESCRIPTORS - 1)
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 |
328 TxIOD->DMA.pvBuffer1 = TxBuffers[x];
330 if (xQueueSend(TxBufferQueue, &TxIOD, 0) != pdTRUE)
337 for (x = 0; x < NUM_RX_DESCRIPTORS; x++)
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)
346 : &RxDescriptor[x + 1]);
347 RxDescriptor[x].Flags = 0;
350 EMACRxDMADescriptorListSet(EMAC0_BASE, (tEMACDMADescriptor *)RxDescriptor);
351 EMACTxDMADescriptorListSet(EMAC0_BASE, (tEMACDMADescriptor *)TxDescriptor);
353 EMACAddrSet(EMAC0_BASE, 0, MACAddr);
357 (EMACPHYRead(EMAC0_BASE, PHYAddr, EPHY_BMSR) & EPHY_BMSR_LINKSTAT) == 0)
359 vTaskDelay(pdMS_TO_TICKS(50));
363 EMACFrameFilterSet(EMAC0_BASE,
365 EMAC_FRMFILTER_RX_ALL);
368 EMAC_FRMFILTER_SADDR | EMAC_FRMFILTER_PASS_MULTICAST |
369 EMAC_FRMFILTER_PASS_NO_CTRL);
373 EMACIntClear(EMAC0_BASE,EMACIntStatus(EMAC0_BASE,
false));
375 for (x = 0; x < NUM_RX_DESCRIPTORS; x++)
377 RxDescriptor[x].DMA.ui32CtrlStatus = DES0_RX_CTRL_OWN;
380 EMACTxEnable(EMAC0_BASE);
381 EMACRxEnable(EMAC0_BASE);
383 MAP_IntPrioritySet(INT_EMAC0, 0xa0);
384 IntEnable(INT_EMAC0);
386 EMACIntEnable(EMAC0_BASE,
390 EMAC_INT_RX_WATCHDOG |
391 EMAC_INT_RX_STOPPED |
392 EMAC_INT_TX_UNDERFLOW |
393 EMAC_INT_RX_OVERFLOW |
395 EMAC_INT_TX_STOPPED |
399 taskENABLE_INTERRUPTS();
405void vNetworkInterfaceAllocateRAMToBuffers(NetworkBufferDescriptor_t
406 pxNetworkBuffers[ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS])
408 for (
int x = 0; x < ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS; x++)
411 pxNetworkBuffers[x].pucEthernetBuffer = &(Buffers[x][ipBUFFER_PADDING]);
413 *((uint32_t *)&Buffers[x][0]) = (uint32_t) & (pxNetworkBuffers[x]);
418BaseType_t xNetworkInterfaceInitialise(
void)
420 if (InitialiseEthernet())
428 uint16_t inx = RxDescIndex;
429 taskENTER_CRITICAL();
430 while (RxDescriptor[inx].DMA.ui32CtrlStatus & DES0_RX_CTRL_OWN)
433 if (inx >= NUM_RX_DESCRIPTORS)
435 if (inx == RxDescIndex)
441 RxDescIndex = (inx == NUM_RX_DESCRIPTORS - 1) ? 0 : (inx + 1);
443 return (&RxDescriptor[inx]);
449 PrintBuffer((uint8_t *)pxTxIOD->DMA.pvBuffer1, DataLength);
450 pxTxIOD->DMA.ui32Count =
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 |
456 DES0_TX_CTRL_CHAINED | DES0_TX_CTRL_OWN;
457 EMACTxDMAPollDemand(EMAC0_BASE);
460BaseType_t xNetworkInterfaceOutput(
461 NetworkBufferDescriptor_t *
const pxDescriptor, BaseType_t xReleaseAfterSend)
466 if (xQueueReceive(TxBufferQueue, &pxTxIOD, pdMS_TO_TICKS(5)) != pdTRUE)
472 pxTxIOD->Flags = IOBUSY;
475 memcpy(pxTxIOD->DMA.pvBuffer1, pxDescriptor->pucEthernetBuffer,
476 pxDescriptor->xDataLength);
479 SendData(pxTxIOD, pxDescriptor->xDataLength);
482 iptraceNETWORK_INTERFACE_TRANSMIT();
484 if (xReleaseAfterSend != pdFALSE)
488 vReleaseNetworkBufferAndDescriptor(pxDescriptor);
495void prvEMACDeferredInterruptHandlerTask(
void *pvParameters)
497 uint32_t IntStatus, CtrlStatus;
498 NetworkBufferDescriptor_t *pxDescriptor;
501 IPStackEvent_t xRxEvent;
508 xQueueReceive(xEMACEventQueue, &IntStatus, portMAX_DELAY) == pdTRUE)
510 if (IntStatus & EMAC_INT_RECEIVE)
513 while ((pxRxIOD = GetNextRxDescriptor()) != NULL)
519 pxDescriptor = pxGetNetworkBufferWithDescriptor(
520 ipTOTAL_ETHERNET_FRAME_SIZE, pdMS_TO_TICKS(50));
521 if (pxDescriptor == NULL)
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);
540 Frame = pxDescriptor->pucEthernetBuffer;
541 FrameLen = pxDescriptor->xDataLength;
542 PrintHex(pxRxIOD->DMA.ui32CtrlStatus);
544 PrintBuffer(Frame, FrameLen);
548 pxRxIOD->DMA.ui32CtrlStatus = DES0_RX_CTRL_OWN;
550 EMACRxDMAPollDemand(EMAC0_BASE);
551 if (!(CtrlStatus & DES0_RX_STAT_ERR))
554 if (CtrlStatus & DES0_RX_STAT_LAST_DESC)
557 if (eConsiderFrameForProcessing(
558 pxDescriptor->pucEthernetBuffer) ==
563 xRxEvent.eEventType = eNetworkRxEvent;
568 xRxEvent.pvData = (
void *)pxDescriptor;
571 if (xSendEventStructToIPTask(&xRxEvent, 0) ==
577 vReleaseNetworkBufferAndDescriptor(
583 iptraceETHERNET_RX_EVENT_LOST();
584 PrintStr(
"RX Event Lost\n");
592 iptraceNETWORK_INTERFACE_RECEIVE();
600 vReleaseNetworkBufferAndDescriptor(
608 if (IntStatus & EMAC_INT_ABNORMAL_INT)
611 PrintStr(
"EMAC Abnormal Int");
616 if (IntStatus & EMAC_INT_PHY)
619 bool OldState = LinkDown;
620 if ((EMACPHYRead(EMAC0_BASE, 0, EPHY_BMSR) &
621 EPHY_BMSR_LINKSTAT) == 0)
632 HWREG(EMAC0_BASE + EMAC_O_EPHYMISC) = 1;
633 PrintStr(
"EMAC PHY Int");
634 if (OldState != LinkDown)
638 PrintStr(
" link down\n");
639 FreeRTOS_NetworkDown();
644 PrintStr(
" link up\n");
654extern "C" void ethernet_interrupt_handler(
void)
656 uint32_t status = EMACIntStatus(EMAC0_BASE,
true);
657 BaseType_t TaskWoken = pdFALSE;
659 EMACIntClear(EMAC0_BASE, status);
660 if (status & EMAC_INT_PHY)
664 uint16_t misr1 = EMACPHYRead(EMAC0_BASE, 0, EPHY_MISR1);
668 if ((status & EMAC_INT_TRANSMIT) || (status & EMAC_INT_TX_STOPPED))
671 for (
int inx = 0; inx < NUM_TX_DESCRIPTORS; inx++)
673 pxTxIOD = &TxDescriptor[inx];
674 if (((pxTxIOD->DMA.ui32CtrlStatus & DES0_TX_CTRL_OWN) == 0) &&
675 (pxTxIOD->Flags & IOBUSY))
679 xQueueSendFromISR(TxBufferQueue, &pxTxIOD, &TaskWoken);
682 status &= ~(EMAC_INT_TRANSMIT | EMAC_INT_TX_STOPPED);
688 xQueueSendFromISR(xEMACEventQueue, &status, &TaskWoken);
691 if (TaskWoken == pdTRUE)
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.