?? emac.c
字號:
{
AT91C_BASE_EMAC->EMAC_MAN = (AT91C_EMAC_SOF & (0x01 << 30))
| (AT91C_EMAC_CODE & (2 << 16))
| (AT91C_EMAC_RW & (2 << 28))
| (AT91C_EMAC_PHYA & ((PhyAddress & 0x1f) << 23))
| (AT91C_EMAC_REGA & (Address << 18));
if ( EMAC_WaitPhy(retry) == 0 ) {
trace_LOG(trace_ERROR, "TimeOut EMAC_ReadPhy\n\r");
return 0;
}
*pValue = ( AT91C_BASE_EMAC->EMAC_MAN & 0x0000ffff );
return 1;
}
//-----------------------------------------------------------------------------
/// Write PHY register
/// Return 1 if successfully, 0 if timeout.
/// \param PhyAddress PHY Address
/// \param Address Register Address
/// \param Value Data to write ( Actually 16 bit data )
/// \param retry The retry times, 0 to wait forever until complete.
//-----------------------------------------------------------------------------
unsigned char EMAC_WritePhy(unsigned char PhyAddress,
unsigned char Address,
unsigned int Value,
unsigned int retry)
{
AT91C_BASE_EMAC->EMAC_MAN = (AT91C_EMAC_SOF & (0x01 << 30))
| (AT91C_EMAC_CODE & (2 << 16))
| (AT91C_EMAC_RW & (1 << 28))
| (AT91C_EMAC_PHYA & ((PhyAddress & 0x1f) << 23))
| (AT91C_EMAC_REGA & (Address << 18))
| (AT91C_EMAC_DATA & Value) ;
if ( EMAC_WaitPhy(retry) == 0 ) {
trace_LOG(trace_ERROR, "TimeOut EMAC_WritePhy\n\r");
return 0;
}
return 1;
}
//-----------------------------------------------------------------------------
/// Setup the EMAC for the link : speed 100M/10M and Full/Half duplex
/// \param speed Link speed, 0 for 10M, 1 for 100M
/// \param fullduplex 1 for Full Duplex mode
//-----------------------------------------------------------------------------
void EMAC_SetLinkSpeed(unsigned char speed, unsigned char fullduplex)
{
unsigned int ncfgr;
ncfgr = AT91C_BASE_EMAC->EMAC_NCFGR;
ncfgr &= ~(AT91C_EMAC_SPD | AT91C_EMAC_FD);
if (speed) {
ncfgr |= AT91C_EMAC_SPD;
}
if (fullduplex) {
ncfgr |= AT91C_EMAC_FD;
}
AT91C_BASE_EMAC->EMAC_NCFGR = ncfgr;
}
//-----------------------------------------------------------------------------
// EMAC functions
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
/// EMAC Interrupt handler
//-----------------------------------------------------------------------------
void EMAC_Handler(void)
{
volatile EmacTxTDescriptor *pTxTd;
volatile EMAC_TxCallback *pTxCb;
unsigned int isr;
unsigned int rsr;
unsigned int tsr;
unsigned int rxStatusFlag;
unsigned int txStatusFlag;
//trace_LOG(trace_DEBUG, "EMAC_Handler\n\r");
isr = AT91C_BASE_EMAC->EMAC_ISR & AT91C_BASE_EMAC->EMAC_IMR;
rsr = AT91C_BASE_EMAC->EMAC_RSR;
tsr = AT91C_BASE_EMAC->EMAC_TSR;
// RX packet
if ((isr & AT91C_EMAC_RCOMP) || (rsr & AT91C_EMAC_REC)) {
rxStatusFlag = AT91C_EMAC_REC;
// Frame received
EmacStatistics.rx_packets++;
// Check OVR
if (rsr & AT91C_EMAC_OVR) {
rxStatusFlag |= AT91C_EMAC_OVR;
EmacStatistics.rx_ovrs++;
}
// Check BNA
if (rsr & AT91C_EMAC_BNA) {
rxStatusFlag |= AT91C_EMAC_BNA;
EmacStatistics.rx_bnas++;
}
// Clear status
AT91C_BASE_EMAC->EMAC_RSR |= rxStatusFlag;
// Invoke callbacks
if (rxTd.rxCb) {
rxTd.rxCb(rxStatusFlag);
}
}
// TX packet
if ((isr & AT91C_EMAC_TCOMP) || (tsr & AT91C_EMAC_COMP)) {
txStatusFlag = AT91C_EMAC_COMP;
EmacStatistics.tx_comp ++;
// A frame transmitted
// Check RLE
if (tsr & AT91C_EMAC_RLES) {
txStatusFlag |= AT91C_EMAC_RLES;
EmacStatistics.tx_errors++;
}
// Check COL
if (tsr & AT91C_EMAC_COL) {
txStatusFlag |= AT91C_EMAC_COL;
EmacStatistics.collisions++;
}
// Check BEX
if (tsr & AT91C_EMAC_BEX) {
txStatusFlag |= AT91C_EMAC_BEX;
EmacStatistics.tx_exausts++;
}
// Check UND
if (tsr & AT91C_EMAC_UND) {
txStatusFlag |= AT91C_EMAC_UND;
EmacStatistics.tx_underruns++;
}
// Clear status
AT91C_BASE_EMAC->EMAC_TSR |= txStatusFlag;
// Sanity check: Tx buffers have to be scheduled
ASSERT(!CIRC_EMPTY(&txTd),
"-F- EMAC Tx interrupt received meanwhile no TX buffers has been scheduled\n\r");
// Check the buffers
while (CIRC_CNT(txTd.head, txTd.tail, TX_BUFFERS)) {
pTxTd = txTd.td + txTd.tail;
pTxCb = txTd.txCb + txTd.tail;
// Exit if buffer has not been sent yet
if ((pTxTd->status & EMAC_TX_USED_BIT) == 0) {
break;
}
// Notify upper layer that packet has been sent
if (*pTxCb) {
(*pTxCb)(txStatusFlag);
}
CIRC_INC( txTd.tail, TX_BUFFERS );
}
// If a wakeup has been scheduled, notify upper layer that it can send
// other packets, send will be successfull.
if( (CIRC_SPACE(txTd.head, txTd.tail, TX_BUFFERS) >= txTd.wakeupThreshold)
&& txTd.wakeupCb) {
txTd.wakeupCb();
}
}
}
//-----------------------------------------------------------------------------
/// Initialize the EMAC with the emac controller address
/// \param id HW ID for power management
/// \param pTxWakeUpfct Thresold TX Wakeup Callback
/// \param pRxfct RX Wakeup Callback
/// \param pMacAddress Mac Address
/// \param enableCAF enable AT91C_EMAC_CAF if needed by application
/// \param enableNBC AT91C_EMAC_NBC if needed by application
//-----------------------------------------------------------------------------
void EMAC_Init( unsigned char id, const unsigned char *pMacAddress,
unsigned char enableCAF, unsigned char enableNBC )
{
int Index;
unsigned int Address;
// Check parameters
ASSERT(RX_BUFFERS * EMAC_RX_UNITSIZE > EMAC_FRAME_LENTGH_MAX,
"E: RX buffers too small\n\r");
trace_LOG(trace_DEBUG, "EMAC_Init\n\r");
// Power ON
AT91C_BASE_PMC->PMC_PCER = 1 << id;
// Disable TX & RX and more
AT91C_BASE_EMAC->EMAC_NCR = 0;
// disable
AT91C_BASE_EMAC->EMAC_IDR = ~0;
rxTd.idx = 0;
CIRC_CLEAR(&txTd);
// Setup the RX descriptors.
for(Index = 0; Index < RX_BUFFERS; Index++) {
Address = (unsigned int)(&(pRxBuffer[Index * EMAC_RX_UNITSIZE]));
// Remove EMAC_RX_OWNERSHIP_BIT and EMAC_RX_WRAP_BIT
rxTd.td[Index].addr = Address & EMAC_ADDRESS_MASK;
rxTd.td[Index].status = 0;
}
rxTd.td[RX_BUFFERS - 1].addr |= EMAC_RX_WRAP_BIT;
// Setup the TX descriptors.
for(Index = 0; Index < TX_BUFFERS; Index++) {
Address = (unsigned int)(&(pTxBuffer[Index * EMAC_TX_UNITSIZE]));
txTd.td[Index].addr = Address;
txTd.td[Index].status = EMAC_TX_USED_BIT;
}
txTd.td[TX_BUFFERS - 1].status = EMAC_TX_USED_BIT | EMAC_TX_WRAP_BIT;
// Set the MAC address
if( pMacAddress != (unsigned char *)0 ) {
AT91C_BASE_EMAC->EMAC_SA1L = ( ((unsigned int)pMacAddress[3] << 24)
| ((unsigned int)pMacAddress[2] << 16)
| ((unsigned int)pMacAddress[1] << 8 )
| pMacAddress[0] );
AT91C_BASE_EMAC->EMAC_SA1H = ( ((unsigned int)pMacAddress[5] << 8 )
| pMacAddress[4] );
}
// Now setup the descriptors
// Receive Buffer Queue Pointer Register
AT91C_BASE_EMAC->EMAC_RBQP = (unsigned int) (rxTd.td);
// Transmit Buffer Queue Pointer Register
AT91C_BASE_EMAC->EMAC_TBQP = (unsigned int) (txTd.td);
AT91C_BASE_EMAC->EMAC_NCR = AT91C_EMAC_CLRSTAT;
// Clear all status bits in the receive status register.
AT91C_BASE_EMAC->EMAC_RSR = (AT91C_EMAC_OVR | AT91C_EMAC_REC | AT91C_EMAC_BNA);
// Clear all status bits in the transmit status register
AT91C_BASE_EMAC->EMAC_TSR = ( AT91C_EMAC_UBR | AT91C_EMAC_COL | AT91C_EMAC_RLES
| AT91C_EMAC_BEX | AT91C_EMAC_COMP
| AT91C_EMAC_UND );
// Clear interrupts
AT91C_BASE_EMAC->EMAC_ISR;
// Enable the copy of data into the buffers
// ignore broadcasts, and don't copy FCS.
AT91C_BASE_EMAC->EMAC_NCFGR |= (AT91C_EMAC_DRFCS | AT91C_EMAC_PAE);
if( enableCAF == EMAC_CAF_ENABLE ) {
AT91C_BASE_EMAC->EMAC_NCFGR |= AT91C_EMAC_CAF;
}
if( enableNBC == EMAC_NBC_ENABLE ) {
AT91C_BASE_EMAC->EMAC_NCFGR |= AT91C_EMAC_NBC;
}
// Enable Rx and Tx, plus the stats register.
AT91C_BASE_EMAC->EMAC_NCR |= (AT91C_EMAC_TE | AT91C_EMAC_RE | AT91C_EMAC_WESTAT);
// Setup the interrupts for TX (and errors)
AT91C_BASE_EMAC->EMAC_IER = AT91C_EMAC_RXUBR
| AT91C_EMAC_TUNDR
| AT91C_EMAC_RLEX
| AT91C_EMAC_TXERR
| AT91C_EMAC_TCOMP
| AT91C_EMAC_ROVR
?? 快捷鍵說明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -