📄 emac_local_loopback_example.c
字号:
printf("\nMake sure to use a loopback connector if not\n");
printf("using local loopback (#define LOCAL_LOOPBACK 1)\n");
}
exit (0);
}
/*
* =============================================================================
* @func HwRxInt
*
* @desc
* Interrupt service routine called as a result of the EMAC hardware Rx
* interrupt.
*
* @arg
* None
*
* @eg
* HwRxInt(); // Refer description
* =============================================================================
*/
void interrupt HwRxInt(void)
{
Uint32 i;
if (hEMAC)
{
i = EMAC_RxServiceCheck(hEMAC, 0);
if (i)
{
return;
// printf("EMAC_RxServiceCheck() returned error %08x\n",i);
}
}
return;
}
/*
* =============================================================================
* @func HwTxInt
*
* @desc
* Interrupt service routine called as a result of the EMAC hardware Tx
* interrupt.
*
* @arg
* None
*
* @eg
* HwTxInt(); // Refer description
* =============================================================================
*/
void interrupt HwTxInt(void)
{
Uint32 i;
if (hEMAC)
{
i = EMAC_TxServiceCheck(hEMAC, 0);
if (i)
{
return;
// printf("EMAC_TxServiceCheck() returned error %08x\n",i);
}
}
return;
}
/*
* =============================================================================
* @func TimerTick
*
* @desc
* Timer tick service routine - called from 100mS PRD
*
* @arg
* None
*
* @eg
* TimerTick(); // Refer description
* =============================================================================
*/
void interrupt TimerTick(void)
{
/* Keep track of time for our local timeout loops */
LocalTicks++;
/* Poll the EMAC */
if (hEMAC)
{
OUREMAC_enter();
EMAC_timerTick(hEMAC, 0);
OUREMAC_exit();
}
}
/*
* =============================================================================
* @func GetPacket - Get empty packet for RX.
*
* @desc
* This function is called from the EMAC module to get an empty packet
* buffer. We need to return a packet buffer to the EMAC or return NULL
* if there are no buffers available.
*
* @arg
* hApplication Handle to the application
*
* @eg
* Handle hApp;
* ... // Initialize and get a value to handle- done elsewhere.
* GetPacket(hApp); // Refer description
* ...
* =============================================================================
*/
static EMAC_Pkt *GetPacket( Handle hApplication )
{
EMAC_Pkt *pPkt;
/* Verify our handle came back OK. We don't use it in this example */
if( (Uint32)hApplication != 0x12345678 ) {
//printf("GetPacket(): Bad App Handle!\n");
return(0);
}
/* Pop a packet off our local free queue */
pPkt = App_pqPop(&FreeQueue);
if( pPkt ) {
/*
* Here we tell the EMAC what offset to use by setting
* the DataOffset field in the packet.
*/
pPkt->DataOffset = 0;
/*
* IMPORTANT: If our data packet were in EXTERNAL memory,
* we would have to invalidated it from the CACHE before
* returning it to the EMAC module!!!
*
* We should probably do the clean operation right here.
* However, we are most likely inside an ISR right now.
* It may be better to invalidate the buffer before it
* is pushed on the FreeQueue.
*/
}
return( pPkt );
}
/*
* =============================================================================
* @func FreePacket
*
* @desc
* Free packet that originated from TX or GetPacket(). This function is
* called from the EMAC module to free a packet buffer after a TX
* operation (or RX in the case of a RX shutdown).
*
* @arg
* hApplication handle to the application
* pPKT poiner to the EMAC packet
*
* @eg
* Handle hApp;
* EMAC_Pkt *emacPkt;
* ...
* FreePacket(hApp, emacPkt); // Refer description
* ...
* =============================================================================
*/
static void FreePacket( Handle hApplication, EMAC_Pkt *pPKT )
{
/* Verify our handle came back OK. We don't use it in this example */
if( (Uint32)hApplication != 0x12345678 ) {
return;
}
App_pqPush( &FreeQueue, pPKT );
}
/*
*
*
*/
/*
* =============================================================================
* @func RxPacket - Reveived packet from the Network.
*
* @desc
* This function is called by the EMAC to indicate a receive. Here
* we just push the packet onto our receive queue.
*
* This function returns a free packet to replace the RX packet on
* the EMAC queue. If there are no free packets available, we
* return NULL.
*
* @arg
* hApplication handle to the application
* pPKT poiner to the EMAC packet
*
* @eg
* Handle hApp;
* EMAC_Pkt *emacPkt;
* ...
* RxPacket(hApp, emacPkt); // Refer description
* ...
* =============================================================================
*/
static EMAC_Pkt *RxPacket( Handle hApplication, EMAC_Pkt *pPKT )
{
/* Verify our handle came back OK. We don't use it in this example */
if( (Uint32)hApplication != 0x12345678 ) {
return(0);
}
/* Push this packet onto our local receive queue */
App_pqPush( &RxQueue, pPKT );
/* We must return a free packet to replace the one we were given */
return( GetPacket(hApplication) );
}
/*
* =============================================================================
* @func StatusUpdate
*
* @desc
* The EMAC or MDIO status has changed
*
* @arg
* hApplication handle to the application
*
* @eg
* Handle hApp;
* ...
* StatusUpdate(hApp); // Refer description
* ...
* =============================================================================
*/
static void StatusUpdate( Handle hApplication )
{
/* Verify our handle came back OK. We don't use it in this example */
if( (Uint32)hApplication != 0x12345678 ) {
return;
}
/*
* The status update function is called for a variety of
* reasons, including LINK change events and EMAC errors.
* We'll get the current status and print it out. Note we
* don't start sending packets until we have a good link.
*
*/
EMAC_getStatus( hEMAC, &status, 0);
LinkStatus = status.MdioLinkStatus;
/* if( !LinkStatus )
printf("Link Status: %s\n",LinkStr[LinkStatus]);
else if( LinkStatus <= 4 )
printf("Link Status : %s on PHY number %d\n",
LinkStr[LinkStatus],status.PhyDev);
printf("Packets Held : %d-RX %d-TX\n",
status.RxPktHeld, status.TxPktHeld);
if( status.FatalError )
printf("Fatal Error : %d\n",status.FatalError);
*/
}
/*
* =============================================================================
* @func StatisticsUpdate
*
* @desc
* The EMAC statistics are in danger of overflow
*
* @arg
* hApplication handle to the application
*
* @eg
* Handle hApp;
* ...
* StatisticsUpdate(hApp); // Refer description
* ...
* =============================================================================
*/
static void StatisticsUpdate( Handle hApplication )
{
/* Verify our handle came back OK. We don't use it in this example */
if( (Uint32)hApplication != 0x12345678 ) {
return;
}
/*
* Here we could call the EMAC_getStatistics() function and pass
* them to whoever wants them. This example app doesn't have
* anything to do with them so we do nothing.
*/
}
/*
* =============================================================================
* @func verify_packet()
*
* @desc
* Perform a sanity check validation on the packet
*
* @arg
* pPkt EMAC packet
* size size to validate
*
* @eg
* EMAC_Pkt *pkt;
* Uint32 size;
* ... ; // variables to get value elsewhere.
* verify_packet(pkt, size);
* ...
* =============================================================================
*/
static int verify_packet( EMAC_Pkt *pPkt, Uint32 size )
{
int i;
Uint8 *pBuf;
if( (pPkt->Flags & (EMAC_PKT_FLAGS_SOP | EMAC_PKT_FLAGS_EOP)) !=
(EMAC_PKT_FLAGS_SOP | EMAC_PKT_FLAGS_EOP) ) {
printf("Verify: Bad Flags %08x\n",pPkt->Flags);
return(0);
}
if( pPkt->ValidLen != size ) {
printf("Verify: Bad ValidLen %d %d\n",pPkt->ValidLen,size);
return(0);
}
if( pPkt->DataOffset != 0 ) {
printf("Verify: Bad DataOffset %d\n",pPkt->DataOffset);
return(0);
}
if( pPkt->PktChannel != 0 ) {
printf("Verify: Bad Channel %d\n",pPkt->PktChannel);
return(0);
}
if( pPkt->PktLength != size ) {
printf("Verify: Bad PktLength %d\n",pPkt->PktLength);
return(0);
}
if( pPkt->PktFrags != 1 ) {
printf("Verify: Bad Frag Count %d\n",pPkt->PktFrags);
return(0);
}
pBuf = pPkt->pDataBuffer+pPkt->DataOffset;
for( i=0; i<size; i++, pBuf++ )
if( *pBuf != (i&0xFF) ) {
printf("Verify: Bad data at %d (%d)(%d)\n",i,*pBuf,i&0xff);
return(0);
}
return(1);
}
/* ============================================================================
* @func App_pqPop()
*
* @desc
* Pop a desc buffer off a queue
*
* @arg
* pq Application packet
*
* @eg
* APP_PKTQ *pq;
* ... ; // variables to get value elsewhere.
* App_pqPop(pq);
* ...
* ============================================================================
*/
static EMAC_Pkt *App_pqPop( APP_PKTQ *pq )
{
EMAC_Pkt *pPktHdr;
OUREMAC_enter();
pPktHdr = pq->pHead;
if( pPktHdr ) {
pq->pHead = pPktHdr->pNext;
pq->Count--;
pPktHdr->pPrev = pPktHdr->pNext = 0;
}
OUREMAC_exit();
return( pPktHdr );
}
/* ============================================================================
* @func App_pqPush()
*
* @desc
* Push a desc buffer onto a queue
*
* @arg
* pq Application packet
* pPktHdr pointer to EMAC pakcet header
*
* @eg
* APP_PKTQ *pq;
* EMAC_Pkt *pPktHdr;
* ... ; // variables to get value elsewhere.
* App_pqPush(pq, pPktHdr);
* ...
* ============================================================================
*/
static void App_pqPush( APP_PKTQ *pq, EMAC_Pkt *pPktHdr )
{
OUREMAC_enter();
pPktHdr->pNext = 0;
if( !pq->pHead ) {
/* Queue is empty - Initialize it with this one packet */
pq->pHead = pPktHdr;
pq->pTail = pPktHdr;
}
else {
// Queue is not empty - Push onto END
pq->pTail->pNext = pPktHdr;
pq->pTail = pPktHdr;
}
pq->Count++;
OUREMAC_exit();
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -