📄 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 "AT91RM9200.h"
#include "lib_AT91RM9200.h"
#include "Emac.h"
#include <string.h>
extern unsigned int AT91F_GetTickCount(void);
// Our Ethernet MAC address and IP address
char OurEmacAddr[6] = {0x01, 0x02, 0x03, 0x04, 0x05, 0x06};
unsigned char OurIpAddr[4] = {192, 168, 0, 11}; // {0x0A, 0xD7, 0xF5, 0xAC}
//Buffer descriptor address must be word aligned
#define AT91C_EMAC_TDLIST_BASE 0x20010000
char RxPacket[NB_ETH_RX_PACKETS*ETH_PACKET_SIZE];
AT91PS_TdDescriptor tdList = (AT91PS_TdDescriptor)AT91C_EMAC_TDLIST_BASE;
// ****************************************************************************************************
// ** EMAC lowlevel functions
// ****************************************************************************************************
//*----------------------------------------------------------------------------
//* \fn AT91F_MII_ReadPhy
//* \brief This function return the MII phy register
//*----------------------------------------------------------------------------
unsigned short AT91F_MII_ReadPhy(
AT91PS_EMAC pEmac, // \arg Pointer to AT91PS_EMAC service
unsigned char addr)
{
unsigned int Wait = AT91F_GetTickCount() + 10;
unsigned int value = 0x60020000 | (addr << 18);
pEmac->EMAC_MAN = value;
while(AT91F_GetTickCount() < Wait);
return (pEmac->EMAC_MAN & 0x0000ffff);
}
//*----------------------------------------------------------------------------
//* \fn AT91F_MII_GetLinkSpeed
//* \brief This function configure the link speed
//*----------------------------------------------------------------------------
int MII_GetLinkSpeed(AT91PS_EMAC pEmac) // \arg Pointer to AT91PS_EMAC service
{
unsigned short stat1, stat2;
stat1 = AT91F_MII_ReadPhy(pEmac, MII_STS_REG);
stat1 = AT91F_MII_ReadPhy(pEmac, MII_STS_REG);
stat2 = AT91F_MII_ReadPhy(pEmac, MII_STS2_REG);
//set MII for 100BaseTX and Full Duplex
if ((stat1 & 0x4000) && (stat2 & 0x8000) )
pEmac->EMAC_CFG |= (AT91C_EMAC_SPD| AT91C_EMAC_FD);
//set MII for 10BaseT and Full Duplex
else if ((stat1 & 0x1000) && (stat2 & 0x2000))
pEmac->EMAC_CFG = (pEmac->EMAC_CFG & AT91C_EMAC_SPD) | AT91C_EMAC_FD;
//set MII for 100BaseTX and Half Duplex
else if ((stat1 & 0x2000) && (stat2 & 0x4000))
pEmac->EMAC_CFG = (pEmac->EMAC_CFG | AT91C_EMAC_SPD ) & ~AT91C_EMAC_FD;
//set MII for 10BaseT and Half Duplex
else if ((stat1 & 0x0800) && (stat2 & 0x1000))
pEmac->EMAC_CFG = pEmac->EMAC_CFG & ~AT91C_EMAC_SPD & ~AT91C_EMAC_FD;
return 0;
}
//*----------------------------------------------------------------------------
//* \fn AT91F_MDIO_StartupPhy
//* \brief This function start the phy
//*----------------------------------------------------------------------------
int AT91F_MDIO_StartupPhy(AT91PS_EMAC pEmac) // \arg Pointer to AT91PS_EMAC service
{
int ret;
if(pEmac->EMAC_SR & AT91C_EMAC_LINK)
return 0;
pEmac->EMAC_CTL |= AT91C_EMAC_MPE;
ret = MII_GetLinkSpeed(pEmac);
pEmac->EMAC_CTL &= ~AT91C_EMAC_MPE;
return 0;
}
//*----------------------------------------------------------------------------
//* \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 pTdList)
{
int status;
AT91F_EMAC_CfgPMC();
AT91F_EMAC_CfgPIO();
status = AT91F_MDIO_StartupPhy(pEmac);
if ( status )
return status;
// 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_RBQP = pTdList;
pEmac->EMAC_RSR &= ~(AT91C_EMAC_OVR | AT91C_EMAC_REC | AT91C_EMAC_BNA);
pEmac->EMAC_CFG |= (AT91C_EMAC_CAF | AT91C_EMAC_NBC | AT91C_EMAC_RMII);
pEmac->EMAC_CFG &= ~(AT91C_EMAC_CLK);
pEmac->EMAC_CTL |= (AT91C_EMAC_TE | AT91C_EMAC_RE);
return 0;
}
//*----------------------------------------------------------------------------
//* \fn AT91F_EmacEntry
//* \brief Initialise Emac to receive packets
//*----------------------------------------------------------------------------
int AT91F_EmacEntry(void)
{
unsigned int i;
char *pRxPacket;
pRxPacket = (char *)RxPacket;
// Initialise tdList descriptor. This descriptor must be WORD aligned
for (i = 0; i < NB_ETH_RX_PACKETS; ++i)
{
tdList[i].addr = ((unsigned int) (pRxPacket + (i * ETH_PACKET_SIZE))) & 0xFFFFFFFC;
tdList[i].size = 0;
}
// Set the WRAP bit at the end of the list descriptor
tdList[NB_ETH_RX_PACKETS-1].addr |= 0x02;
return(AT91F_EMACInit(AT91C_BASE_EMAC, (unsigned int) tdList));
}
//*----------------------------------------------------------------------------
//* \fn AT91F_IcmpChksum
//* \brief Process ICMP Checksum...
//*----------------------------------------------------------------------------
unsigned short AT91F_IcmpChksum(unsigned short *p, int len)
{
int i, t;
for (i=0,t=0; i<len; i++, p++)
t += SWAP16(*p);
t = (t & 0xffff) + (t >> 16);
return (~t);
}
//*----------------------------------------------------------------------------
//* \fn AT91F_ProcessEmacPacket
//* \brief Process ARP and ICMP packets...
//*----------------------------------------------------------------------------
int AT91F_ProcessEmacPacket(AT91PS_IPheader pHeader)
{
unsigned short *pFrameType, *pArpOp;
unsigned int i, icmp_len;
char *pData;
int status = AT91C_NO_IPPACKET;
AT91PS_IPheader pIpHeader;
AT91PS_IcmpEchoHdr pIcmpEcho;
int process = 0;
// Receive one packet
process = 0;
status = 0;
for (i = 0; i < NB_ETH_RX_PACKETS; ++i) {
if(tdList[i].addr & 0x1) {
if (*AT91C_EMAC_RSR & AT91C_EMAC_REC)
(*AT91C_EMAC_RSR) |= AT91C_EMAC_REC;
process = 1;
break;
}
}
if (!process)
return AT91C_NO_IPPACKET;
process = i;
// Process this packet
pFrameType = (unsigned short *) ((tdList[i].addr & 0xFFFFFFFC) + 12);
pData = (char *)(tdList[i].addr & 0xFFFFFFFC);
switch (SWAP16(*pFrameType)) {
case PROT_ARP: // ARP Packet format
pArpOp = (unsigned short *) (pData + 20);
if (SWAP16(*pArpOp) == ARP_REQUEST) {
// ARP REPLY operation
*pArpOp = SWAP16(ARP_REPLY);
// Fill the dest address and src address
for (i = 0; i <6; i++) {
// swap ethernet dest address and ethernet src address
pData[i] = pData[i+6];
pData[i+6] = OurEmacAddr[i];
// swap sender ethernet address and target ethernet address
pData[i+22] = OurEmacAddr[i];
pData[i+32] = pData[i+6];
}
// swap sender IP address and target IP address
for (i = 0; i<4; i++) {
pData[i+38] = pData[i+28];
pData[i+28] = OurIpAddr[i];
}
if (!(*AT91C_EMAC_TSR & AT91C_EMAC_BNQ))
return AT91C_NO_IPPACKET;
*AT91C_EMAC_TSR |= AT91C_EMAC_COMP;
*AT91C_EMAC_TAR = (unsigned int)pData;
*AT91C_EMAC_TCR = 0x40;
}
break; // case PROT_ARP
case PROT_IP: // IP protocol frame
pIpHeader = (AT91PS_IPheader)(pData + 14);
pIcmpEcho = (AT91PS_IcmpEchoHdr)((char *)pIpHeader + 20);
memcpy(pHeader, pIpHeader,sizeof(AT91S_IPheader));
#if AT91C_DISPLAY_ALL_IPHEADER
status = AT91C_IPPACKET;
#endif
switch(pIpHeader->ip_p) {
case PROT_ICMP:
// set the status variable to display in main.c only ICMP packets
status = AT91C_IPPACKET;
// if ICMP_ECHO_REQUEST ==> resp = ICMP_ECHO_REPLY
if(pIcmpEcho->type == ICMP_ECHO_REQUEST) {
pIcmpEcho->type = ICMP_ECHO_REPLY;
pIcmpEcho->code = 0;
pIcmpEcho->cksum = 0;
// Checksum of the ICMP Message
icmp_len = (SWAP16(pIpHeader->ip_len) - 20)/(sizeof(unsigned short));
pIcmpEcho->cksum = SWAP16(AT91F_IcmpChksum((unsigned short *) pIcmpEcho, icmp_len));
// Swap IP Dest address and IP Source address
for(i = 0; i <4; i++) {
pIpHeader->ip_dst[i] = pIpHeader->ip_src[i];
pIpHeader->ip_src[i] = OurIpAddr[i];
}
// Swap Eth Dest address and Eth Source address
for(i = 0; i <6; i++) {
pData[i] = pData[i + 6];
pData[i+6] = OurEmacAddr[i];
}
// send the echo_reply
*AT91C_EMAC_TSR |= AT91C_EMAC_COMP;
*AT91C_EMAC_TAR = (unsigned int)pData;
*AT91C_EMAC_TCR = SWAP16(pIpHeader->ip_len)+ 14;
}
break; // case PROT_ICMP
default:
break;
}
break; // case PROT_IP
default:
break;
}// switch (SWAP16(*pFrameType))
// process the packet
tdList[process].addr &= ~0x01;
return status;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -