📄 eth97j60.c
字号:
/*********************************************************************
*
* MAC Module (Microchip PIC18F97J60 family) for Microchip TCP/IP Stack
*
*********************************************************************
* FileName: ETH97J60.c
* Dependencies: ETH97J60.h
* MAC.h
* string.h
* StackTsk.h
* Helpers.h
* Delay.h
* Processor: PIC18F97J60 family device
* Complier: MCC18 v3.02 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
*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
* Rawin Rojvanit 07/26/05 Stuff
* Howard Schlunder 11/17/05 Ported to PIC18F97J60
* Howard Schlunder 06/16/06 Synchronized with ENC28J60 code
********************************************************************/
#define THIS_IS_MAC_LAYER
#include <string.h>
#include "..\Include\StackTsk.h"
#include "..\Include\Helpers.h"
#include "..\Include\Delay.h"
#include "..\Include\MAC.h"
#if !defined(__18F97J60) && !defined(__18F96J65) && !defined(__18F96J60) && !defined(__18F87J60) && !defined(__18F86J65) && !defined(__18F86J60) && !defined(__18F67J60) && !defined(__18F66J65) && !defined(__18F66J60) && !defined(HI_TECH_C)
#error "ETH97J60.c MAC layer for PIC18F97J60 family Ethernet modules is included, but a PIC18F97J60 family mirocontroller is not selected. Did you mean to include the ENC28J60.c MAC layer instead? Is your target processor selected correctly?"
#endif
#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 ****************************************************/
// Since the Ethernet PHY 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
// Pseudo Functions
#define LOW(a) (a & 0xFF)
#define HIGH(a) ((a>>8) & 0xFF)
// 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)
#define ETHER_IP (0x00u)
#define ETHER_ARP (0x06u)
#define MAXFRAMEC (1500u+sizeof(ETHER_HEADER)+4u)
// A generic structure representing the Ethernet header starting all Ethernet
// frames
typedef struct _ETHER_HEADER
{
MAC_ADDR DestMACAddr;
MAC_ADDR SourceMACAddr;
WORD_VAL Type;
} ETHER_HEADER;
// A header appended at the start of all RX frames by the hardware
typedef struct _ENC_PREAMBLE
{
WORD NextPacketPointer;
RXSTATUS StatusVector;
MAC_ADDR DestMACAddr;
MAC_ADDR SourceMACAddr;
WORD_VAL Type;
} ENC_PREAMBLE;
typedef struct _DATA_BUFFER
{
WORD_VAL StartAddress;
WORD_VAL EndAddress;
struct
{
unsigned char bFree : 1;
unsigned char bTransmitted : 1;
} Flags;
} DATA_BUFFER;
// Internal and externally used MAC level variables.
#if MAC_TX_BUFFER_COUNT > 1
static DATA_BUFFER TxBuffers[MAC_TX_BUFFER_COUNT];
#endif
BUFFER CurrentTxBuffer;
BUFFER LastTXedBuffer;
// Internal MAC level variables and flags.
WORD_VAL NextPacketLocation;
WORD_VAL CurrentPacketLocation;
BOOL WasDiscarded;
// Temp fix for bank f issue where registers are not located properly on PIC18F97J60 silicon revision A1 (A1 is beta silicon only)
// This can can be deleted for all production silicon chips (Rev. B0)
#pragma udata eth_sfr0=0xEFC
union
{
volatile far unsigned char EIRx;
volatile far struct {
unsigned RXERIF:1;
unsigned TXERIF:1;
unsigned WOLIF:1;
unsigned TXIF:1;
unsigned LINKIF:1;
unsigned DMAIF:1;
unsigned PKTIF:1;
} EIRxbits;
} EIRUnion;
#pragma udata eth_sfr1=0xEFA
volatile far unsigned char EDATAx;
#pragma udata eth_sfr3=0xEE0
union {
volatile far unsigned int ERDPTx;
volatile far struct {
unsigned char ERDPTLx;
unsigned char ERDPTHx;
} ERDPTxbytes;
} ERDPTUnion;
#pragma udata eth_sfr4=0xEDF
union {
volatile far unsigned char ECON1x;
volatile far struct {
unsigned :2;
unsigned RXEN:1;
unsigned TXRTS:1;
unsigned CSUMEN:1;
unsigned DMAST:1;
unsigned RXRST:1;
unsigned TXRST:1;
} ECON1xbits;
}ECON1Union;
//#pragma udata eth_sfr5=0xEFD
//volatile far unsigned char ESTATx;
#pragma udata
#define EDATA EDATAx
#define EIR EIRUnion.EIRx
#define EIRbits EIRUnion.EIRxbits
#define ERDPT ERDPTUnion.ERDPTx
#define ERDPTH ERDPTUnion.ERDPTxbytes.ERDPTHx
#define ERDPTL ERDPTUnion.ERDPTxbytes.ERDPTLx
#define ECON1 ECON1Union.ECON1x
#define ECON1bits ECON1Union.ECON1xbits
#define ESTAT ESTATx
/******************************************************************************
* Function: void MACInit(void)
*
* PreCondition: None
*
* Input: None
*
* Output: None
*
* Side Effects: None
*
* Overview: MACInit enables the Ethernet module, waits for the
* to become ready, and programs all registers for future
* TX/RX operations.
*
* Note: This function blocks for at least 1ms, waiting for the
* hardware to stabilize.
*****************************************************************************/
void MACInit(void)
{
BYTE i;
LATAbits.LATA0 = 0;
LATAbits.LATA1 = 0;
TRISAbits.TRISA0 = 0; // Set LED0 as output
TRISAbits.TRISA1 = 0; // Set LED1 as output
ECON2bits.ETHEN = 1; // Enable Ethernet!
// Wait for PHYRDY to become set.
while(!ESTATbits.PHYRDY);
// Wait at least 1ms for everything to stabilize
DelayMs(1);
#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.Val = TXSTART + ((WORD)i * (MAC_TX_BUFFER_SIZE+8));
TxBuffers[i].Flags.bFree = TRUE;
}
#endif
CurrentTxBuffer = 0;
// Configure the receive buffer boundary pointers
// and the buffer write protect pointer (receive buffer read pointer)
WasDiscarded = TRUE;
NextPacketLocation.Val = RXSTART;
ERXST = RXSTART;
ERXRDPTL = LOW(RXSTOP); // Write low byte first
ERXRDPTH = HIGH(RXSTOP);// Write high byte last
#if RXSTOP != 0x1FFF // The RESET default ERXND is 0x1FFF
ERXND = RXSTOP;
#endif
#if TXSTART != 0 // The RESET default ETXST is 0
ETXST = TXSTART;
#endif
// Configure Receive Filters
// (No need to reconfigure - Unicast OR Broadcast with CRC checking is
// acceptable)
//ERXFCON = ERXFCON_CRCEN; // Promiscious mode
// Configure the MAC
// Enable the receive portion of the MAC
MACON1 = MACON1_TXPAUS | MACON1_RXPAUS | MACON1_MARXEN; Nop();
// Pad packets to 60 bytes, add CRC, and check Type/Length field.
MACON3 = MACON3_PADCFG0 | MACON3_TXCRCEN | MACON3_FRMLNEN; Nop();
// Allow infinite deferals if the medium is continuously busy
// (do not time out a transmission if the half duplex medium is
// completely saturated with other people's data)
MACON4 = MACON4_DEFER; Nop();
// Late collisions occur beyond 63 bytes (default for 802.3 spec)
MACLCON2 = 63; Nop();
// 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.
MAIPGL = 0x12; Nop();
MAIPGH = 0x0C; Nop();
// Set the maximum packet size which the controller will accept
MAMXFLL = LOW(MAXFRAMEC); Nop();
MAMXFLH = HIGH(MAXFRAMEC); Nop();
// Initialize physical MAC address registers
MAADR1 = AppConfig.MyMACAddr.v[0]; Nop();
MAADR2 = AppConfig.MyMACAddr.v[1]; Nop();
MAADR3 = AppConfig.MyMACAddr.v[2]; Nop();
MAADR4 = AppConfig.MyMACAddr.v[3]; Nop();
MAADR5 = AppConfig.MyMACAddr.v[4]; Nop();
MAADR6 = AppConfig.MyMACAddr.v[5]; Nop();
// Disable half duplex loopback in PHY.
WritePHYReg(PHCON2, PHCON2_HDLDIS);
// Configure LEDA to display LINK status, LEDB to display TX/RX activity
SetLEDConfig(0x0472);
// Use the external LEDB polarity to determine weather full or half duplex
// communication mode should be set.
#if defined(FULL_DUPLEX)
MACSetDuplex(FULL); // Function exits with Bank 2 selected
#else
MACSetDuplex(HALF); // Function exits with Bank 2 selected
#endif
// Enable packet reception
ECON1bits.RXEN = 1;
}//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;
}
/******************************************************************************
* Function: BOOL MACIsTxReady(BOOL HighPriority)
*
* PreCondition: None
*
* Input: HighPriority: TRUE: Check the hardware ECON1.TXRTS bit
* FALSE: Check if a TX buffer is free
*
* 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.
*
* Side Effects: None
*
* Overview: Returns the ECON1.TXRTS bit
*
* Note: None
*****************************************************************************/
BOOL MACIsTxReady(BOOL HighPriority)
{
#if MAC_TX_BUFFER_COUNT > 1
BUFFER i;
if(HighPriority)
#endif
{
return !ECON1bits.TXRTS;
}
#if MAC_TX_BUFFER_COUNT > 1
// Check if the current buffer can be modified. It cannot be modified if
// the TX hardware is currently transmitting it.
if(CurrentTxBuffer == LastTXedBuffer)
{
return !ECON1bits.TXRTS;
}
// Check if a buffer is available for a new packet
for(i = 1; i < MAC_TX_BUFFER_COUNT; i++)
{
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -