📄 at91emac.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 "AT91Emac.h"
#include <string.h>
#include "end.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, 254}; /* {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+sizeof(unsigned long)];
AT91PS_TdDescriptor tdList = (AT91PS_TdDescriptor)AT91C_EMAC_TDLIST_BASE;
/*---------------------------------------------------------------------------- */
/* \fn AT91F_PMC_EnablePeriphClock */
/* \brief Enable peripheral clock */
/*---------------------------------------------------------------------------- */
__inline void AT91F_PMC_EnablePeriphClock (
AT91PS_PMC pPMC, /* \arg pointer to PMC controller*/
unsigned int periphIds) /* \arg IDs of peripherals to enable*/
{
pPMC->PMC_PCER = periphIds;
}
/*---------------------------------------------------------------------------- */
/* \fn AT91F_EMAC_CfgPMC */
/* \brief Enable Peripheral clock in PMC for EMAC */
/*---------------------------------------------------------------------------- */
__inline void AT91F_EMAC_CfgPMC (void)
{
AT91F_PMC_EnablePeriphClock(
AT91C_BASE_PMC, /* PIO controller base address*/
((unsigned int) 1 << AT91C_ID_EMAC));
}
/*---------------------------------------------------------------------------- */
/* \fn AT91F_PIO_CfgPeriph */
/* \brief Enable pins to be drived by peripheral */
/*---------------------------------------------------------------------------- */
__inline void AT91F_PIO_CfgPeriph(
/* AT91PS_PIO pPio, */ /* \arg pointer to a PIO controller*/
UINT32 pPio, /* \arg pointer to a PIO controller*/
unsigned int periphAEnable, /* \arg PERIPH A to enable*/
unsigned int periphBEnable) /* \arg PERIPH B to enable*/
{
/*
pPio->PIO_ASR = periphAEnable;
pPio->PIO_BSR = periphBEnable;
pPio->PIO_PDR = (periphAEnable | periphBEnable); *//* Set in Periph mode*/
(*(volatile UINT32 *)((UINT32)pPio+ (PIO_ASR))) = periphAEnable;
(*(volatile UINT32 *)((UINT32)pPio+ (PIO_BSR))) = periphBEnable;
(*(volatile UINT32 *)((UINT32)pPio+ (PIO_PDR))) = (periphAEnable | periphBEnable);/* Set in Periph mode*/
}
/*---------------------------------------------------------------------------- */
/* \fn AT91F_EMAC_CfgPIO */
/* \brief Configure PIO controllers to drive EMAC signals */
/*---------------------------------------------------------------------------- */
__inline void AT91F_EMAC_CfgPIO (void)
{
/* Configure PIO controllers to periph mode*/
AT91F_PIO_CfgPeriph(
AT91C_BASE_PIOA, /* PIO controller base address*/
((unsigned int) AT91C_PA14_ERXER ) |
((unsigned int) AT91C_PA12_ERX0 ) |
((unsigned int) AT91C_PA13_ERX1 ) |
((unsigned int) AT91C_PA8_ETXEN ) |
((unsigned int) AT91C_PA16_EMDIO ) |
((unsigned int) AT91C_PA9_ETX0 ) |
((unsigned int) AT91C_PA10_ETX1 ) |
((unsigned int) AT91C_PA11_ECRS_ECRSDV) |
((unsigned int) AT91C_PA15_EMDC ) |
((unsigned int) AT91C_PA7_ETXCK_EREFCK), /* Peripheral A*/
0); /* Peripheral B*/
}
/********************************************************************************/
/** 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+sizeof(unsigned long))&(~(sizeof(unsigned long)-1));
/* 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);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -