项目中使用的UCOS/II实时操作系统,在确保硬件电路正常后需要先完成的工作是驱动PHY-DP83848网口芯片,通过查资料确定芯片物理地址的定义
在驱动程序中初始化完芯片的参数后,可以读取芯片的参数确定芯片是否正常启动,
程序中需先确定 PHY芯片的地址值是否与硬件上设计的一致,
id1 = read_PHY (PHY_REG_IDR1);
id2 = read_PHY (PHY_REG_IDR2);
函数的末尾处读取的芯片的参数,各寄存器如下,
PHY_REG_BMCR,PHY_REG_BMSR, PHY_REG_ANAR,PHY_REG_ANLPAR,PHY_REG_ANER,PHY_REG_ANNPTR,PHY_REG_STS ,PHY_REG_RBR
这些寄存器的值与注释一样则说明DP83848驱动成功。这些寄存器的默认值可通过查手册确定。
以下为驱动程序主要代码,
long Init_EMAC(void)
{
long xReturn = pdPASS;
// Keil: function modified to access the EMAC
// Initializes the EMAC ethernet controller
volatile unsigned int regv,tout,id1,id2;
/* Enable P1 Ethernet Pins. */
/* Enable P1 Ethernet Pins. */
PINSEL2 &= ~0xF03F330F;
PINSEL2 = configPINSEL2_VALUE;
PINSEL3 = (PINSEL3 & ~0x0000000F) | 0x00000005;
/* Power Up the EMAC controller. */
PCONP |= 0x40000000;
//vTaskDelay( 1 );
//OSTimeDly(1);
/* Reset all EMAC internal modules. */
MAC_MAC1 = MAC1_RES_TX | MAC1_RES_MCS_TX | MAC1_RES_RX | MAC1_RES_MCS_RX | MAC1_SIM_RES | MAC1_SOFT_RES;
MAC_COMMAND = CR_REG_RES | CR_TX_RES | CR_RX_RES;
/* A short delay after reset. */
//vTaskDelay( 1 );
//for (tout = 100; tout; tout--);
OSTimeDly(1);
/* Initialize MAC control registers. */
MAC_MAC1 = MAC1_PASS_ALL;
MAC_MAC2 = MAC2_CRC_EN | MAC2_PAD_EN;
MAC_MAXF = ETH_MAX_FLEN;
MAC_CLRT = CLRT_DEF;
MAC_IPGR = IPGR_DEF;
/*PCLK=18MHz, clock select=6, MDC=18/6=3MHz */
/* Enable RMII interface. */
// MAC_COMMAND = CR_RMII | CR_PASS_RUNT_FRM;
MAC_COMMAND = CR_RMII | CR_PASS_RUNT_FRM | CR_PASS_RX_FILT;
/* Reset Reduced MII Logic. */
MAC_SUPP = SUPP_RES_RMII;
OSTimeDly(1);
MAC_SUPP = 0;
/* Put the DP83848C in reset mode */
write_PHY (PHY_REG_BMCR, 0x8000);
write_PHY (PHY_REG_BMCR, 0x8000);
/* Wait for hardware reset to end. */
for (tout = 0; tout < 1000; tout++) {
//vTaskDelay( 10 );
OSTimeDly(10);
regv = read_PHY (PHY_REG_BMCR);
if (!(regv & 0x8000)) {
/* Reset complete */
break;
}
}
/* Check if this is a DP83848C PHY. */
id1 = read_PHY (PHY_REG_IDR1);
id2 = read_PHY (PHY_REG_IDR2);
if (((id1 << 16) | (id2 & 0xFFF0)) == DP83848C_ID) {
/* Configure the PHY device */
/* Use autonegotiation about the link speed. */
write_PHY (PHY_REG_BMCR, PHY_AUTO_NEG);
/* Wait to complete Auto_Negotiation. */
for (tout = 0; tout < 10; tout++) {
//vTaskDelay( 100 );
OSTimeDly(50);
regv = read_PHY (PHY_REG_BMSR);
if (regv & 0x0020) {
/* Autonegotiation Complete. */
break;
}
}
}
else
{
xReturn = pdFAIL;
}
/* Check the link status. */
if( xReturn == pdPASS )
{
xReturn = pdFAIL;
for (tout = 0; tout < 10; tout++) {
//vTaskDelay( 100 );
OSTimeDly(50);
regv = read_PHY (PHY_REG_STS);
if (regv & 0x0001) {
/* Link is on. */
xReturn = pdPASS;
break;
}
}
}
if( xReturn == pdPASS )
{
/* Configure Full/Half Duplex mode. */
if (regv & 0x0004) {
/* Full duplex is enabled. */
MAC_MAC2 |= 0x31;
//MAC_COMMAND |= CR_FULL_DUP;
MAC_COMMAND |= 0x640;//RMII½Ó¿Ú ȫ˫¹¤
MAC_IPGT = IPGT_FULL_DUP;
}
else {
/* Half duplex mode. */
MAC_IPGT = IPGT_HALF_DUP;
}
/* Configure 100MBit/10MBit mode. */
if (regv & 0x0002) {
/* 10MBit mode. */
MAC_SUPP = 0;
}
else {
/* 100MBit mode. */
MAC_SUPP = SUPP_SPEED;
}
/* Set the Ethernet MAC Address registers */
MAC_SA0 = (emacETHADDR0 << 8) | emacETHADDR1;
MAC_SA1 = (emacETHADDR2 << 8) | emacETHADDR3;
MAC_SA2 = (emacETHADDR4 << 8) | emacETHADDR5;
/* Initialize Tx and Rx DMA Descriptors */
EMACTxDescriptorInit();
EMACRxDescriptorInit();
MAC_MAC1 |= 0x0002;/* [1]-Pass All Rx Frame */
/* Receive Broadcast and Perfect Match Packets */
//MAC_RXFILTERCTRL = RFC_UCAST_EN | RFC_BCAST_EN | RFC_PERFECT_EN;
MAC_RXFILTERCTRL = RFC_BCAST_EN | RFC_PERFECT_EN;
/* Set up RX filter, accept broadcast and perfect station */
// MAC_RXFILTERCTRL = 0x0022;/* [1]-accept broadcast, [5]accept perfect */
MAC_RXFILTERCTRL |= 0x0005;//MULTICAST_UNICAST
MAC_RXFILTERCTRL |= 0x0018;//ENABLE_HASH
/* Create the semaphore used ot wake the uIP task. */
// vSemaphoreCreateBinary( xEMACSemaphore );
/* Reset all interrupts */
MAC_INTCLEAR = 0xFFFF;
/* Enable receive and transmit mode of MAC Ethernet core */
MAC_COMMAND |= (CR_RX_EN | CR_TX_EN);
MAC_MAC1 |= MAC1_REC_EN;
}
/******************************************************/
EINTSTA = 0;
MAC_INTENABLE = 0x000C;/** Enable all interrupts except SOFTINT and WOL */
regv = read_PHY(PHY_REG_BMSR);
if( (regv & 0x0004) ==0 ) //判断驱动是否成功
INITSTATUS = 0;
else
INITSTATUS = 1;
/*
id1 = read_PHY(PHY_REG_BMCR);//0x3000
id1 = read_PHY(PHY_REG_BMSR);//0x786D
id1 = read_PHY(PHY_REG_ANAR);//0x1E1
id1 = read_PHY(PHY_REG_ANLPAR);//0xCDE1
id1 = read_PHY(PHY_REG_ANER);//0x0F
id1 = read_PHY(PHY_REG_ANNPTR );//0x2801
id1 = read_PHY(PHY_REG_STS ); //0x0615
id1 = read_PHY(PHY_REG_RBR ); //0x21
id1 = read_PHY(PHY_REG_PHYCR ); //0x8021
*/
return xReturn;
}
// Keil: function added to write PHY
void write_PHY (int PhyReg, int Value)
{
unsigned int tout;
MAC_MADR = DP83848C_DEF_ADR | PhyReg;
MAC_MWTD = Value;
/* Wait utill operation completed */
tout = 0;
for (tout = 0; tout < MII_WR_TOUT; tout++) {
if ((MAC_MIND & MIND_BUSY) == 0) {
break;
}
}
}
// Keil: function added to read PHY
unsigned short read_PHY (unsigned char PhyReg)
{
unsigned int tout;
MAC_MADR = DP83848C_DEF_ADR | PhyReg;
MAC_MCMD = MCMD_READ;
/* Wait until operation completed */
tout = 0;
for (tout = 0; tout < MII_RD_TOUT; tout++) {
if ((MAC_MIND & MIND_BUSY) == 0) {
break;
}
}
MAC_MCMD = 0;
return (MAC_MRDD);
}
void EMACRxDescriptorInit( void )
{
uint32 i;
uint32 *rx_desc_addr, *rx_status_addr;
/*-----------------------------------------------------------------------------
* setup the Rx status,descriptor registers --
* Note, the actual rx packet data is loaded into the ahb2_sram16k memory as part
* of the simulation
*----------------------------------------------------------------------------*/
MAC_RXDESCRIPTOR = RX_DESCRIPTOR_ADDR; /* Base addr of rx descriptor array */
MAC_RXSTATUS = RX_STATUS_ADDR; /* Base addr of rx status */
MAC_RXDESCRIPTORNUM = EMAC_RX_DESCRIPTOR_COUNT - 1;/* number of rx descriptors, 16 */
for ( i = 0; i < EMAC_RX_DESCRIPTOR_COUNT; i++ )
{
/* two words at a time, packet and control */
rx_desc_addr = (uint32 *)(RX_DESCRIPTOR_ADDR + i * 8);
*rx_desc_addr = (uint32)(EMAC_RX_BUFFER_ADDR + i * EMAC_BLOCK_SIZE);
*(rx_desc_addr+1) = (uint32)(EMAC_RX_DESC_INT | (EMAC_BLOCK_SIZE - 1));/* set size only */
}
for ( i = 0; i < EMAC_RX_DESCRIPTOR_COUNT; i++ )
{
/* RX status, two words, status info. and status hash CRC. */
rx_status_addr = (uint32 *)(RX_STATUS_ADDR + i * 8);
*rx_status_addr = (uint32)0;/* initially, set both status info and hash CRC to 0 */
*(rx_status_addr+1) = (uint32)0;
}
MAC_RXCONSUMEINDEX = 0x0; /* RX descriptor points to zero */
return;
}
void EMACTxDescriptorInit( void )
{
uint32 i;
uint32 *tx_desc_addr, *tx_status_addr;
/*-----------------------------------------------------------------------------
* setup the Tx status,descriptor registers --
* Note, the actual tx packet data is loaded into the ahb2_sram16k memory as part
* of the simulation
*----------------------------------------------------------------------------*/
MAC_TXDESCRIPTOR = TX_DESCRIPTOR_ADDR; /* Base addr of tx descriptor array */
MAC_TXSTATUS = TX_STATUS_ADDR; /* Base addr of tx status */
MAC_TXDESCRIPTORNUM = EMAC_TX_DESCRIPTOR_COUNT - 1;/* number of tx descriptors, 16 */
for ( i = 0; i < EMAC_TX_DESCRIPTOR_COUNT; i++ )
{
tx_desc_addr = (uint32 *)(TX_DESCRIPTOR_ADDR + i * 8);/* two words at a time, packet and control */
*tx_desc_addr = (uint32)(EMAC_TX_BUFFER_ADDR + i * EMAC_BLOCK_SIZE);
*(tx_desc_addr+1) = (uint32)(EMAC_TX_DESC_INT | (EMAC_BLOCK_SIZE - 1));/* set size only */
}
for ( i = 0; i < EMAC_TX_DESCRIPTOR_COUNT; i++ )
{
tx_status_addr = (uint32 *)(TX_STATUS_ADDR + i * 4);/* TX status, one word only, status info. */
*tx_status_addr = (uint32)0;/* initially, set status info to 0 */
}
MAC_TXPRODUCEINDEX = 0x0; /* TX descriptors point to zero */
return;
}
版权声明:未经许可,请勿转载。Copyright © Valiant 2008-2015 all rights reserved.