Ethernet - Transmitting and Receiving using Memory Copy
Reception using Memory Copy
On some devices, the MAC is not part of processor peripherals, and is connected through a serial or a parallel communication scheme. You will have to create specific data transfer functions for writing and reading the data structures of the MAC.
Processing reception buffers in the ISR
The following is a list of the actions that must be performed in NetDev_ISR_Handler() to receive packets using Memory Copy.
Read MAC Status Register
Handle Receive ISR:
Signal Net IF Receive task
Clear Interrupt
Handle any other reported interrupts by MAC controller.
The listing below shows a template for the NetDev_ISR_Handle() function:
Listing - ISR Handler function template
static void NetDev_ISR_Handler (NET_IF *pif,
NET_DEV_ISR_TYPE type)
{
NET_DEV_CFG_ETHER *pdev_cfg;
NET_DEV_DATA *pdev_data;
NET_DEV *pdev;
CPU_DATA reg_val;
CPU_INT08U *p_data;
NET_ERR err;
(void)&type; (1)
pdev_cfg = (NET_DEV_CFG_ETHER *)pif->Dev_Cfg; (2)
pdev_data = (NET_DEV_DATA *)pif->Dev_Data; (3)
pdev = (NET_DEV *)pdev_cfg->BaseAddr; (4)
reg_val = pdev->ISR; (5)
if ((reg_val & RX_ISR_EVENT_MSK) > 0) { (6)
NetOS_IF_RxTaskSignal(pif->Nbr, &err); (7)
switch (err) {
case NET_IF_ERR_NONE:
No error during signalling.
break;
case NET_IF_ERR_RX_Q_FULL:
case NET_IF_ERR_RX_Q_SIGNAL_FAULT:
default:
An error occurred during signalling.
break;
}
pdev->ISR |= RX_ISR_EVENT_MSK; (8)
}
(9)
if ((reg_val & TX_ISR_EVENT_MSK) > 0) {
(10)
p_data = (CPU_INT08U *)pdev_data->TxBufCompPtr;
NetOS_IF_TxDeallocTaskPost(p_data, &err);
NetOS_Dev_TxRdySignal(pif->Nbr); (11)
pdev->ISR |= TX_ISR_EVENT_MSK; (12)
}
pdev->ISR |= UNHANDLED_ISR_EVENT_MASK; (13)
}(1) Prevent “variable unused” compiler warning.
(2) Obtain pointer to the device configuration structure.
(3) Obtain pointer to device data area.
(4) Overlay device register structure on top of device base address.
(5) Determine interrupt type.
(6) Handle reception interrupts.
(7) Signal NetIF reception queue task for each new ready descriptor.
(8) Clear device’s reception interrupt event flag.
(9) Handle transmission interrupts.
(10) Increment transmission packet counter.
(11) Signal NetIF that transmission resources are now available.
(12) Clear device’s transmission interrupt event flag.
(13) Clear unhandled interrupt event flag.
Moving buffers from the device to the TCP-IP stack using Memory Copy
The following a list of the actions that must be performed in NetDev_Rx() to receive packets using Memory Copy.
Disable interrupts
Read the length of the received frame
Obtain pointer to new data area
Copy frame to new data area
Set return values. Pointer to received data area and size
Re-Enable interrupts
Check for additional ready frames, and signal Net IF receive task
The listing below shows a template for the NetDev_Rx() function:
Listing - NetDev_Rx() function template
static void NetDev_Rx (NET_IF *pif,
CPU_INT08U **p_data,
CPU_INT16U *size,
NET_ERR *perr)
{
NET_DEV_CFG_ETHER *pdev_cfg;
NET_DEV_DATA *pdev_data;
NET_DEV *pdev;
CPU_INT08U *pbuf_new;
CPU_INT16S length;
CPU_INT16U cnt;
CPU_INT16U i;
pdev_cfg = (NET_DEV_CFG_ETHER *)pif->Dev_Cfg; (1)
pdev_data = (NET_DEV_DATA *)pif->Dev_Data; (2)
pdev = (NET_DEV *)pdev_cfg->BaseAddr; (3)
if ((pdev->RSTAT & RX_STATUS_ERR_MSK) > 0) { (4)
*size = (CPU_INT16U )0;
*p_data = (CPU_INT08U *)0;
*perr = (NET_ERR )NET_DEV_ERR_RX;
return;
}
length = (pdev->STATUS & RX_STATUS_SIZE_MSK) - NET_IF_ETHER_FRAME_CRC_SIZE; (5)
if (length < NET_IF_ETHER_FRAME_MIN_SIZE) {
*size = (CPU_INT16U )0;
*p_data = (CPU_INT08U *)0;
*perr = (NET_ERR )NET_DEV_ERR_INVALID_SIZE;
return;
}
pbuf_new = NetBuf_GetDataPtr((NET_IF *)pif, (6)
(NET_TRANSACTION)NET_TRANSACTION_RX,
#if (NET_VERSION >= 21000u)
(NET_BUF_SIZE )NET_IF_ETHER_FRAME_MAX_SIZE,
(NET_BUF_SIZE )NET_IF_IX_RX,
(NET_BUF_SIZE *)0,
#else
(NET_BUF_SIZE )pdev_cfg->RxBufLargeSize,
(NET_BUF_SIZE )0u,
#endif
(NET_BUF_SIZE *)0,
(NET_TYPE *)0,
(NET_ERR *)perr);
if (*perr != NET_BUF_ERR_NONE) { (7)
*size = (CPU_INT16U )0;
*p_data = (CPU_INT08U *)0;
return;
}
*size = length; (8)
cnt = length / pdev_cfg->DataBusSizeNbrBits; (9)
for (i = 0; i < cnt; i++) {
Read data from device using Memcopy. (10)
}
*p_data = pbuf_new; (11)
*perr = NET_DEV_ERR_NONE;
}(1) Obtain pointer to the device configuration structure.
(2) Obtain pointer to device data area.
(3) Overlay device register structure on top of device base address.
(4) If the frame contains reception errors, discard the frame by setting *size to 0, *p_data to null. Set *perr to NET_DEV_ERR_RX to indicate a reception error.
(5) If frame is a runt, discard the frame.
(6) Request an empty buffer.
(7) If unable to get a buffer, discard the frame.
(8) Return the size of the received frame.
(9) Determine the number of device memory or FIFO reads that are required to complete the memory copy.
(10) Read data from device.
(11) Return a pointer to the received data.
Transmission using Memory Copy
The following a list of the actions that must be done in NetDev_Tx() in order to implement transmission using Memory Copy:
Disable interrupts.
Prepare device to receive the transmit frame in memory.
Copy frame to transmit to MAC buffer.
If no frames are queued for transmission, issue a transmission request to the MAC.
Update the device’s list of transmit pointers
Re-enable interrupts
The listing below shows a template for the NetDev_Tx() function:
Listing - NetDev_Tx() function template
static void NetDev_Tx (NET_IF *pif,
CPU_INT08U *p_data,
CPU_INT16U size,
NET_ERR *perr)
{
NET_DEV_CFG_ETHER *pdev_cfg;
NET_DEV_DATA *pdev_data;
NET_DEV *pdev;
CPU_INT16U cnt;
CPU_INT16U i;
pdev_cfg = (NET_DEV_CFG_ETHER *)pif->Dev_Cfg; (1)
pdev_data = (NET_DEV_DATA *)pif->Dev_Data; (2)
pdev = (NET_DEV *)pdev_cfg->BaseAddr; (3)
if ((pdev->STATUS & TX_STATUS_BUSY) > 0) { (4)
*perr = NET_DEV_ERR_TX_BUSY;
return;
}
cnt = size / pdev_cfg->DataBusSizeNbrBits; (5)
for (i = 0; i < cnt; i++) {
Copy data to device using Memcopy (6)
}
pdev->CTRL = 1; (7)
pdev_data->TxBufCompPtr = p_data;
}The following is a list of actions that must be performed in NetDev_ISR_Handler() to transmit packets using Memory Copy.
(1) Obtain pointer to the device configuration structure.
(2) Obtain pointer to device data area.
(3) Overlay device register structure on top of the device base address.
(4) Check if the device is ready to transmit.
(5) Determine the number of device memory or FIFO writes that are required to complete the transfer.
(6) Copy data to device using memory copy.
(7) Initiate transmission of the packet.
Processing transmission buffer in the ISR
Setup next frame to transmit if any
Signal already transmitted frame for deallocation
Signal that Transmit resources have become available
Clear interrupt
For the template of NetDev_ISR_Handler() refer to the template in the listing above.