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

📄 enc28j60.c

📁 Taiwan sunplus develop spce3200, it is a test program ----- testboard source code
💻 C
📖 第 1 页 / 共 5 页
字号:
/*********************************************************************
 *
 *     MAC Module (Microchip ENC28J60) for Microchip TCP/IP Stack
 *
 *********************************************************************
 * FileName:        ENC28J60.c
 * Dependencies:    ENC28J60.h
 *					MAC.h
 *					string.h
 *                  StackTsk.h
 *                  Helpers.h
 *					Delay.h
 * Processor:       PIC18
 * Complier:        MCC18 v3.00 or higher
 *                  HITECH PICC-18 V8.10PL1 or higher
 * Company:         Microchip Technology, Inc.
 *
 * Software License Agreement
 *
 * This software is owned by Microchip Technology Inc. ("Microchip") 
 * and is supplied to you for use exclusively as described in the 
 * associated software agreement.  This software is protected by 
 * software and other intellectual property laws.  Any use in 
 * violation of the software license may subject the user to criminal 
 * sanctions as well as civil liability.  Copyright 2006 Microchip
 * Technology Inc.  All rights reserved.
 *
 * This software is provided "AS IS."  MICROCHIP DISCLAIMS ALL 
 * WARRANTIES, EXPRESS, IMPLIED, STATUTORY OR OTHERWISE, NOT LIMITED 
 * TO MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, AND 
 * INFRINGEMENT.  Microchip shall in no event be liable for special, 
 * incidental, or consequential damages.
 *
 * Author               Date   		Comment
 *~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 * Howard Schlunder		6/28/04		Original
 * Howard Schlunder		10/8/04		Cleanup
 * Howard Schlunder		10/19/04 	Small optimizations and more cleanup
 * Howard Schlunder		11/29/04 	Added Set/GetCLKOUT
 * Howard Schlunder		12/23/05 	Added B1 silicon errata workarounds
 * Howard Schlunder		1/09/06		Added comments and minor mods
 * Howard Schlunder		1/18/06 	Added more silicon errata workarounds
 * Howard Schlunder		2/20/06 	Fixed TXSTART, RXSTOP
********************************************************************/
#define THIS_IS_MAC_LAYER

#include <string.h>
#include "StackTsk.h"
//#include "Helpers.h"
//#include "Delay.h"
#include "MAC.h"
#include "ENC28J60.h"

extern void delay( unsigned short time);
extern unsigned char getSPIchar(unsigned char Address);
extern void putSPIchar2(unsigned char Address, unsigned char Data);
extern void putSPIchar(char ucData);

#if defined(STACK_USE_SLIP)
#error Unexpected module is detected.
#error This file must be linked when SLIP module is not in use.
#endif


/** D E F I N I T I O N S ****************************************************/
/* Hardware interface to NIC. */
#define MCP_RESET_TRIS	(TRISB_RB5)
#define MCP_RESET_IO	(LATB5)
#define MCP_CS_TRIS		(TRISB_RB3)
#define MCP_CS_IO		(LATB3)
// The following SPI pins are used but are not configurable
// RC3 is used for the SCK pin and is an output
// RC4 is used for the SDI pin and is an input
// RC5 is used for the SDO pin and is an output
// IMPORTANT SPI NOTE: The code in this file expects that the SPI interrupt 
// flag (PIR1_SSPIF) be clear at all times.  If the SPI is shared with 
// other hardware, the other code should clear the PIR1_SSPIF when it is 
// done using the SPI.

// Since the ENC28J60 doesn't support auto-negotiation, full-duplex mode is 
// not compatible with most switches/routers.  If a dedicated network is used 
// where the duplex of the remote node can be manually configured, you may 
// change this configuration.  Otherwise, half duplex should always be used.
#define HALF_DUPLEX
//#define FULL_DUPLEX
//#define LEDB_DUPLEX

/* Pseudo Functions */
#define LOW(a) 					(a & 0xFF)
#define HIGH(a) 				((a>>8) & 0xFF)
#define SPISelectEthernet()		MCP_CS_IO = 0
#define SPIUnselectEthernet()	MCP_CS_IO = 1

/* NIC RAM definitions */
#define RAMSIZE	8192ul		
#define TXSTART (RAMSIZE-(MAC_TX_BUFFER_COUNT * (MAC_TX_BUFFER_SIZE + 8ul)))
#define RXSTART	(0ul)											// Should be an even memory address
#define	RXSTOP	((TXSTART-2ul) | 0x0001ul)						// Odd for errata workaround
#define RXSIZE	(RXSTOP-RXSTART+1ul)

/* ENC28J60 Opcodes (to be ORed with a 5 bit address) */
#define	WCR (0x2<<5)											// Write Control Register command
#define BFS (0x4<<5)											// Bit Field Set command
#define	BFC (0x5<<5)											// Bit Field Clear command
#define	RCR (0x000<<5)											// Read Control Register command
#define RBM ((0x1<<5) | 0x1A)									// Read Buffer Memory command
#define	WBM ((0x3<<5) | 0x1A) 									// Write Buffer Memory command
#define	SR  ((0x7<<5) | 0x1F)									// System Reset command does not use an address.  
																// It requires 0x1F, however.

#define ETHER_IP	(0x00)
#define ETHER_ARP	(0x06)

#define MAXFRAMEC	(1500+sizeof(ETHER_HEADER)+4)

APP_CONFIG AppConfig;
// A generic structure representing the Ethernet header starting all Ethernet 
// frames
typedef struct _ETHER_HEADER
{
    MAC_ADDR        DestMACAddr;
    MAC_ADDR        SourceMACAddr;
    WORD_VAL        Type;
}__attribute__ ((packed)) ETHER_HEADER;

// A header appended at the start of all RX frames by the hardware
typedef struct _MCP_PREAMBLE
{
    WORD			NextPacketPointer;//2
    RXSTATUS		StatusVector;//4

    MAC_ADDR        DestMACAddr;//6
    MAC_ADDR        SourceMACAddr;//6
    WORD_VAL        Type;//2
} __attribute__ ((packed)) MCP_PREAMBLE;

typedef struct _DATA_BUFFER
{
	WORD_VAL StartAddress;
//	WORD_VAL EndAddress;
	BOOL bFree;
}__attribute__ ((packed)) DATA_BUFFER;


/* Prototypes of functions intended for MAC layer use only */
 void BankSel(WORD Register);
 REG ReadETHReg(unsigned char Address);
 REG ReadMACReg(unsigned char Address);
 void WriteReg(unsigned char Address, unsigned char Data);
 void BFCReg(unsigned char Address, unsigned char Data);
 void BFSReg(unsigned char Address, unsigned char Data);
 void SendSystemReset(void);
 
 void Software_Reset_Ethernet(void);
unsigned char  Read_RCR(unsigned char addr);
unsigned char  Read_MACRCR(unsigned char addr);
void Write_WCR(unsigned char addr,unsigned char data);
unsigned char  Read_RBM(void);
void Write_WBM(unsigned char data);
void Set_BFS(unsigned char addr,unsigned char data);
void Clear_BFC(unsigned char addr,unsigned char data);
void Bank_Select(unsigned char bank);
void Write_PHY(unsigned char addr,unsigned int data);
unsigned int  Read_PHY(unsigned char addr);
unsigned int  Scan_PHY(unsigned char addr);
void Led_Init(void);
 
#ifdef MAC_POWER_ON_TEST
static BOOL TestMemory(void);
#endif

/* Internal and externally used MAC level variables */
#if MAC_TX_BUFFER_COUNT > 1
static DATA_BUFFER TxBuffers[MAC_TX_BUFFER_COUNT];
#endif
unsigned char NICCurrentTxBuffer;

/* Internal MAC level variables and flags */
WORD_VAL NextPacketLocation;
WORD_VAL CurrentPacketLocation;
BOOL WasDiscarded;

/***added by lfei 2007/02/05********/
/*function: Used for transmitting data packet for MACFLUSH*/
unsigned char ENCRevID;

/*******************************/

unsigned short swaps(unsigned short v)
{
    WORD_VAL t;
    unsigned char b;

    t.Val   = v;
    b       = t.v[1];
    t.v[1]  = t.v[0];
    t.v[0]  = b;

    return t.Val;
}


/******************************************************************************
 * Function:		void MACInit(void)
 *
 * PreCondition:	None
 *
 * Input:			None
 *
 * Output:			None
 *
 * Side Effects:	None
 *
 * Overview:		MACInit sets up the PIC's SPI module and all the 
 *					registers in the ENC28J60 so that normal operation can 
 *					begin.
 *
 * Note:			None
 *****************************************************************************/
short MACInit(void)
{
	unsigned char i;
	short Ret = 1;
	int j=0;


	// Wait for CLKRDY to become set.
	// Bit 3 in ESTAT is an unimplemented bit.  If it reads out as '1' that
	// means the part is in RESET or otherwise our SPI pin is being driven
	// incorrectly.  Make sure it is working before proceeding.
	j = 0;
	do
	{
		i = ReadETHReg(ESTAT).Val;
		j++;
		if(j>=5000)
		{
			Ret = 0;
			break;
		}
	} while((i & 0x08) || (~i & ESTAT_CLKRDY));


#ifdef MAC_POWER_ON_TEST
	// Do the memory test and enter a while always trap if a hardware error 
	// occured.  The LEDA and LEDB pins will be configured to blink 
	// periodically in an abnormal manner to indicate to the user that the 
	// error occured.
	if( !TestMemory() )
	{
		SetLEDConfig(0x0AA2);									// Set LEDs to blink periodically
		while(1);			
	}
#endif

	// RESET the entire ENC28J60, clearing all registers
	SendSystemReset();	
	delay(1000);

#if MAC_TX_BUFFER_COUNT > 1
    // On Init, all transmit buffers are free.
    for (i = 0; i < MAC_TX_BUFFER_COUNT; i++ )
    {
        TxBuffers[i].StartAddress = TXSTART + ((WORD)i * (MAC_TX_BUFFER_SIZE+8));
        TxBuffers[i].bFree = TRUE;
    }
#endif
    NICCurrentTxBuffer = 0;
	
	/*
	 * Start up in Bank 0 and configure the receive buffer boundary pointers 
	 * and the buffer write protect pointer (receive buffer read pointer)
	 */
	WasDiscarded = TRUE;
	NextPacketLocation.Val = RXSTART;
	WriteReg(ERXSTL, LOW(RXSTART));
	WriteReg(ERXSTH, HIGH(RXSTART));

	WriteReg(ERXRDPTL, LOW(RXSTOP));				// Write low byte first
	WriteReg(ERXRDPTH, HIGH(RXSTOP));							// Write high byte last

#if RXSTOP != 0x1FFF											// The RESET default ERXND is 0x1FFF
	WriteReg(ERXNDL, LOW(RXSTOP));
	WriteReg(ERXNDH, HIGH(RXSTOP));
#endif
#if TXSTART != 0												// The RESET default ETXST is 0
	WriteReg(ETXSTL, LOW(TXSTART));
	WriteReg(ETXSTH, HIGH(TXSTART));
#endif

	/*
	 * Enter Bank 1 and configure Receive Filters 
	 * (No need to reconfigure - Unicast OR Broadcast with CRC checking is 
	 * acceptable)
	 */
	 BankSel(ERXFCON);
	 WriteReg(ERXFCON, ERXFCON_CRCEN);

	/*
	 * Enter Bank 2 and configure the MAC
	 */
	BankSel(MACON1);

	/*--------added by lfei 2007/01/21--*/
	// Clear MARST in MACON2, MAC exits reset status 
	
	WriteReg( MACON2, MACON2_MARST_CLR);
	
	/*-------------------------------*/

	// Enable the receive portion of the MAC
	WriteReg(MACON1, MACON1_TXPAUS | MACON1_RXPAUS | MACON1_MARXEN);
	
	// Pad packets to 60 bytes, add CRC, and check Type/Length field.
	// Default status of FULDPX is 0, that is, MAC is in half-duplex mode
	
	WriteReg(MACON3, MACON3_PADCFG0 | MACON3_TXCRCEN | MACON3_FRMLNEN);
	
	// Set non-back-to-back inter-packet gap to 9.6us.  The back-to-back 
	// inter-packet gap (MABBIPG) is set by MACSetDuplex() which is called 
	// later.
	WriteReg(MAIPGL, 0x12);
	WriteReg(MAIPGH, 0x0C);

	// Set the maximum packet size which the controller will accept
	WriteReg(MAMXFLL, LOW(MAXFRAMEC));	
	WriteReg(MAMXFLH, HIGH(MAXFRAMEC));
	
	/*
     * Enter Bank 3 and initialize physical MAC address registers
	 */
	BankSel(MAADR1);
//	print1("Set MAC address:\n");
    WriteReg(MAADR1, MY_MAC_BYTE1);
    if(Read_MACRCR(MAADR1)!=MY_MAC_BYTE1)
    	Ret = 0;
    WriteReg(MAADR2, MY_MAC_BYTE2);
    if(Read_MACRCR(MAADR2)!=MY_MAC_BYTE2)
    	Ret = 0;
    WriteReg(MAADR3, MY_MAC_BYTE3);
    if(Read_MACRCR(MAADR3)!=MY_MAC_BYTE3)
    	Ret = 0;
    WriteReg(MAADR4, MY_MAC_BYTE4);
    if(Read_MACRCR(MAADR4)!=MY_MAC_BYTE4)
    	Ret = 0;
    WriteReg(MAADR5, MY_MAC_BYTE5);
    if(Read_MACRCR(MAADR5)!=MY_MAC_BYTE5)
    	Ret = 0;
    WriteReg(MAADR6, MY_MAC_BYTE6);
    if(Read_MACRCR(MAADR6)!=MY_MAC_BYTE6)
    	Ret = 0;

/***added by lfei 2007/02/05********************/
	// Get the Rev ID so that we can implement the correct errata workarounds
		return Ret;

}//end MACInit


/******************************************************************************
 * Function:		BOOL MACIsLinked(void)
 *
 * PreCondition:	None
 *
 * Input:			None
 *
 * Output:			TRUE: If the PHY reports that a link partner is present 
 *					and the link has been up continuously since the last 
 *					call to MACIsLinked()
 *					FALSE: If the PHY reports no link partner, or the link went 
 *					down momentarily since the last call to MACIsLinked()
 *
 * Side Effects:	None
 *
 * Overview:		Returns the PHSTAT1.LLSTAT bit.
 *
 * Note:			None
 *****************************************************************************/
BOOL MACIsLinked(void)
{
	// LLSTAT is a latching low link status bit.  Therefore, if the link 
	// goes down and comes back up before a higher level stack program calls
	// MACIsLinked(), MACIsLinked() will still return FALSE.  The next 
	// call to MACIsLinked() will return TRUE (unless the link goes down 
	// again).
	return ReadPHYReg(PHSTAT1).PHSTAT1bits.LLSTAT;
//	return 0;
}

/******************************************************************************
 * Function:		BOOL MACIsTxReady(void)
 *
 * PreCondition:	None
 *
 * Input:			None
 *
 * Output:			TRUE: If no Ethernet transmission is in progress
 *					FALSE: If a previous transmission was started, and it has 
 *					not completed yet.  While FALSE, the data in the 
 *					transmit buffer and the TXST/TXND pointers must not
 *					be changed.

⌨️ 快捷键说明

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