I want to modify ndk driver for my device,but I my driver stop at ’‘ i = EMAC_open( 1, (Handle)0x12345678, &ecfg, &hEMAC )’‘ in’‘ ethdriver.c’‘,
and the function EMAC_open it does not run at all,what wrong with it?
I am using
bios_6_35_01_29
xdctools_3_25_00_48
ndk_2_22_03_20
nsp_1_10_02_09
/** * @file ethdriver.c * * @brief * Ethernet Packet Driver written using the CSL and NIMU * Packet Architecture guidelines. * * \par * NOTE: * (C) Copyright 2008, Texas Instruments, Inc. * * \par */ #include <stdio.h> #include <string.h> #include <xdc/std.h> #include <stkmain.h> #include <emac_common.h> #include <nimu_eth.h> #include <csl_emac.h> #include <csl_emacAux.h> /********************************************************************** ****************** Global Variables / Definitions ******************** **********************************************************************/ /* use compiler(-specific) intrinsics */ #define disableInterrupts() _disable_interrupts() #define restoreInterrupts(key) _restore_interrupts(key) #define PKT_MAX 64 #if defined(__TMS470__) #define CORENUM 0 #define RXINT 34 #define TXINT 35 /*! TODO: review for ARM */ #define EXTERNAL_MEMORY 1 #define EXTMEM 0x80000000 #else #define CORENUM 1 #define RXINT 5 #define TXINT 6 #define EXTERNAL_MEMORY 1 #define EXTMEM 0x80000000 #endif static Handle hEMAC = 0; /* Handle to our EMAC instance */ static PDINFO *pPDI = 0; /* Handle to Device Info */ static Handle hMDIO = 0; /* Handle to MDIO instance */ static Uint32 csl_errors = 0; /* CSL returned error due to software */ static Uint32 emac_fatal_error = 0; /* EMAC fatal error */ static Uint32 coreNum = CORENUM; static Uint32 PktMTU; static UINT8 bMacAddr[6] = {0x0, 0x11, 0x22, 0x33, 0x44, 0x55}; static Uint32 FlashActiveLED = 0; /* Array of initialized EMAC packet buffers to handle incoming packets */ static EMAC_Pkt rcv_pkt[PKT_MAX]; /* Array of EMAC packet placeholders to handle tx packets */ static EMAC_Pkt send_pkt[PKT_MAX]; int memory_squeeze_error = 0; /** * * Configuration (Obtained via callback) * */ /* ideally we want to add one more param to getConfig, indicating mii/rmii phy mode, * so that we can dynamically configure as necessary at init time * instead rebuilding the library */ extern void EMAC_initialize(void); extern void EMAC_getConfig( UINT8 *pMacAddr ); extern void EMAC_linkStatus( uint phy, uint linkStatus ); /** * @brief * EMAC_Pkt Queue Data Structure * * @details * Maintains the count of queued elements and head and tail to EMAC_Pkt queue. */ typedef struct pkt_queue { /** * @brief Number of packets in queue */ Uint32 Count; /** * @brief Pointer to first packet */ EMAC_Pkt *pHead; /** * @brief Pointer to last packet */ EMAC_Pkt *pTail; } PKT_QUEUE; static PKT_QUEUE RxQueue; /* Receive Queue */ static PKT_QUEUE TxQueue; /* Transmit Queue */ static EMAC_Pkt *Queue_pop( PKT_QUEUE *pq ); static void Queue_push( PKT_QUEUE *pq, EMAC_Pkt *pPktHdr ); static void Interrupt_init(void); static void Interrupt_end(void); /********************************************************************** *************************** EMAC Functions *************************** **********************************************************************/ /** * @b Queue_pop * @n * Dequeues a packet from EMAC_Pkt queue. * * @param[in] pq * Packet queue of type PKT_QUEUE . * * @retval * EMAC_Pkt popped from the queue. */ static EMAC_Pkt *Queue_pop( PKT_QUEUE *pq ) { EMAC_Pkt *pPktHdr = NULL; UInt key; key = disableInterrupts(); pPktHdr = pq->pHead; if( pPktHdr ) { pq->pHead = pPktHdr->pNext; pq->Count--; pPktHdr->pPrev = pPktHdr->pNext = 0; } restoreInterrupts(key); return( pPktHdr ); } /** * @b Queue_push * @n * Enqueues a packet in EMAC_Pkt queue. * * @param[in] pq * Packet queue of type PKT_QUEUE . * @param[in] pPktHdr * EMAC_Pkt type packet to push. * * @retval * void */ static void Queue_push( PKT_QUEUE *pq, EMAC_Pkt *pPktHdr ) { UInt key; key = disableInterrupts(); 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++; restoreInterrupts(key); } /** * @b GetPacket * @n * Returns a packet from the RxQueue. * * @param[in] hApplication * Driver's handle. * * @retval * EMAC_Pkt pointer of a packet with buffer to replenish CSL. */ static EMAC_Pkt *GetPacket( Handle hApplication ) { EMAC_Pkt *pPkt = NULL; if( (Uint32)hApplication != 0x12345678 ) { return NULL; } pPkt = Queue_pop(&RxQueue); if( pPkt ) { pPkt->DataOffset = PBM_getDataOffset(pPkt->AppPrivate); } #ifdef EXTERNAL_MEMORY /* Clean the cache for external addesses */ if( (UINT32)(PBM_getDataBuffer(pPkt->AppPrivate)) & EXTMEM ) OEMCacheClean( (void *)(PBM_getDataBuffer(pPkt->AppPrivate)), PBM_getBufferLen(pPkt->AppPrivate) ); #endif return( pPkt ); } /** * @b FreePacket * @n * Called by CSL to free the buffer. * * @param[in] hApplication * Driver's handle. * @param[in] cslPkt * EMAC_Pkt type packet passed by CSL. * * @retval * void */ static void FreePacket( Handle hApplication, EMAC_Pkt *cslPkt ) { if( (Uint32)hApplication != 0x12345678 ) { return; } PBM_free( (PBM_Handle)cslPkt->AppPrivate ); Queue_push( &TxQueue, cslPkt ); } /** * @b RxPacket * @n * Function called by CSL to pass the received packet to the driver. * * @param[in] hApplication * Driver's handle. * @param[in] cslPkt * EMAC_Pkt type packet passed by CSL. * * @retval * EMAC_Pkt pointer of a packet with buffer to replenish CSL. */ static EMAC_Pkt *RxPacket(Handle hApplication, EMAC_Pkt *cslPkt) { PBM_Handle hPkt; if( (Uint32)hApplication != 0x12345678 ) { return NULL; } hPkt = PBM_alloc(PktMTU + 4 + PKT_PREPAD); if (hPkt) { PBM_setValidLen((PBM_Handle) cslPkt->AppPrivate, cslPkt->ValidLen); PBM_setIFRx((PBM_Handle) cslPkt->AppPrivate, pPDI->hEther ); PBMQ_enq( &pPDI->PBMQ_rx, (PBM_Handle) cslPkt->AppPrivate ); /* Notify NDK stack of pending Rx Ethernet packet */ STKEVENT_signal( pPDI->hEvent, STKEVENT_ETHERNET, 1 ); PBM_setDataOffset( hPkt, PKT_PREPAD ); cslPkt->AppPrivate = (Uint32)hPkt; cslPkt->pDataBuffer = PBM_getDataBuffer(hPkt); cslPkt->BufferLen = PBM_getBufferLen(hPkt); cslPkt->DataOffset = PBM_getDataOffset(hPkt); #ifdef EXTERNAL_MEMORY /* Clean the cache for external addesses */ if( (UINT32)(PBM_getDataBuffer(cslPkt->AppPrivate)) & EXTMEM ) OEMCacheClean( (void *)(PBM_getDataBuffer(cslPkt->AppPrivate)), PBM_getBufferLen(cslPkt->AppPrivate) ); #endif return( cslPkt ); } /* Increment the statistics to account for packets dropped because * of memory squeeze */ memory_squeeze_error++; return cslPkt; } /** * @b StatusUpdate * @n * Called from CSL on Rx/Tx MACFATAL error and from CSL timer tick function. * Tells the driver of a status update. * * @param[in] hApplication * Driver's Handle. * * @retval * void */ static void StatusUpdate( Handle hApplication ) { if( (Uint32)hApplication != 0x12345678 ) { return; } emac_fatal_error++; } /** * @b StatisticsUpdate * @n * Called by CSL to indicate a statistic update * interrupt. * * @param[in] hApplication * Driver's Handle. * * @retval * void */ static void StatisticsUpdate( Handle hApplication ) { if( (Uint32)hApplication != 0x12345678 ) { return; } } /** * @b HwPktInit * @n * Initializes the device MAC address to use. * * @param[in] void * * @retval * Success - 1 * @retval * Error - 0 */ uint HwPktInit() { /* Get our EMAC address to use, overriding default initializer */ EMAC_getConfig(bMacAddr); return (1); } /** * @b HwPktShutdown * @n * Void * * @param[in] void * * @retval * void */ void HwPktShutdown() { } /** * @b HwPktOpen * @n * Opens and configures EMAC. Configures Interrupts, SGMII, * and send and receive queues. * * @param[in] pi * PDINFO structure pointer. * * @retval * Success - 0 * @retval * Error - >0 */ uint HwPktOpen( PDINFO *pi ) { Uint32 i, j; PBM_Handle hPkt; EMAC_Config ecfg; EMAC_AddrConfig *addrCfg; UInt key; pPDI = pi; ecfg.UseMdio = 1; ecfg.CoreNum = CORENUM; ecfg.PktMTU = 1514; ecfg.TotalNumOfMacAddrs = 1; ecfg.DescBase = EMAC_DESC_BASE_CPPI; PktMTU = ecfg.PktMTU; memset(&RxQueue, 0, sizeof(PKT_QUEUE)); memset(&TxQueue, 0, sizeof(PKT_QUEUE)); /* Queue up some initialized receive buffers */ for( i=0; i<PKT_MAX; i++ ) { hPkt = PBM_alloc(ecfg.PktMTU); /* Couldnt allocate memory, return error */ if (hPkt == NULL) return 1; rcv_pkt[i].AppPrivate = (Uint32)hPkt; rcv_pkt[i].pDataBuffer = PBM_getDataBuffer(hPkt); rcv_pkt[i].BufferLen = PBM_getBufferLen(hPkt); Queue_push( &RxQueue, &rcv_pkt[i] ); } /* Queue up some transmit buffers */ for( i=0; i<PKT_MAX; i++ ) { Queue_push( &TxQueue, &send_pkt[i] ); } ecfg.ModeFlags = EMAC_CONFIG_MODEFLG_RXOFFLENBLOCK | EMAC_CONFIG_MODEFLG_RMII; ecfg.MdioModeFlags = MDIO_MODEFLG_AUTONEG; /* channel usage must be mutual exclusive among cores */ ecfg.ChannelInfo[0].RxChanEnable = 1; ecfg.ChannelInfo[0].TxChanEnable = 1; ecfg.ChannelInfo[1].RxChanEnable = 2; ecfg.ChannelInfo[1].TxChanEnable = 2; ecfg.RxMaxPktPool = 8; ecfg.pfcbGetPacket = &GetPacket; ecfg.pfcbFreePacket = &FreePacket; ecfg.pfcbRxPacket = &RxPacket; ecfg.pfcbStatus = &StatusUpdate; ecfg.pfcbStatistics = &StatisticsUpdate; /* allocate memory to two dimensional array to hold MAC addresses */ ecfg.MacAddr = (EMAC_AddrConfig **) mmAlloc(ecfg.TotalNumOfMacAddrs * sizeof(EMAC_AddrConfig *)); for ( j=0; j<ecfg.TotalNumOfMacAddrs; j++ ) { ecfg.MacAddr[j] = (EMAC_AddrConfig *)mmAlloc(sizeof(EMAC_AddrConfig)); } // /* Generate a default MAC address to use */ // for( j=0; (Uint8)j<(ecfg.TotalNumOfMacAddrs); j++ ) // { // addrCfg = ecfg.MacAddr[j]; // addrCfg->ChannelNum = coreNum; // if( j>=3 && j<6 ) // addrCfg->ChannelNum = 1; // if( j>=6 && j<9 ) // addrCfg->ChannelNum = 2; // for( i=0; i<6; i++ ) // { // addrCfg->Addr[i] = j * 0x10 + i ; // } // } // // addrCfg = ecfg.MacAddr[0]; // // /* Check if EMAC_getConfig had returned a valid MAC address to use. If not, // * use the default generated above. // */ // for( i=0; (i<6) && (!(bMacAddr[i])); i++ ); // if( i==6 ) // { // mmCopy( (void *)&pPDI->bMacAddr[0], (void *)&addrCfg->Addr[0], 6 ); // printf("Since EFUSE MAC address is Zero we use th MAC Address = %02x-%02x-%02x-%02x-%02x-%02x\n", // pPDI->bMacAddr[0],pPDI->bMacAddr[1],pPDI->bMacAddr[2],pPDI->bMacAddr[3],pPDI->bMacAddr[4],pPDI->bMacAddr[5]); // } // else // { // mmCopy( (void *)&addrCfg->Addr[0], (void *)&bMacAddr[0], 6 ); // } // // /* Copy the MAC Address into the PDI Structure */ // mmCopy ((void *)&pPDI->bMacAddr[0], (void *)&addrCfg->Addr[0], 6); // // addrCfg = ecfg.MacAddr[3 * coreNum + 2]; //assinging MAC addresses for ( j=0; j<ecfg.TotalNumOfMacAddrs; j++ ) { addrCfg = ecfg.MacAddr[j]; addrCfg->ChannelNum = coreNum; memcpy((void *)&addrCfg->Addr[j], (void *)&bMacAddr[j], 6 ); memcpy((void *)&pPDI->bMacAddr[j], (void *)&addrCfg->Addr[j], 6); printf("MAC Address = %02x-%02x-%02x-%02x-%02x-%02x\n", pPDI->bMacAddr[0], pPDI->bMacAddr[1], pPDI->bMacAddr[2], pPDI->bMacAddr[3], pPDI->bMacAddr[4], pPDI->bMacAddr[5]); } EMAC_initialize(); key = disableInterrupts(); printf("514 \n"); i = EMAC_open( 1, (Handle)0x12345678, &ecfg, &hEMAC ); printf("516 \n"); if( i ) { printf("EMAC OPEN Returned error \n"); csl_errors++; return i; } printf("523 \n"); Interrupt_init(); printf("525 \n"); hMDIO = ((EMAC_Device *)hEMAC)->hMDIO; /* Wait for link to come up */ pi->TxFree = 0; /* Enable general purpose interrupt */ restoreInterrupts(key); printf("EMAC should be up and running\n"); return 0; } /** * @b HwPktClose * @n * Closes EMAC and disables interrupts. * * @param[in] pi * PDINFO structure pointer. * * @retval * void */ void HwPktClose( PDINFO *pi ) { EMAC_Pkt * p; Uint32 i; (void)pi; Interrupt_end(); i = EMAC_close( hEMAC ); if( i ) { csl_errors++; printf("EMAC Close Returned error %08x\n",i); } while ((p = Queue_pop(&RxQueue)) != NULL) { if (p->AppPrivate) { PBM_free((PBM_Handle)p->AppPrivate); } } hEMAC = 0; } /** * @b HwPktSetRx * @n * Sets the filter for EMAC. Also sets ram or hash multicast addresses. * * @param[in] pi * PDINFO structure pointer. * * @retval * void */ void HwPktSetRx( PDINFO *pi ) { uint tmp1,tmp2; int i; Uint8 HashVal,tmpval,*pMCastList; UINT32 temp,temp1,MacHash1,MacHash2; UInt key; /* Clear the hash bits */ MacHash1 = 0; MacHash2 = 0; if ( RAM_MCAST && (PKT_MAX_MCAST < 32) ) /* Use RAM based multicast list */ { /* Clear the multicast list */ for (i = 1; i < 32; i++) { EMAC_REGS->MACINDEX = i; EMAC_REGS->MACADDRHI = 0; EMAC_REGS->MACADDRLO = 0; } /* For each address in the list, add it to the RAM */ pMCastList = pi->bMCast; for( tmp1=0; tmp1<pi->MCastCnt; tmp1++ ) { EMAC_REGS->MACINDEX = tmp1+1; temp = 0; for( i=3; i>=0; i-- ) temp = (temp<<8) | *(pMCastList+i); EMAC_REGS->MACADDRHI = temp; temp = *(pMCastList+4); temp1 = *(pMCastList+5); EMAC_REGS->MACADDRLO = CSL_FMKT( EMAC_MACADDRLO_VALID, VALID ) | CSL_FMKT( EMAC_MACADDRLO_MATCHFILT, MATCH ) | CSL_FMK( EMAC_MACADDRLO_CHANNEL, 0 ) | (temp1<<8) | temp ; pMCastList+=6; } } if ( HASH_MCAST ) /* Use hash tables multicast */ { /* For each address in the list, hash and set the bit */ pMCastList = pi->bMCast; for( tmp1=0; tmp1<pi->MCastCnt; tmp1++ ) { HashVal=0; for( tmp2=0; tmp2<2; tmp2++ ) { tmpval = *pMCastList++; HashVal ^= (tmpval>>2)^(tmpval<<4); tmpval = *pMCastList++; HashVal ^= (tmpval>>4)^(tmpval<<2); tmpval = *pMCastList++; HashVal ^= (tmpval>>6)^(tmpval); } if( HashVal & 0x20 ) MacHash2 |= (1<<(HashVal&0x1f)); else MacHash1 |= (1<<(HashVal&0x1f)); } } ((EMAC_Device *)hEMAC)->MacHash1 = MacHash1; ((EMAC_Device *)hEMAC)->MacHash2 = MacHash2; key = disableInterrupts(); i = EMAC_setReceiveFilter( hEMAC, pi->Filter, coreNum ); restoreInterrupts(key); if( i ) { csl_errors++; printf("EMAC_setReceiveFilter Returned error %08x\n",i); HwPktClose (pi); } } /** * @b HwPktTxNext * @n * Routine to send out a packet. * * @param[in] pi * PDINFO structure pointer. * * @retval * void */ void HwPktTxNext( PDINFO *pi ) { #ifdef EXTERNAL_MEMORY register UINT8 *buffer; register uint length; #endif PBM_Handle hPkt; EMAC_Pkt* csl_send_pkt; Uint32 i; UInt key; /* Checking for any queued packets to be transmitted */ if( !(hPkt = PBMQ_deq(&pi->PBMQ_tx)) ) { pi->TxFree = 1; return; } #ifdef EXTERNAL_MEMORY buffer = PBM_getDataBuffer(hPkt) + PBM_getDataOffset(hPkt); length = PBM_getBufferLen(hPkt); /* Clean the cache for external addesses */ if( (UINT32)buffer & EXTMEM ) OEMCacheClean( (void *)buffer, length ); #endif csl_send_pkt = Queue_pop( &TxQueue ); if( csl_send_pkt ) { csl_send_pkt->AppPrivate = (Uint32)hPkt; csl_send_pkt->pDataBuffer = PBM_getDataBuffer(hPkt); csl_send_pkt->BufferLen = PBM_getBufferLen(hPkt); csl_send_pkt->Flags = EMAC_PKT_FLAGS_SOP | EMAC_PKT_FLAGS_EOP; csl_send_pkt->ValidLen = PBM_getValidLen(hPkt); csl_send_pkt->DataOffset = PBM_getDataOffset(hPkt); csl_send_pkt->PktChannel = coreNum; //0; csl_send_pkt->PktLength = PBM_getValidLen(hPkt); csl_send_pkt->PktFrags = 1; key = disableInterrupts(); i = EMAC_sendPacket(hEMAC, csl_send_pkt); restoreInterrupts(key); if( i ) { csl_errors++; printf("EMAC_sendPacket() returned error %08x\n",i); /* Free the packet as the packet did not go on the wire*/ PBM_free( (PBM_Handle)csl_send_pkt->AppPrivate ); Queue_push( &TxQueue, csl_send_pkt ); } /* Packet has been transmitted */ return; } /* Free the packet as the packet did not go on the wire. */ PBM_free((PBM_Handle)hPkt); return; } /** * @b _HwPktPoll * @n * This function is called at least every 100ms, faster in a * polling environment. The fTimerTick flag is set only when * called on a 100ms event. * * @param[in] pi * PDINFO structure pointer. * @param[in] fTimerTick * Flag for timer, set when called on a 100ms event. * * @retval * void */ void _HwPktPoll( PDINFO *pi, uint fTimerTick ) { uint mdioStatus,phy,linkStatus; UInt key; (void)pi; if( fTimerTick && hMDIO ) { LED_TOGGLE( USER_LED2 ); if(0u != FlashActiveLED ) { FlashActiveLED = 0; LED_TOGGLE( USER_LED3 ); } llEnter(); key = disableInterrupts(); /* Signal the MDIO */ mdioStatus = MDIO_timerTick( hMDIO ); /* Track new or lost link */ if( mdioStatus == MDIO_EVENT_LINKDOWN || mdioStatus == MDIO_EVENT_LINKUP ) { MDIO_getStatus( hMDIO, &phy, &linkStatus ); /* On a new link, set the EMAC duplex */ if( mdioStatus == MDIO_EVENT_LINKUP ) { if( linkStatus == MDIO_LINKSTATUS_FD10 || linkStatus == MDIO_LINKSTATUS_FD100 ) { CSL_FINST( EMAC_REGS->MACCONTROL, EMAC_MACCONTROL_FULLDUPLEX, FULLDUPLEX ); } else { CSL_FINST( EMAC_REGS->MACCONTROL, EMAC_MACCONTROL_FULLDUPLEX, HALFDUPLEX ); } /* Now that we have a link, send any queued packets */ while( !pi->TxFree ) HwPktTxNext( pi ); } /* Notify application of link status change */ EMAC_linkStatus( phy, linkStatus ); } else if ( mdioStatus == MDIO_EVENT_PHYERROR) { printf("NO PHY CONNECTED \n"); } restoreInterrupts(key); llExit(); } } /** * @b HwRxInt * @n * Receive Packet ISR. * * @param[in] void * * @retval * void */ void HwRxInt(void * x) { Uint32 i; if ( hEMAC ) { i = EMAC_RxServiceCheck(hEMAC); if( i ) { if (i == EMAC_ERROR_MACFATAL) emac_fatal_error++; else csl_errors++; } /* write the EOI register */ EMAC_rxEoiWrite(coreNum); } return; } /** * @b HwTxInt * @n * Transmit Complete ISR. * * @param[in] void * * @retval * void */ void HwTxInt(void * x) { Uint32 i; if (hEMAC) { i = EMAC_TxServiceCheck(hEMAC); if(i) { if (i == EMAC_ERROR_MACFATAL) emac_fatal_error++; else csl_errors++; } /* write the EOI register */ EMAC_txEoiWrite(coreNum); } return; } /** * @b Interrupt_init * @n * Registering Interrupts and Enabling global interrupts. * * @param[in] void * * @retval * void */ static void Interrupt_init(void) { IntSetup hwi_intSetup; Uint32 retVal; /* Setup the Rx Int using NDK's Interrupt Manager */ hwi_intSetup.intVectId = RXINT; hwi_intSetup.sysEvtCount = 1; hwi_intSetup.sysEvtId[0] = 31; hwi_intSetup.pCallbackFxn = &HwRxInt; hwi_intSetup.pCallbackArg = 0; hwi_intSetup.bEnable = 1; retVal = Interrupt_add(&hwi_intSetup); if(retVal != 0) printf("Error setting up Rx Interrupts \n"); /* Setup the Tx Int using NDK's Interrupt Manager */ hwi_intSetup.intVectId = TXINT; hwi_intSetup.sysEvtCount = 1; hwi_intSetup.sysEvtId[0] = 32; hwi_intSetup.pCallbackFxn = &HwTxInt; hwi_intSetup.pCallbackArg = 0; hwi_intSetup.bEnable = 1; retVal = Interrupt_add(&hwi_intSetup); if(retVal != 0) printf("Error setting up Tx Interrupts \n"); } /** * @b Interrupt_end * @n * Deregistering the interrupts * * @param[in] void * * @retval * void */ static void Interrupt_end(void) { IntSetup intSetup; intSetup.intVectId = RXINT; Interrupt_delete(&intSetup); intSetup.intVectId = TXINT; Interrupt_delete(&intSetup); }