📄 emac.c
字号:
//*----------------------------------------------------------------------------
//* ATMEL Microcontroller Software Support - ROUSSET -
//*----------------------------------------------------------------------------
//* The software is delivered "AS IS" without warranty or condition of any
//* kind, either express, implied or statutory. This includes without
//* limitation any warranty or condition with respect to merchantability or
//* fitness for any particular purpose, or against the infringements of
//* intellectual property rights of others.
//*----------------------------------------------------------------------------
//* File Name : main.c
//* Object : main application written in C
//* Creation : Hi 11/18/2002
//*
//*----------------------------------------------------------------------------
#include "FreeRTOS.h"
#include "Emac.h"
#include "mii.h"
#include <string.h>
extern unsigned int AT91F_GetTickCount(void);
extern void AT91F_DBGU_Printk(char *buffer);
//extern char MsgBuffer[256];
static int xcalls = 0;
// Our Ethernet MAC address and IP address
char OurEmacAddr[6] = {0x01, 0x02, 0x03, 0x04, 0x05, 0x06};
unsigned char OurIpAddr[4] = {172, 25, 218, 210};
//Buffer descriptor address must be word aligned
//#define AT91C_EMAC_RX_TDLIST_BASE 0x30c000 // take care that RxtdList[NB_RCV_BUFFERS] area is available
///#define AT91C_EMAC_RX_TDLIST_BASE 0x00204000 // take care that RxtdList[NB_RCV_BUFFERS] area is available
//#define AT91C_EMAC_TX_TDLIST_BASE (AT91C_EMAC_RX_TDLIST_BASE + NB_RX_BUFFERS * sizeof(AT91S_RxTdDescriptor))
//#define AT91C_EMAC_TX_TDLIST_BASE 0x00204640 //(AT91C_EMAC_RX_TDLIST_BASE + NB_RX_BUFFERS * sizeof(AT91S_RxTdDescriptor))
unsigned int TxBuffIndex = 0;
unsigned int Dummy = 0x12345678;
//char *RxPacket = (char *)0x308000;
//char *TxPacket = (char *)(0x308000 + (NB_RX_BUFFERS*ETH_RX_BUFFER_SIZE));
//char *RxPacket = (char *)0x00206000;
#pragma data_alignment=8
char RxPacket[ NB_RX_BUFFERS * ETH_RX_BUFFER_SIZE ];
//char *TxPacket = (char *)0x0020A000;
#pragma data_alignment=8
char TxPacket[ NB_TX_BUFFERS * ETH_TX_BUFFER_SIZE ];
//AT91PS_RxTdDescriptor RxtdList = (AT91PS_RxTdDescriptor)AT91C_EMAC_RX_TDLIST_BASE;
//AT91PS_RxTdDescriptor RxtdList;// = (AT91PS_RxTdDescriptor)AT91C_EMAC_RX_TDLIST_BASE;
//AT91PS_RxTdDescriptor RxtdList = (AT91PS_RxTdDescriptor) AT91C_EMAC_RX_TDLIST_BASE;
AT91S_RxTdDescriptor RxtdList[ NB_RX_BUFFERS ];
//AT91PS_TxTdDescriptor TxtdList = (AT91PS_TxTdDescriptor)AT91C_EMAC_TX_TDLIST_BASE;
AT91S_TxTdDescriptor TxtdList[ NB_TX_BUFFERS ];
AT91S_RxTdDescriptor RxtdList[ NB_RX_BUFFERS ];
// ****************************************************************************************************
// ** EMAC lowlevel functions
// ****************************************************************************************************
/* Enable the MDIO bit in MAC control register */
void AT91F_Enable_Mdi(AT91PS_EMAC pEmac)
{
pEmac->EMAC_NCR |= AT91C_EMAC_MPE; /* enable management port */
}
/*
* Disable the MDIO bit in the MAC control register
*/
void AT91F_Disable_Mdi(AT91PS_EMAC pEmac)
{
pEmac->EMAC_NCR &= ~AT91C_EMAC_MPE; /* disable management port */
}
/*
* Write value to the a PHY register
* Note: MDI interface is assumed to already have been enabled.
*/
void write_phy(AT91PS_EMAC pEmac, unsigned char phy_addr, unsigned char address, unsigned int value)
{
pEmac->EMAC_MAN = ((AT91C_EMAC_SOF & (0x01<<30)) | (2 << 16) | (1 << 28)
| ((phy_addr & 0x1f) << 23) | (address << 18)) + (value & 0xffff);
/* Wait until IDLE bit in Network Status register is cleared */
while (!(pEmac->EMAC_NSR & AT91C_EMAC_IDLE));
}
/*
* Read value stored in a PHY register.
* Note: MDI interface is assumed to already have been enabled.
*/
void read_phy(AT91PS_EMAC pEmac, unsigned char phy_addr, unsigned char address, unsigned int *value)
{
pEmac->EMAC_MAN = (AT91C_EMAC_SOF & (0x01<<30)) | (2 << 16) | (2 << 28)
| ((phy_addr & 0x1f) << 23) | (address << 18);
/* Wait until IDLE bit in Network Status register is cleared */
while (!(pEmac->EMAC_NSR & AT91C_EMAC_IDLE));
*value = (pEmac->EMAC_MAN & 0x0000ffff);
}
//*----------------------------------------------------------------------------
//* \fn AT91F_GetLinkSpeed
//* \brief This function configure the link speed
//*----------------------------------------------------------------------------
int AT91F_GetLinkSpeed( AT91PS_EMAC pEmac) // \arg Pointer to AT91PS_EMAC service
{
unsigned int bmsr, bmcr, lpa, mac_cfg;
unsigned int speed, duplex;
/* Link status is latched, so read twice to get current value */
read_phy(pEmac, AT91C_PHY_ADDR, MII_BMSR, &bmsr);
read_phy(pEmac, AT91C_PHY_ADDR, MII_BMSR, &bmsr);
if (!(bmsr & BMSR_LSTATUS))
return -1; /* no link */
read_phy(pEmac, AT91C_PHY_ADDR, MII_BMCR, &bmcr);
if (bmcr & BMCR_ANENABLE) { /* AutoNegotiation is enabled */
if (!(bmsr & BMSR_ANEGCOMPLETE))
return -2; /* auto-negotitation in progress */
read_phy(pEmac, AT91C_PHY_ADDR, MII_LPA, &lpa);
if ((lpa & LPA_100FULL) || (lpa & LPA_100HALF))
speed = SPEED_100;
else
speed = SPEED_10;
if ((lpa & LPA_100FULL) || (lpa & LPA_10FULL))
duplex = DUPLEX_FULL;
else duplex = DUPLEX_HALF;
} else {
speed = (bmcr & BMCR_SPEED100) ? SPEED_100 : SPEED_10;
duplex = (bmcr & BMCR_FULLDPLX) ? DUPLEX_FULL : DUPLEX_HALF;
}
/* Update the MAC */
mac_cfg = pEmac->EMAC_NCFGR & ~(AT91C_EMAC_SPD | AT91C_EMAC_FD);
if (speed == SPEED_100) {
if (duplex == DUPLEX_FULL) /* 100 Full Duplex */
pEmac->EMAC_NCFGR = mac_cfg | AT91C_EMAC_SPD | AT91C_EMAC_FD;
else /* 100 Half Duplex */
pEmac->EMAC_NCFGR = mac_cfg | AT91C_EMAC_SPD;
} else {
if (duplex == DUPLEX_FULL) /* 10 Full Duplex */
pEmac->EMAC_NCFGR = mac_cfg | AT91C_EMAC_FD;
else /* 10 Half Duplex */
pEmac->EMAC_NCFGR = mac_cfg;
}
#if 0
if (duplex == DUPLEX_FULL)
sprintf(MsgBuffer, "\n\r EMAC Init : %d Mbit/s FULL DUPLEX", speed);
else
sprintf(MsgBuffer, "\n\r EMAC Init : %d Mbit/s HALF DUPLEX", speed);
AT91F_DBGU_Printk(MsgBuffer);
#endif
return 0;
}
/*
* Detect MAC and PHY and perform initialization
*/
int AT91F_Ether_Probe(
AT91PS_EMAC pEmac) // \arg Pointer to AT91PS_EMAC service
{
unsigned int phyid1, phyid2;
unsigned int status;
/* Read the PHY ID registers */
AT91F_Enable_Mdi(pEmac);
read_phy(pEmac, AT91C_PHY_ADDR, MII_PHYSID1, &phyid1);
read_phy(pEmac, AT91C_PHY_ADDR, MII_PHYSID2, &phyid2);
/* AMD AM79C875: PHY_ID1 = 0x0022 PHY_ID2 = 0x5541
Bits 3:0 Revision Number Four bit manufacturer抯 revision number. 0001 stands for Rev. A, etc.
These bits are masked.
*/
if (((phyid1 << 16) | (phyid2 & 0xfff0)) != MII_DM9161_ID) {
AT91F_Disable_Mdi(pEmac);
return -1;
}
status = AT91F_GetLinkSpeed(pEmac);
AT91F_Disable_Mdi(pEmac);
return status;
}
//*----------------------------------------------------------------------------
//* \fn AT91F_EMACInit
//* \brief This function initialise the ethernet
//*----------------------------------------------------------------------------
int AT91F_EMACInit( // \return Status ( Success = 0)
AT91PS_EMAC pEmac, // \arg Pointer to AT91PS_EMAC service
unsigned int pRxTdList,
unsigned int pTxTdList)
{
AT91F_EMAC_CfgPIO();
if (AT91F_Ether_Probe(pEmac))
return -1;
// the sequence write EMAC_SA1L and write EMAC_SA1H must be respected
pEmac->EMAC_SA1L = ((int)OurEmacAddr[2] << 24) | ((int)OurEmacAddr[3] << 16) | ((int)OurEmacAddr[4] << 8) | OurEmacAddr[5];
pEmac->EMAC_SA1H = ((int)OurEmacAddr[0] << 8) | OurEmacAddr[1];
//pEmac->EMAC_SA1L = ((int)31 << 24) | ((int)146 << 16) | ((int)170 << 8) | 85;
//pEmac->EMAC_SA1H = ((int)0 << 8) | 15;
pEmac->EMAC_RBQP = pRxTdList;
pEmac->EMAC_TBQP = pTxTdList;
pEmac->EMAC_RSR &= ~(AT91C_EMAC_OVR | AT91C_EMAC_REC | AT91C_EMAC_BNA);
pEmac->EMAC_NCFGR |= (AT91C_EMAC_CAF | AT91C_EMAC_NBC );// | AT91C_EMAC_RBOF_OFFSET_2);
pEmac->EMAC_NCFGR &= ~(AT91C_EMAC_CLK);
pEmac->EMAC_NCR |= (AT91C_EMAC_TE | AT91C_EMAC_RE | AT91C_EMAC_WESTAT);
return 0;
}
#define AT91C_RCV_OFFSET 0
//*----------------------------------------------------------------------------
//* \fn AT91F_EmacEntry
//* \brief Initialise Emac to receive packets
//*----------------------------------------------------------------------------
int AT91F_EmacEntry(void)
{
unsigned int i;
unsigned int val;
// Initialise RxtdList descriptor
for (i = 0; i < NB_RX_BUFFERS; ++i)
{
val = (unsigned int)(RxPacket + (i * ETH_RX_BUFFER_SIZE));
RxtdList[i].addr = val & 0xFFFFFFF8;
RxtdList[i].U_Status.status = 0;
}
// Set the WRAP bit at the end of the list descriptor
RxtdList[NB_RX_BUFFERS-1].addr |= 0x02;
memset( RxPacket, 0x55, ( NB_RX_BUFFERS * ETH_RX_BUFFER_SIZE ) );
// Initialise TxtdList descriptor
for (i = 0; i < NB_TX_BUFFERS; ++i) {
val = (unsigned int)(TxPacket + (i * ETH_TX_BUFFER_SIZE));
TxtdList[i].addr = val & 0xFFFFFFF8;
TxtdList[i].U_Status.status = 0;
}
// Set the WRAP bit at the end of the list descriptor
TxtdList[NB_TX_BUFFERS-1].U_Status.S_Status.Wrap = 1;
return(AT91F_EMACInit(AT91C_BASE_EMAC, (unsigned int) RxtdList, (unsigned int) TxtdList));
}
//*----------------------------------------------------------------------------
//* \fn AT91F_TransmitPacket
//* \brief Send a packet
//*----------------------------------------------------------------------------
int AT91F_TransmitPacket(char *pData, unsigned int length)
{
AT91PS_EMAC pEmac = (AT91PS_EMAC)AT91C_BASE_EMAC;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -