📄 net_nic.c
字号:
NIC_BUF_DESC *searchPtr;
n_rdy = 0;
searchPtr = NIC_RxBufDescPtrStart;
while (searchPtr != NIC_RxBufDescPtrEnd) {
if (((searchPtr->status & EMAC_RXBUF_EOF_MASK) > 0) &&
((searchPtr->addr & EMAC_RXBUF_SW_OWNED) > 0)) {
n_rdy++;
}
searchPtr++;
}
return (n_rdy);
}
/*
---------------------------------------------------------------------------------------------------------
THE FOLLOWING FUNCTIONS ARE CALLED FROM THE RX TASK DURING THE PROCESSING OF A SINGLE RX FRAME
The following functions are called in the order described below.
GetSize(), followed by (RxPkt(), OR RxPktDiscard())
---------------------------------------------------------------------------------------------------------
*/
/*
*********************************************************************************************************
* NetNIC_RxPktGetSize()
*
* Description : Get network packet size from NIC.
*
* Argument(s) : none.
*
* Return(s) : Size, in octets, of next frame to be read from the EMAC buffers
*
* Caller(s) : NetIF_RxTaskHandler()
*
* Notes : 1) On occassion, it is possible to have frame fragments in the descriptor list. As mentioned
* above in Note 1) of NIC_GetNRdy(), should 2 start of frame descriptors be found without
* corresponding EOF descriptors , then softwares must free the rogue descriptors. This
* function will free rogue descriptors if they are found while searching for the next
* frame and its corresponding size
*
* 2) This routine causes the TCP/IP stack to service received frames in a random order.
* In other words, frames that arrive before other frames are not guarrenteed to be
* serviced first. This is a result of always searching through the descriptor list from
* top to bottom, and not from an expected start point and wrapping around. The benefit to
* this approach however is that you dont have to keep state information about where the
* next expected SOF flag will be. Nor do you have check if the expected SOF pointer is
* correct and make changes should Note 1) effect the correctness of that pointer.
*
* 3) There MUST be at least 1 SOF / EOF combination in the descriptor list, otherwise
* interrupt generation would not have occured since interrupt generation takes place
* after the complete frame has been trasferred via DMA to RAM.
*********************************************************************************************************
*/
CPU_INT16U NetNIC_RxPktGetSize (void)
{ /* WARNING: No code should never be inserted between a */
CPU_INT16U size; /* ptr increment, and the following end of list check */
NIC_BUF_DESC *searchPtr; /* This function contains several pointer increments */
NIC_CurrentFrameStart = NULL; /* Initialize the Current Frame Start pointer to NULL */
NIC_CurrentFrameEnd = NULL; /* Initialize the Current Frame Start pointer to NULL */
searchPtr = NIC_ExpectedFrameStart; /* Begin searching from the expected SOF descriptor */
while (((searchPtr->status & EMAC_RXBUF_SOF_MASK) == 0) || /* While the expected SOF is NOT pointing to a software */
((searchPtr->addr & EMAC_RXBUF_SW_OWNED) == 0)) { /* owned SOF descriptor (precautionary code) */
searchPtr++; /* Move the next descriptor in the list */
if (searchPtr == NIC_RxBufDescPtrEnd) { /* If we are at the end of the list */
searchPtr = NIC_RxBufDescPtrStart; /* Wrap around to the beginning */
}
}
/* We now point to a SOF desc that software ownes */
NIC_CurrentFrameStart = searchPtr; /* Save the location of the SOF descriptor */
while (((searchPtr->status & EMAC_RXBUF_EOF_MASK) == 0) || /* Loop until we find the matching EOF descriptor */
((searchPtr->addr & EMAC_RXBUF_SW_OWNED) == 0)) { /* that is software owned */
searchPtr++;
if (searchPtr == NIC_RxBufDescPtrEnd) { /* If we are at the end of the list */
searchPtr = NIC_RxBufDescPtrStart; /* Wrap around to the beginning */
}
if (((searchPtr->status & EMAC_RXBUF_SOF_MASK) > 0) && /* If while searching for EOF we find another SW owned */
((searchPtr->addr & EMAC_RXBUF_SW_OWNED) > 0)) { /* SOF, then we must free the incomplete frame desc's */
while (NIC_CurrentFrameStart != searchPtr) { /* Loop from the last found SOF, to the newly found SOF */
NIC_CurrentFrameStart->addr &= ~EMAC_RXBUF_SW_OWNED; /* Free a descriptor belonging to the incomplete frame */
NIC_CurrentFrameStart++; /* Point to the next descriptor that needs to be freed */
if (NIC_CurrentFrameStart == NIC_RxBufDescPtrEnd) { /* If we are at the end of the descriptor list */
NIC_CurrentFrameStart = NIC_RxBufDescPtrStart; /* Wrap around to the beginning of the list */
}
}
/* Done freeing incomplete frame descriptors */
NIC_CurrentFrameStart = searchPtr; /* However, we must now save the new SOF location */
}
}
/* We now point to a SW owned EOF descriptor */
NIC_CurrentFrameEnd = searchPtr; /* Save the location of the EOF descriptor */
NIC_ExpectedFrameStart = (searchPtr + 1); /* The next expected SOF is in the next descriptor */
/* We store this information now to improve search */
/* performance on the next NetNIC_RxPktGetSize() */
if (NIC_ExpectedFrameStart == NIC_RxBufDescPtrEnd) { /* If the next expected frame points after the end of */
NIC_ExpectedFrameStart = NIC_RxBufDescPtrStart; /* the list, wrap back around to the beginning */
}
/* Retrieve the frame size for the frame to be read */
/* next from the buffers using the 'Current' pointers */
size = NIC_CurrentFrameEnd->status & EMAC_RXBUF_LEN_MASK;
return (size);
}
/*
*********************************************************************************************************
* NetNIC_RxPkt()
*
* Description : Read network packet from NIC into buffer.
*
* Argument(s) : ppkt Pointer to memory buffer to receive NIC packet.
*
* size Number of packet frame octets to read into buffer.
*
* perr Pointer to variable that will hold the return error code from this function :
*
* NET_NIC_ERR_NONE Packet successfully read.
* NET_ERR_INIT_INCOMPLETE Network initialization NOT complete.
* NET_NIC_ERR_NULL_PTR Argument 'ppkt' passed a NULL pointer.
* NET_NIC_ERR_INVALID_SIZE Invalid size.
*
* Return(s) : none.
*
* Caller(s) : NetIF_RxTaskHandler().
*
* Note(s) : 1) NetNIC_RxPkt() blocked until network initialization completes; perform NO action.
*********************************************************************************************************
*/
void NetNIC_RxPkt (void *ppkt,
CPU_INT16U size,
NET_ERR *perr)
{
#if (NET_CTR_CFG_STAT_EN == DEF_ENABLED)
#if (CPU_CFG_CRITICAL_METHOD == CPU_CRITICAL_METHOD_STATUS_LOCAL)
CPU_SR cpu_sr;
#endif
#endif
if (Net_InitDone != DEF_YES) { /* If init NOT complete, exit rx (see Note #2). */
*perr = NET_ERR_INIT_INCOMPLETE;
return;
}
#if (NET_ERR_CFG_ARG_CHK_DBG_EN == DEF_ENABLED) /* ------------------- VALIDATE PTR ------------------ */
if (ppkt == (void *)0) {
*perr = NET_NIC_ERR_NULL_PTR;
return;
}
/* ------------------- VALIDATE SIZE ----------------- */
if (size < NET_IF_FRAME_MIN_SIZE) {
*perr = NET_NIC_ERR_INVALID_SIZE;
return;
}
#endif
EMAC_RxPkt(ppkt, size, perr); /* Read the received Frame from the EMAC buffers */
if (*perr != NET_NIC_ERR_NONE) {
return;
}
NET_CTR_STAT_INC(NetNIC_StatRxPktCtr);
*perr = NET_NIC_ERR_NONE;
}
/*
*********************************************************************************************************
* EMAC_RxPkt()
*
* Description : (1) Read network packet from NIC into buffer :
* (a) Read received frame from AT91SAM7X256 DMA memory space.
* (b) Release descriptors once data has been read
*
* Argument(s) : ppkt Pointer to memory buffer to receive NIC packet.
* ---- Argument checked in NetNIC_RxPkt().
*
* size Number of packet frame octets to read into buffer.
* ---- Argument checked in NetNIC_RxPkt().
*
* perr Pointer to variable that will hold the return error code from this function :
*
* NET_NIC_ERR_NONE Packet successfully transmitted.
* NET_ERR_RX Error Reading Buffers (EOF not found)
*
* Return(s) : none.
*
* Caller(s) : NetNIC_RxPkt().
*
* Note(s) : 1) See 'AT91SAM7X256 EMAC RECEIVE BUFFER DESCRIPTOR' for packet frame format.
* 2) Operational Description:
* a) If we are operating on a descriptor that is both SOF and EOF, we only
* execute the code below the while loop.
*
* b) If the received frame is contained in 2 descriptors, we ONLY execute the
* outside 'if' block within the while loop, AND, the code below the while loop.
*
* c) If the received frame fills 3 or more descriptors, we first execute code
* within the outside 'if' statement if the while loop once, followed by
* (numberOfFilledDescriptors - 1) iterations of the outside 'else' block
* within the while loop, and for the very last descriptor, the code below
* the while loop.
*********************************************************************************************************
*/
static void EMAC_RxPkt (void *ppkt,
CPU_INT16U size,
NET_ERR *perr)
{
#if (CPU_CFG_CRITICAL_METHOD == CPU_CRITICAL_METHOD_STATUS_LOCAL)
CPU_SR cpu_sr;
#endif
CPU_INT16U sizeLeftToCopy;
CPU_INT08U dataOffset;
CPU_INT08U *pStackBuf;
CPU_INT08U *pEMACBuf;
NIC_BUF_DESC *searchPtr;
CPU_BOOLEAN doMemCpy;
*perr = NET_NIC_ERR_NONE; /* Begin with no error code being returned */
doMemCpy = TRUE; /* Error Control. If an error occurs, we can stop */
/* performing mem copies, will still executing the loop */
/* freeing the remaining descriptors without */
/* accidently overwriting other memory */
sizeLeftToCopy = size; /* Make a copy of size for debugging purposes */
searchPtr = NIC_CurrentFrameStart; /* Point to the SOF descriptor. Start copy from here */
pStackBuf = (CPU_INT08U *)ppkt; /* Point to the TCP/IP stacks buffer, copy into here */
/* Determine the data offset for the first descriptor */
dataOffset = (searchPtr->status & EMAC_RXBUF_OFF_MASK) >> 12;
while (searchPtr != NIC_CurrentFrameEnd) { /* Copy from SOF to EOF descriptor (EOF not inclusive) */
/* Get the address of the buffer we wish to copy */
pEMACBuf = (CPU_INT08U *)((searchPtr->addr & EMAC_RXBUF_ADDRESS_MASK));
if (searchPtr == NIC_CurrentFrameStart) { /* If its the SOF, include the offset in the copy size */
if (doMemCpy == TRUE) {
Mem_Copy((void *)(pStackBuf), (void *)(pEMACBuf + dataOffset), NIC_RX_BUF_SIZE - dataOffset);
pStackBuf += (NIC_RX_BUF_SIZE - dataOffset); /* Advance the pointer into the TCP/IP stacks buffer */
}
if ((sizeLeftToCopy - NIC_RX_BUF_SIZE - dataOffset) >= 0) { /* Subtract the amount copied from the total left */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -