📄 enc28j60.c
字号:
/******************************************************/
}
/******************************************************************************
* Function: void MACSetRxBuffer(WORD offset)
*
* PreCondition: A packet has been obtained by calling MACGetHeader() and
* getting a TRUE result.
*
* Input: offset: WORD specifying how many bytes beyond the Ethernet
* header's type field to relocate the SPI read and
* write pointers.
*
* Output: None
*
* Side Effects: None
*
* Overview: SPI read and write pointers are updated. All calls to
* MACGet(), MACPut(), MACGetArray(), and MACPutArray(),
* and various other functions will use these new values.
*
* Note: RXSTOP must be statically defined as being > RXSTART for
* this function to work correctly. In other words, do not
* define an RX buffer which spans the 0x1FFF->0x0000 memory
* boundary.
*****************************************************************************/
void MACSetRxBuffer(WORD offset)
{
WORD_VAL ReadPT;
// Determine the address of the beginning of the entire packet
// and adjust the address to the desired location
ReadPT.Val = CurrentPacketLocation.Val + sizeof(MCP_PREAMBLE) + offset;
// Since the receive buffer is circular, adjust if a wraparound is needed
if ( ReadPT.Val > RXSTOP )
ReadPT.Val -= RXSIZE;
// Set the SPI read and write pointers to the new calculated value
BankSel(ERDPTL);
WriteReg(ERDPTL, ReadPT.v[0]);
WriteReg(ERDPTH, ReadPT.v[1]);
WriteReg(EWRPTL, ReadPT.v[0]);
WriteReg(EWRPTH, ReadPT.v[1]);
}
/******************************************************************************
* Function: void MACSetTxBuffer(BUFFER buffer, WORD offset)
*
* PreCondition: None
*
* Input: buffer: unsigned char specifying which transmit buffer to seek
* within. If MAC_TX_BUFFER_COUNT <= 1, this
* parameter is not used.
* offset: WORD specifying how many bytes beyond the Ethernet
* header's type field to relocate the SPI read and
* write pointers.
*
* Output: None
*
* Side Effects: None
*
* Overview: SPI read and write pointers are updated. All calls to
* MACGet(), MACPut(), MACGetArray(), and MACPutArray(),
* and various other functions will use these new values.
*
* Note: None
*****************************************************************************/
void MACSetTxBuffer(BUFFER buffer, WORD offset)
{
NICCurrentTxBuffer = buffer;
// Calculate the proper address. Since the TX memory area is not circular,
// no wrapparound checks are necessary. +1 adjustment is needed because of
// the per packet control byte which preceeds the packet in the TX memory
// area.
#if MAC_TX_BUFFER_COUNT > 1
offset += TxBuffers[buffer].StartAddress + 1 + sizeof(ETHER_HEADER);
#else
offset += TXSTART + 1 + sizeof(ETHER_HEADER);
#endif
// Set the SPI read and write pointers to the new calculated value
BankSel(EWRPTL);
WriteReg(ERDPTL, ((WORD_VAL*)&offset)->v[0]);
WriteReg(ERDPTH, ((WORD_VAL*)&offset)->v[1]);
WriteReg(EWRPTL, ((WORD_VAL*)&offset)->v[0]);
WriteReg(EWRPTH, ((WORD_VAL*)&offset)->v[1]);
}
#if defined(MCHP_MAC)
// MACCalcRxChecksum() and MACCalcTxChecksum() use the DMA module to calculate
// checksums. These two functions have been tested.
/******************************************************************************
* Function: WORD MACCalcRxChecksum(WORD offset, WORD len)
*
* PreCondition: None
*
* Input: offset- Number of bytes beyond the beginning of the
* Ethernet data (first byte after the type field)
* where the checksum should begin
* len- Total number of bytes to include in the checksum
*
* Output: 16-bit checksum as defined by rfc 793.
*
* Side Effects: None
*
* Overview: This function performs a checksum calculation in the MAC
* buffer itself using the hardware DMA module
*
* Note: None
*****************************************************************************/
WORD MACCalcRxChecksum(WORD offset, WORD len)
{
WORD_VAL temp;
// Add the offset requested by firmware plus the Ethernet header
// temp.val is the position of IP head
temp.Val = CurrentPacketLocation.Val + sizeof(MCP_PREAMBLE) + offset;
if ( temp.Val > RXSTOP ) // Adjust value if a wrap is needed
temp.Val -= RXSIZE;
// Program the start address of the DMA
BankSel(EDMASTL);
WriteReg(EDMASTL, temp.v[0]);
WriteReg(EDMASTH, temp.v[1]);
// Calculate the end address, given the start address and len
temp.Val += len-1;
if ( temp.Val > RXSTOP ) // Adjust value if a wrap is needed
temp.Val -= RXSIZE;
// Program the end address of the DMA
WriteReg(EDMANDL, temp.v[0]);
WriteReg(EDMANDH, temp.v[1]);
// Do the checksum calculation
BFSReg(ECON1, ECON1_DMAST | ECON1_CSUMEN);
while(ReadETHReg(ECON1).ECON1bits.DMAST);
// Swap endianness and return
temp.v[1] = ReadETHReg(EDMACSL).Val;
temp.v[0] = ReadETHReg(EDMACSH).Val;
return temp.Val;
}
/******************************************************************************
* Function: WORD MACCalcTxChecksum(WORD offset, WORD len)
*
* PreCondition: None
*
* Input: offset- Number of bytes beyond the beginning of the
* Ethernet data (first byte after the type field)
* where the checksum should begin
* len- Total number of bytes to include in the checksum
*
* Output: 16-bit checksum as defined by rfc 793.
*
* Side Effects: None
*
* Overview: This function performs a checksum calculation in the MAC
* buffer itself using the hardware DMA module
*
* Note: None
*****************************************************************************/
WORD MACCalcTxChecksum(WORD offset, WORD len)
{
WORD_VAL temp;
// Program the start address of the DMA, after adjusting for the Ethernet
// header
#if MAC_TX_BUFFER_COUNT > 1
temp.Val = TxBuffers[NICCurrentTxBuffer].StartAddress + sizeof(ETHER_HEADER)
+ offset + 1; // +1 needed to account for per packet control byte
#else
temp.Val = TXSTART + sizeof(ETHER_HEADER)
+ offset + 1; // +1 needed to account for per packet control byte
#endif
BankSel(EDMASTL);
WriteReg(EDMASTL, temp.v[0]);
WriteReg(EDMASTH, temp.v[1]);
// Program the end address of the DMA.
temp.Val += len-1;
WriteReg(EDMANDL, temp.v[0]);
WriteReg(EDMANDH, temp.v[1]);
// Do the checksum calculation
BFSReg(ECON1, ECON1_DMAST | ECON1_CSUMEN);
while(ReadETHReg(ECON1).ECON1bits.DMAST);
// Swap endianness and return
temp.v[1] = ReadETHReg(EDMACSL).Val;
temp.v[0] = ReadETHReg(EDMACSH).Val;
return temp.Val;
}
/******************************************************************************
* Function: WORD CalcIPBufferChecksum(WORD len)
*
* PreCondition: Read buffer pointer set to starting of checksum data
*
* Input: len: Total number of bytes to calculate the checksum over.
* The first byte included in the checksum is the byte
* pointed to by ERDPT, which is updated by calls to
* MACGet(), MACSetRxBuffer(), MACSetTxBuffer(), etc.
*
* Output: 16-bit checksum as defined by rfc 793.
*
* Side Effects: None
*
* Overview: This function performs a checksum calculation in the MAC
* buffer itself. The ENC28J60 has a hardware DMA module
* which can calculate the checksum faster than software, so
* this function replaces the CaclIPBufferChecksum() function
* defined in the helpers.c file. Through the use of
* preprocessor defines, this replacement is automatic.
*
* Note: This function works either in the RX buffer area or the TX
* buffer area. No validation is done on the len parameter.
*****************************************************************************/
WORD CalcIPBufferChecksum(WORD len)
{
WORD_VAL temp;
// Take care of special cases which the DMA cannot be used for
if(len == 0u)
return 0xFFFF;
else if(len == 1u)
return ~(((WORD)MACGet())<<8);
// Set the DMA starting address to the SPI read pointer value
BankSel(ERDPTL);
temp.v[0] = ReadETHReg(ERDPTL).Val;
temp.v[1] = ReadETHReg(ERDPTH).Val;
WriteReg(EDMASTL, temp.v[0]);
WriteReg(EDMASTH, temp.v[1]);
// See if we are calculating a checksum within the RX buffer (where
// wrapping rules apply) or TX/unused area (where wrapping rules are
// not applied)
if(temp.Val >= RXSTART && temp.Val <= RXSTOP)
{
// Calculate the DMA ending address given the starting address and len
// parameter. The DMA will follow the receive buffer wrapping boundary.
temp.Val += len-1;
if(temp.Val > RXSTOP)
{
temp.Val -= RXSIZE;
}
}
else
{
temp.Val += len-1;
}
// Write the DMA end address
WriteReg(EDMANDL, temp.v[0]);
WriteReg(EDMANDH, temp.v[1]);
// Begin the DMA checksum calculation and wait until it is finished
BFSReg(ECON1, ECON1_DMAST | ECON1_CSUMEN);
while(ReadETHReg(ECON1).ECON1bits.DMAST);
// Return the resulting good stuff
temp.v[0] = ReadETHReg(EDMACSL).Val;
temp.v[1] = ReadETHReg(EDMACSH).Val;
return temp.Val;
}
#endif // End of MCHP_MAC specific code
/******************************************************************************
* Function: void MACCopyRxToTx(WORD RxOffset, WORD TxOffset, WORD len)
*
* PreCondition: None
*
* Input: RxOffset: Offset in the RX buffer (0=first byte of
* destination MAC address) to copy from.
* TxOffset: Offset in the TX buffer (0=first byte of
* destination MAC address) to copy to.
* len: Number of bytes to copy
*
* Output: None
*
* Side Effects: None
*
* Overview: If the TX logic is transmitting a packet (ECON1.TXRTS is
* set), the hardware will wait until it is finished. Then,
* the DMA module will copy the data from the receive buffer
* to the transmit buffer.
*
* Note: None
*****************************************************************************/
// Remove this line if your application needs to use this
// function. This code has NOT been tested.
#if 0
void MACCopyRxToTx(WORD RxOffset, WORD TxOffset, WORD len)
{
WORD_VAL temp;
temp.Val = CurrentPacketLocation.Val + RxOffset + sizeof(MCP_PREAMBLE);
if ( temp.Val > RXSTOP ) // Adjust value if a wrap is needed
temp.Val -= RXSIZE;
BankSel(EDMASTL);
WriteReg(EDMASTL, temp.v[0]);
WriteReg(EDMASTH, temp.v[1]);
temp.Val += len-1;
if ( temp.Val > RXSTOP ) // Adjust value if a wrap is needed
temp.Val -= RXSIZE;
WriteReg(EDMANDL, temp.v[0]);
WriteReg(EDMANDH, temp.v[1]);
TxOffset += TXSTART+1;
WriteReg(EDMADSTL, ((WORD_VAL*)&TxOffset)->v[0]);
WriteReg(EDMADSTH, ((WORD_VAL*)&TxOffset)->v[1]);
// Do the DMA Copy. The DMA module will wait for TXRTS to become clear
// before starting the copy.
BFCReg(ECON1, ECON1_CSUMEN);
BFSReg(ECON1, ECON1_DMAST);
while(ReadETHReg(ECON1).ECON1bits.DMAST);
}
#endif
#if defined(MAC_FILTER_BROADCASTS)
// NOTE: This code has NOT been tested. See StackTsk.h's explanation
// of MAC_FILTER_BROADCASTS.
/******************************************************************************
* Function: void MACSetPMFilter(unsigned char *Pattern,
* unsigned char *PatternMask,
* WORD PatternOffset)
*
* PreCondition: SPI bus must be initialized (done in MACInit()).
* MACIsTxReady() must return TRUE
*
* Input: *Pattern: Pointer to an intial pattern to compare against
* *PatternMask: Pointer to an 8 byte pattern mask which
* defines which bytes of the pattern are
* important. At least one bit must be set.
* PatternOffset: Offset from the beginning of the Ethernet
* frame (1st byte of destination address), to
* begin comparing with the given pattern.
*
* Output: None
*
* Side Effects: Contents of the TX buffer space are overwritten
*
* Overview: MACSetPMFilter sets the hardware receive filters for:
* CRC AND (Unicast OR Pattern Match). As a result, only a
* subset of the broadcast packets which are normally
* received will be received.
*
* Note: None
*****************************************************************************/
void MACSetPMFilter(unsigned char *Pattern,
unsigned char *PatternMask,
WORD PatternOffset)
{
WORD_VAL i;
unsigned char *MaskPtr;
unsigned char UnmaskedPatternLen;
// Set the SPI write pointer and DMA startting address to the beginning of
// the transmit buffer
BankSel(EWRPTL);
WriteReg(EWRPTL, LOW(TXSTART));
WriteReg(EWRPTH, HIGH(TXSTART));
WriteReg(EDMASTL, LOW(TXSTART));
WriteReg(EDMASTH, HIGH(TXSTART));
// Fill the transmit buffer with the pattern to match against. Only the
// bytes which have a mask bit of 1 are written into the buffer and will
// subsequently be used for checksum computation.
MaskPtr = PatternMask;
for(i.Val = 0x0100; i.v[0] < 64; i.v[0]++)
{
if( *MaskPtr & i.v[1] )
{
MACPut(*Pattern);
UnmaskedPatternLen++;
}
Pattern++;
i.v[1] <<= 1;
if( i.v[1] == 0u )
{
i.v[1] = 0x01;
MaskPtr++;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -