hal_mac.c

来自「最新版IAR FOR ARM(EWARM)5.11中的代码例子」· C语言 代码 · 共 380 行

C
380
字号
//-----------------------------------------------------------------------------
// HAL_MAC
//-----------------------------------------------------------------------------

#include "hal_mac.h"

#include "stdlib.h"
#include "string.h"


//-----------------------------------------------------------------------------
// Ethernet MAC address + static IP address + Ethernet types
//-----------------------------------------------------------------------------

  u8 srcMAC[6] = {0x00,0x08,0x07,0x06,0x05,0x04};
  u8 destMAC[6] = {0x00,0x01,0x02,0x1C,0xAD,0x64};

  u8 srcIP[4] = {192,168,1,15};
  u8 destIP[4] = {192,168,1,16};

  u8 brcastADD[4] = {255,255,255,255};
  u8 etherIP[2]={0x08,0x00};
  u8 etherARP[2]={0x08,0x06};
  u8 httpPORT[2]={0x00,0x50};

//-----------------------------------------------------------------------------
// MAC-DMA
// Declarations of Frame Descriptor tables for RX and TX + declaration of pointers
//-----------------------------------------------------------------------------

static DmaMacDescr  *RX_MAC_DescrTable;       // Ptr to RX Descriptor Table
static u16          RX_MAC_currDescNum = 0;   // RX DescrTable current element

static DmaMacDescr  *TX_MAC_DescrTable;       // Ptr to TX Descriptor Table
static u16          TX_MAC_currDescNum = 0;   // TX DescrTable current element

//-----------------------------------------------------------------------------
//name:MAC_GetPhyLayer()
//funcionality: Communication with Ethernet phy, ready to be used with
//STE100P and STE101P
//-----------------------------------------------------------------------------
void MAC_GetPhyLayer(
                u16 PHYnum,  // PHY num
                u16 PHYreg,  // PHY register num
                u16 *CtrlBit // PHY Operation Mode
                )

{
        *CtrlBit = 0x0;
        while (MAC->MII_ADDR & Mii_Busy);        // wait

        // Program PHY address
        MAC->MII_ADDR    = ((PHYnum * Phy_AddrU) & Phy_AddrMsk) | ((PHYreg * Mii_RegisterU) & Mii_RegisterMsk);

        while (MAC->MII_ADDR & Mii_Busy);        // wait

        *CtrlBit = MAC->MII_DATA;

        while (MAC->MII_ADDR & Mii_Busy);        // wait

}

//-----------------------------------------------------------------------------
//name:MAC_SetPhyLayer()
//funcionality: Communication with Ethernet phy, ready to be used with
//STE100P and STE101P
//-----------------------------------------------------------------------------
void MAC_SetPhyLayer
                (
                u16 PHYnum,  // PHY num
                u16 PHYreg,  // PHY register num
                u16 CtrlBit, // Bit to be set/reset
                u16 Set      // Turn Off (0) or On (1) the mode
                )
{
	volatile unsigned int tmpval = 0;
	
        while (MAC->MII_ADDR & Mii_Busy);        // wait

        // Program PHY address
        MAC->MII_ADDR    = ((PHYnum * Phy_AddrU) & Phy_AddrMsk) | ((PHYreg * Mii_RegisterU) & Mii_RegisterMsk);

        while (MAC->MII_ADDR & Mii_Busy);        // wait
        tmpval = MAC->MII_DATA;
        while (MAC->MII_ADDR & Mii_Busy);        // wait
	
        // Set/Clear Control Bit.
        if (Set)
                MAC->MII_DATA    = tmpval | CtrlBit;
        else
                MAC->MII_DATA    = tmpval & ~CtrlBit;

        //Program PHY address + write bit set
        MAC->MII_ADDR    = ((PHYnum * Phy_AddrU) & Phy_AddrMsk) | ((PHYreg * Mii_RegisterU) & Mii_RegisterMsk) | Mii_Write;

        while (MAC->MII_ADDR & Mii_Busy);        // wait

        // DUMMY READ; phy bug? = additional code
        MAC->MII_ADDR    = ((PHYnum * Phy_AddrU) & Phy_AddrMsk) | ((PHYreg * Mii_RegisterU) & Mii_RegisterMsk);

        while (MAC->MII_ADDR & Mii_Busy);        // wait
	tmpval = MAC->MII_DATA;
        while (MAC->MII_ADDR & Mii_Busy);        // wait

}


//-----------------------------------------------------------------------------
// name: MAC_Init()
// functionality: Initialization of the Ethernet phy + allocation of DMA descritpor chain
// (Frame Descriptor Tables)
//-----------------------------------------------------------------------------
int MAC_Init()
{
        int i;
        u16 LanStatus;

	/*****************************************
	 * INIT DMA MAC controller
	 *****************************************/
	// Turn the reset off
	DMA_MAC->DMA_STS_CNTL  &= ~DmaMac_SRst;
	
	// Program the DMA Burst Length for TX/RX
	DMA_MAC->DMA_STS_CNTL    |= DmaMac_RXBurst_08 | DmaMac_TXBurst_04;

	// Program the DMA_MAC interrupts
        DMA_MAC->DMA_INT_EN =  DmaMac_RxCurrDone | DmaMac_TxCurrDone;

        //Clear all the interrupt pending bits
        DMA_MAC->DMA_INT_STS = 0xFFFFFFFF;

	/*****************************************
	 * INIT MAC110 controller
	 *****************************************/
	// Program the local MAC Address, should be loaded from EEPROM
	MAC->MAC_ADDL     =  srcMAC[0] +
			  (srcMAC[1] <<  8)+
			  (srcMAC[2] << 16)+
			  (srcMAC[3] << 24);
	
	MAC->MAC_ADDH    =  srcMAC[4] +
			  (srcMAC[5] << 8);
	
	MAC->MAC_CNTL   =  Mac_RxEn |
			   Mac_TxEn |
			   Mac_DfrChk |
			   Mac_NoHeartBeat |
			   Mac_AutoPadStrip |   //strips the PAD frame data
			   Mac_BckOff_04;

	MAC->MMC_CTRL_REG    =  Mmc_Reset |
			   Mmc_RollOver |
			   ((MAC_MAX_FRAME_SZ * Mmc_MaxFrmSzU) & Mmc_MaxFrmSzMsk);
	
	MAC -> MMC_INT_MSK_LO_REG = 0xffffffff;    // ALL Disabled!!!
	MAC -> MMC_INT_MSK_HI_REG = 0xffffffff;    // ALL Disabled!!!


	/*****************************************
	 * INIT the PHY by using MII
	 *****************************************/
	MAC_SetPhyLayer(PHY_NUM, Phy_CtrlReg, Phy_Reset, 1);
	MAC_GetPhyLayer(PHY_NUM, Phy_CtrlReg, &LanStatus);
	MAC_GetPhyLayer(PHY_NUM, Phy_QPDSReg, &LanStatus);

	
	/******************************************
	 * Build the Frame Descriptor table for RX.
	 ******************************************/
	RX_MAC_currDescNum = 0;
        RX_MAC_DescrTable = (DmaMacDescr *)calloc((RX_MAC_DESCR_NUM+1), sizeof(DmaMacDescr));

	if ( RX_MAC_DescrTable == NULL)
	{
		return 0;
	}
	
	/* Init the RX buffer descriptor table for this device, chain construction */
	for (i = 0; i < RX_MAC_DESCR_NUM; i++)
	{
		if (i < RX_MAC_DESCR_NUM - 1)
			RX_MAC_DescrTable[i].DmaMac_Next = ((int) &RX_MAC_DescrTable[i+1] & DmaMac_DescrAddrMsk) | DmaMac_NpolEn;
		else
			RX_MAC_DescrTable[i].DmaMac_Next = ((int) &RX_MAC_DescrTable[0] & DmaMac_DescrAddrMsk) | DmaMac_NpolEn;

	
		RX_MAC_DescrTable[i].TxRx_Status = DmaMac_Valid;
		RX_MAC_DescrTable[i].DmaMac_Addr = (int)(RX_MAC_DescrTable[i].FrameBuf);	
		RX_MAC_DescrTable[i].DmaMac_Cntl = DmaMac_NxtEn |
	            				    (MAC_MAX_FRAME_SZ & DmaMac_XferCntMsk) |
	                                            ((3 * DmaMac_EntryTrigU) & DmaMac_EntryTrigMsk);
	}

	/* Start the DMA for receiving. DMA must use word-aligned not-aliased descriptor pointer */
	DMA_MAC->RX_DMA_NXT   = ((int) RX_MAC_DescrTable & DmaMac_DescrAddrMsk) | DmaMac_NpolEn;
	DMA_MAC->RX_DMA_START =	DmaMac_StartFetch |
				((1000 * DmaMac_DFetchDlyU) & DmaMac_DFetchDlyMsk);

	
	/******************************************
	 * Build the Frame Descriptor table for TX.
	 ******************************************/
	TX_MAC_currDescNum = 0;
        TX_MAC_DescrTable = (DmaMacDescr *)calloc((TX_MAC_DESCR_NUM+1), sizeof(DmaMacDescr));

	/* Alloc the TX buffer descriptor table for this device. (TBD: '+ 1' ??) */
	if (TX_MAC_DescrTable == NULL)
	{
		return 0;
	}
	
	/* Init the TX buffer descriptor table for this device, chain construction */
	for (i = 0; i < TX_MAC_DESCR_NUM; i++)
	{
		if (i < TX_MAC_DESCR_NUM - 1)
			TX_MAC_DescrTable[i].DmaMac_Next = ((int) &TX_MAC_DescrTable[i+1] & DmaMac_DescrAddrMsk) | DmaMac_NpolEn;
		else
			TX_MAC_DescrTable[i].DmaMac_Next = ((int) &TX_MAC_DescrTable[0] & DmaMac_DescrAddrMsk) | DmaMac_NpolEn;

	
		TX_MAC_DescrTable[i].TxRx_Status = 0x0;
		TX_MAC_DescrTable[i].DmaMac_Addr = (int)(TX_MAC_DescrTable[i].FrameBuf);	
		TX_MAC_DescrTable[i].DmaMac_Cntl = DmaMac_NxtEn |
	            				    (MAC_MAX_FRAME_SZ & DmaMac_XferCntMsk) |
	                                            ((3 * DmaMac_EntryTrigU) & DmaMac_EntryTrigMsk);
	}

	/* Start the DMA for sending */
	DMA_MAC->TX_DMA_NXT   = ((int) TX_MAC_DescrTable & DmaMac_DescrAddrMsk) | DmaMac_NpolEn;

        return 1; //MAC initialized
}

//-----------------------------------------------------------------------------
// name: MAC_Send()
// functionality: Builds and Sends an Ethernet frame
//-----------------------------------------------------------------------------
int MAC_Send(EthernetFrame *frame, u16 len)
{
	u8	*dest; //pointer to the data to be sent
        u32	DmaStat;
        u8 *Buffer;


        if (!len) {
          len = ETHER_HEADER_LENGTH; //
                  //Check whether the length of the frame is not too long
          if (len >= MAC_MAX_FRAME_SZ)
	        {
		  return 0;  //frame too long
	        }
        }

        Buffer = frame->EthernetFrameByByte;

        //Check whether the current DMA descriptor VALID bit is 0 -> CPU is the owner -> continue
 	DmaStat = TX_MAC_DescrTable[TX_MAC_currDescNum].TxRx_Status;
 	if (DmaStat & DmaMac_Valid)
		return 0;

	dest = TX_MAC_DescrTable[TX_MAC_currDescNum].FrameBuf; //pointer to the data to be sent

        //Data is copied
	memcpy(dest, Buffer, len);

        //Prepares settings of the TX_DMA_CNTL register
        TX_MAC_DescrTable[TX_MAC_currDescNum].DmaMac_Cntl  = DmaMac_NxtEn |
	            				    		(len & DmaMac_XferCntMsk) |
	                                            		((3 * DmaMac_EntryTrigU) & DmaMac_EntryTrigMsk);

        //Set the VALID bit to 1, enables DMA to access the Current Descriptor
        TX_MAC_DescrTable[TX_MAC_currDescNum].TxRx_Status   = DmaMac_Valid;

	DMA_MAC->TX_DMA_START   |= DmaMac_StartFetch | ((1000 * DmaMac_DFetchDlyU) & DmaMac_DFetchDlyMsk);


        /* Test the wrap-around condition. */
        if (++TX_MAC_currDescNum >= TX_MAC_DESCR_NUM)
                TX_MAC_currDescNum = 0;

        return 1;
}

//-----------------------------------------------------------------------------
// name: MAC_Recv()
// functionality: Receives an Ethernet frame
//-----------------------------------------------------------------------------
u16 MAC_Recv(EthernetFrame *frame)
{
        u16     type = 0;
        u32     DmaStat;

        while(1)
        {
 		DmaStat = RX_MAC_DescrTable[RX_MAC_currDescNum].TxRx_Status;
 		if (DmaStat & DmaMac_Valid)
			break;
                type = *(u16 *)&RX_MAC_DescrTable[RX_MAC_currDescNum].FrameBuf[2*MAC_ADDR_LEN];

                //Data is copied
                memcpy(frame->EthernetFrameByByte, RX_MAC_DescrTable[RX_MAC_currDescNum].FrameBuf, MAC_MAX_FRAME_SZ);
		
		/* Make the current descriptor valid again and go to the next one */
		RX_MAC_DescrTable[RX_MAC_currDescNum].TxRx_Status = DmaMac_Valid;

		/* Test the wrap-around condition. */
		if (++RX_MAC_currDescNum >= RX_MAC_DESCR_NUM)
			RX_MAC_currDescNum = 0;
        }

	return type;
}


//-----------------------------------------------------------------------------
//*                                                                         *//
//*                                                                         *//
//*                                                                         *//
//*                         DMA MAC irq handler routines                    *//
//*                                                                         *//
//*                                                                         *//
//*                                                                         *//
//-----------------------------------------------------------------------------
void MAC_IrqHandler_RxEmpty(void){
}
//-----------------------------------------------------------------------------
void MAC_IrqHandler_RxFull(void){
}
//-----------------------------------------------------------------------------
void MAC_IrqHandler_RxEntry(void){
}
//-----------------------------------------------------------------------------
void MAC_IrqHandler_RxTo(void){
}
//-----------------------------------------------------------------------------
void MAC_IrqHandler_PckLost(void){
}
//-----------------------------------------------------------------------------
void MAC_IrqHandler_RxNext(void){
}
//-----------------------------------------------------------------------------
void MAC_IrqHandler_RxDone(void){
}
//-----------------------------------------------------------------------------
void MAC_IrqHandler_RxMErr(void){
}
//-----------------------------------------------------------------------------
void MAC_IrqHandler_RxCurrDone(void){
}
//-----------------------------------------------------------------------------
void MAC_IrqHandler_TxEmpty(void){
}
//-----------------------------------------------------------------------------
void MAC_IrqHandler_TxFull(void){
}
//-----------------------------------------------------------------------------
void MAC_IrqHandler_TxEntry(void){
}
//-----------------------------------------------------------------------------
void MAC_IrqHandler_TxTo(void){
}
//-----------------------------------------------------------------------------
void MAC_IrqHandler_TxNext(void){
}
//-----------------------------------------------------------------------------
void MAC_IrqHandler_TxDone(void){
}
//-----------------------------------------------------------------------------
void MAC_IrqHandler_TxMErr(void){
}
//-----------------------------------------------------------------------------
void MAC_IrqHandler_MACInt(void){
}
//-----------------------------------------------------------------------------
void MAC_IrqHandler_TxCurrDone(void){

}
//-----------------------------------------------------------------------------

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?