⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 emac.c

📁 MSP430 IAR project with FreeRTOS port.
💻 C
📖 第 1 页 / 共 2 页
字号:
//*----------------------------------------------------------------------------
//*         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 + -