?? lib_emac.c
字號:
//* 設置EMAC地址
AT91C_BASE_EMAC->EMAC_SA1L = 0xBC | ((ULONG)(0x20 << 8)) | ((ULONG)(0x06 << 16)) | ((ULONG)(0x09 << 24));
AT91C_BASE_EMAC->EMAC_SA1H = 0x30 | ((ULONG)(0x11 << 8));
//* 設置EMAC中斷
OS_ENTER_CRITICAL()
{
//* 發(fā)送和接收結束中斷使能
AT91C_BASE_EMAC->EMAC_IER = AT91C_EMAC_RCOMP | AT91C_EMAC_TCOMP;
at91_irq_open(AT91C_ID_EMAC, AT91C_AIC_PRIOR_HIGHEST, AT91C_AIC_SRCTYPE_INT_HIGH_LEVEL, irqEMACISR);
}
OS_EXIT_CRITICAL()
//* 最后,接收、發(fā)送使能
AT91C_BASE_EMAC->EMAC_NCR |= AT91C_EMAC_TE | AT91C_EMAC_RE;
}
//*------------------------------------------------------------------------------------------------
//* 函數名稱 : __HandlePHY
//* 功能描述 : 對PHY進行讀寫操作
//* 入口參數 : <ubRegAddr>[in] 指定對PHY的哪個寄存器進行讀寫
//* : <puwData>[in][out] 指向操作數據的指針。對于讀,這個地址保存讀取的數據;對于寫則是要寫入
//* : 寄存器的數據
//* : <blIsRead>[in] 是否是讀操作,如果不是則是寫操作
//* 出口參數 : 無
//*------------------------------------------------------------------------------------------------
static void __HandlePHY(UBYTE ubRegAddr, UWORD *puwData, BOOLEAN blIsRead)
{
ULONG __ulHandleVal;
if(blIsRead)
{
__ulHandleVal = (0x01 << 30)
| (0x02 << 28)
| (PHY_ADDR << 23)
| (ubRegAddr << 18)
| (0x02 << 16);
}
else
{
__ulHandleVal = (0x01 << 30)
| (0x01 << 28)
| (PHY_ADDR << 23)
| (ubRegAddr << 18)
| (0x02 << 16)
| (*puwData & 0xFFFF);
}
AT91C_BASE_EMAC->EMAC_MAN = __ulHandleVal;
while(!(AT91C_BASE_EMAC->EMAC_NSR & AT91C_EMAC_IDLE));
if(blIsRead)
*puwData = AT91C_BASE_EMAC->EMAC_MAN & 0x0000FFFF;
}
//*------------------------------------------------------------------------------------------------
//* 函數名稱 : __ResetPHY
//* 功能描述 : 設置PHY芯片為UTP模式并復位PHY芯片
//* 入口參數 : 無
//* 出口參數 : 無
//*------------------------------------------------------------------------------------------------
static void __ResetPHY(void)
{
//* PHY在上電或復位期間需要根據RXER/FXEN引腳(24腳)的鎖存輸入狀態(tài)來選擇是UTP模式還是光纖模式。每個PIO
//* 口線都被內置了一個上拉電阻,所以整機上電后該引腳的邏輯電平為高,這樣就會使得PHY進入了光纖模式。我們
//* 需要UTP模式,也就是PHY上電或復位期間的鎖存輸入狀態(tài)為低,所以在這里必須禁止該口線的內部上拉電阻,然后
//* 再復位PHY芯片,使其進入UTP模式
AT91C_BASE_PIOB->PIO_PPUDR = AT91C_PB7_ERXER;
//* 復位PHY芯片,RTL8201BL的數據手冊要求必須維持至少10ms的低電平,這里設置為2的(8 + 1)次方個SCK周期,
//* 時間為15.621ms
AT91C_BASE_RSTC->RSTC_RMR = 0xA5000000 | (0x08 << 8);
AT91C_BASE_RSTC->RSTC_RCR = 0xA5000000 | AT91C_RSTC_EXTRST;
//* 等待NRST引腳恢復為高電平
while(!(AT91C_BASE_RSTC->RSTC_RSR & AT91C_RSTC_NRSTL));
}
//*------------------------------------------------------------------------------------------------
//* 函數名稱 : __CheckPHYID
//* 功能描述 : 檢查PHY ID是否為0x82010000,如果不是則表明PHY還沒有就緒或者出現故障,函數將一直查詢直至正確
//* 入口參數 : 無
//* 出口參數 : 無
//*------------------------------------------------------------------------------------------------
static void __CheckPHYID(void)
{
ULONG __ulPHYID;
UBYTE __ubDelaySeconds = 0;
EnableMDI()
{
while(TRUE)
{
__HandlePHY(PHY_REG_ID1, (UWORD*)&__ulPHYID, TRUE);
__HandlePHY(PHY_REG_ID2, ((UWORD*)&__ulPHYID)+1, TRUE);
if(__ulPHYID == PHY_ID_RTL8201)
break;
else
{
__ResetPHY();
if(__ubDelaySeconds < 15)
__ubDelaySeconds++;
OSTimeDlyHMSM(0, 0, __ubDelaySeconds, 0);
}
}
}
DisableMDI()
}
//*------------------------------------------------------------------------------------------------
//* 函數名稱 : __ilWaitLinkEstablished
//* 功能描述 : 等待PHY建立鏈路
//* 入口參數 : 無
//* 出口參數 : 無
//*------------------------------------------------------------------------------------------------
__inline void __ilWaitLinkEstablished(void)
{
UWORD __uwHandleData;
UBYTE __ubDelaySeconds = 0;
while(TRUE)
{
__HandlePHY(PHY_REG_BMSR, &__uwHandleData, TRUE);
if(__uwHandleData & PHY_BMSR_LINKESTABLISHED)
break;
else
{
__ResetPHY();
if(__ubDelaySeconds < 15)
__ubDelaySeconds++;
OSTimeDlyHMSM(0, 0, __ubDelaySeconds, 0);
}
}
}
//*------------------------------------------------------------------------------------------------
//* 函數名稱 : __ilWaitAutoNegEnd
//* 功能描述 : 等待PHY自動協商結束
//* 入口參數 : 無
//* 出口參數 : 無
//*------------------------------------------------------------------------------------------------
__inline void __ilWaitAutoNegEnd(void)
{
UWORD __uwHandleData;
UBYTE __ubDelaySeconds = 0;
do{
if(__uwHandleData & PHY_BMSR_AUTONEGEND)
break;
else
{
__HandlePHY(PHY_REG_BMSR, &__uwHandleData, TRUE);
OSTimeDlyHMSM(0, 0, 1, 0);
}
}while(TRUE);
}
//*------------------------------------------------------------------------------------------------
//* 函數名稱 : __SetupLinkSpeedAndDuplex
//* 功能描述 : 從PHY獲取自動協商的結果,設置EMAC自身的鏈路速度和單雙工方式。注意,該函數會阻塞所在任務的正
//* : 常執(zhí)行直至設置成功
//* 入口參數 : 無
//* 出口參數 : 無
//*------------------------------------------------------------------------------------------------
static void __SetupLinkSpeedAndDuplex(void)
{
UWORD __uwHandleData;
ULONG __ulSpdAndFD = 0x00000000;
EnableMDI()
{
__ilWaitLinkEstablished();
__ilWaitAutoNegEnd();
//* 獲得協商的結果
__HandlePHY(PHY_REG_ANLPAR, &__uwHandleData, TRUE);
//* 決定線速
if((__uwHandleData & PHY_ANLPAR_100TX) || (__uwHandleData & PHY_ANLPAR_100TXFD))
__ulSpdAndFD = AT91C_EMAC_SPD;
//* 決定單雙工方式
if((__uwHandleData & PHY_ANLPAR_100TXFD) || (__uwHandleData & PHY_ANLPAR_10TFD))
__ulSpdAndFD |= AT91C_EMAC_FD;
//* 將鏈路速度和單雙工方式設置進EMAC的網絡配置寄存器
AT91C_BASE_EMAC->EMAC_NCFGR = (AT91C_BASE_EMAC->EMAC_NCFGR & EMAC_NCFGR_SPD_FD_MASK) | __ulSpdAndFD;
}
DisableMDI()
}
//*------------------------------------------------------------------------------------------------
//* 函數名稱 : __InitDescriptorsForRxBAndTxB
//* 功能描述 : 初始化接收和發(fā)送緩沖區(qū)描述符,使每個描述符指向正確的緩沖區(qū)地址,然后將描述符首地址寫入隊列指
//* : 針指針寄存器
//* 入口參數 : 無
//* 出口參數 : 無
//*------------------------------------------------------------------------------------------------
static void __InitDescriptorsForRxBAndTxB(void)
{
LONG i;
//* 將接收緩沖區(qū)地址填充到緩沖區(qū)描述符
for(i=0; i<NB_RX_BUFS; i++)
__staRxBDescriptors[i].ulRxBAddrAndFlag = (int)baRxBufs[i];
//* 置位最后一個緩沖區(qū)描述符的Wrap位
__staRxBDescriptors[NB_RX_BUFS - 1].ulRxBAddrAndFlag |= RxDESC_FLAG_WARP;
//* 將發(fā)送緩沖區(qū)地址填充到緩沖區(qū)描述符
for(i=0; i<NB_TX_BUFS; i++)
{
__staTxBDescriptors[i].ulTxBAddr = (int)baTxBufs[i];
//* 標記這個緩沖區(qū)為程序所有,根據數據手冊,該位為0表示這個緩沖區(qū)為EMAC所有
__staTxBDescriptors[i].uStatus.bstStatus.bitIsUsed = 1;
}
//* 置位發(fā)送緩沖區(qū)的結束位(Wrap)
__staTxBDescriptors[NB_TX_BUFS - 1].uStatus.bstStatus.bitIsWrap = 1;
//* 將描述符隊列首地址寫入接收和發(fā)送隊列指針寄存器
AT91C_BASE_EMAC->EMAC_RBQP = (int)__staRxBDescriptors;
AT91C_BASE_EMAC->EMAC_TBQP = (int)__staTxBDescriptors;
}
//*------------------------------------------------------------------------------------------------
//* 函數名稱 : __ilResetTxBDescriptors
//* 功能描述 : 復位發(fā)送緩沖區(qū)描述符的Used位,使其能夠繼續(xù)被使用
//* 入口參數 : 無
//* 出口參數 : 無
//*------------------------------------------------------------------------------------------------
__inline void __ilResetTxBDescriptors(void)
{
static LONG __lIdxToReset = 0;
//* 根據EMAC數據手冊,EMAC在發(fā)送完畢后會置位幀的第一個緩沖區(qū)描述符的Used位,所以在這里只需置位其它描
//* 述符即可
if(__staTxBDescriptors[__lIdxToReset].uStatus.bstStatus.bitIsUsed)
{
while(!__staTxBDescriptors[__lIdxToReset].uStatus.bstStatus.bitIsLastBuf)
{
__lIdxToReset++;
if(__lIdxToReset >= NB_TX_BUFS)
__lIdxToReset = 0;
__staTxBDescriptors[__lIdxToReset].uStatus.bstStatus.bitIsUsed = 1;
}
__lIdxToReset++;
if(__lIdxToReset >= NB_TX_BUFS)
__lIdxToReset = 0;
}
else;
}
//*------------------------------------------------------------------------------------------------
//* 函數名稱 : GetInputPacketLen
//* 功能描述 : 獲取到達的信息包的長度
//* 入口參數 : 無
//* 出口參數 : 無
//*------------------------------------------------------------------------------------------------
UWORD GetInputPacketLen(void)
{
UWORD __uwIdx, __uwLen = 0;
//* 跳過碎片幀,判斷依據是幀頭位未被置位
while((__staRxBDescriptors[__uwCurRxBIdx].ulRxBAddrAndFlag & RxDESC_FLAG_OWNSHIP)
&& !__staRxBDescriptors[__uwCurRxBIdx].uStatus.bstStatus.bitStartOfFrm)
{
//* 釋放這個緩沖區(qū)
__staRxBDescriptors[__uwCurRxBIdx].ulRxBAddrAndFlag &= (~RxDESC_FLAG_OWNSHIP);
__uwCurRxBIdx++;
if(__uwCurRxBIdx >= NB_RX_BUFS )
{
__uwCurRxBIdx = 0;
}
}
__uwIdx = __uwCurRxBIdx;
//* 只有最后一個緩沖區(qū)才保存幀的長度,其它均為0
while((__staRxBDescriptors[__uwIdx].ulRxBAddrAndFlag & RxDESC_FLAG_OWNSHIP))
{
__uwLen = __staRxBDescriptors[__uwIdx].uStatus.bstStatus.bitLen;
if(__uwLen > 0)
break;
__uwIdx++;
if(__uwIdx >= NB_RX_BUFS)
__uwIdx = 0;
}
//* 保存信息包讀取位置
__pbFrom = (BYTE*)(__staRxBDescriptors[__uwCurRxBIdx].ulRxBAddrAndFlag & EMAC_RxB_ADDR_MASK);
return __uwLen;
}
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -