mirror of
https://github.com/espressif/esp-idf.git
synced 2025-11-03 00:21:44 +01:00
ethernet: optimise tx and rx
This commit is contained in:
@@ -438,11 +438,12 @@ uint32_t emac_hal_get_tx_desc_owner(emac_hal_context_t *hal)
|
||||
return hal->tx_desc->TDES0.Own;
|
||||
}
|
||||
|
||||
void emac_hal_transmit_frame(emac_hal_context_t *hal, uint8_t *buf, uint32_t length)
|
||||
uint32_t emac_hal_transmit_frame(emac_hal_context_t *hal, uint8_t *buf, uint32_t length)
|
||||
{
|
||||
/* Get the number of Tx buffers to use for the frame */
|
||||
uint32_t bufcount = 0;
|
||||
uint32_t lastlen = length;
|
||||
uint32_t sentout = 0;
|
||||
while (lastlen > CONFIG_ETH_DMA_BUFFER_SIZE) {
|
||||
lastlen -= CONFIG_ETH_DMA_BUFFER_SIZE;
|
||||
bufcount++;
|
||||
@@ -452,6 +453,10 @@ void emac_hal_transmit_frame(emac_hal_context_t *hal, uint8_t *buf, uint32_t len
|
||||
}
|
||||
/* A frame is transmitted in multiple descriptor */
|
||||
for (uint32_t i = 0; i < bufcount; i++) {
|
||||
/* Check if the descriptor is owned by the Ethernet DMA (when 1) or CPU (when 0) */
|
||||
if (hal->tx_desc->TDES0.Own != EMAC_DMADESC_OWNER_CPU) {
|
||||
goto err;
|
||||
}
|
||||
/* Clear FIRST and LAST segment bits */
|
||||
hal->tx_desc->TDES0.FirstSegment = 0;
|
||||
hal->tx_desc->TDES0.LastSegment = 0;
|
||||
@@ -468,18 +473,22 @@ void emac_hal_transmit_frame(emac_hal_context_t *hal, uint8_t *buf, uint32_t len
|
||||
hal->tx_desc->TDES1.TransmitBuffer1Size = lastlen;
|
||||
/* copy data from uplayer stack buffer */
|
||||
memcpy((void *)(hal->tx_desc->Buffer1Addr), buf + i * CONFIG_ETH_DMA_BUFFER_SIZE, lastlen);
|
||||
sentout += lastlen;
|
||||
} else {
|
||||
/* Program size */
|
||||
hal->tx_desc->TDES1.TransmitBuffer1Size = CONFIG_ETH_DMA_BUFFER_SIZE;
|
||||
/* copy data from uplayer stack buffer */
|
||||
memcpy((void *)(hal->tx_desc->Buffer1Addr), buf + i * CONFIG_ETH_DMA_BUFFER_SIZE, CONFIG_ETH_DMA_BUFFER_SIZE);
|
||||
sentout += CONFIG_ETH_DMA_BUFFER_SIZE;
|
||||
}
|
||||
/* Set Own bit of the Tx descriptor Status: gives the buffer back to ETHERNET DMA */
|
||||
hal->tx_desc->TDES0.Own = EMAC_DMADESC_OWNER_DMA;
|
||||
/* Point to next descriptor */
|
||||
hal->tx_desc = (eth_dma_tx_descriptor_t *)(hal->tx_desc->Buffer2NextDescAddr);
|
||||
}
|
||||
err:
|
||||
hal->dma_regs->dmatxpolldemand = 0;
|
||||
return sentout;
|
||||
}
|
||||
|
||||
uint32_t emac_hal_receive_frame(emac_hal_context_t *hal, uint8_t *buf, uint32_t size, uint32_t *frames_remain)
|
||||
@@ -488,7 +497,9 @@ uint32_t emac_hal_receive_frame(emac_hal_context_t *hal, uint8_t *buf, uint32_t
|
||||
eth_dma_rx_descriptor_t *first_desc = NULL;
|
||||
uint32_t iter = 0;
|
||||
uint32_t seg_count = 0;
|
||||
uint32_t len = 0;
|
||||
uint32_t ret_len = 0;
|
||||
uint32_t copy_len = 0;
|
||||
uint32_t write_len = 0;
|
||||
uint32_t frame_count = 0;
|
||||
|
||||
first_desc = hal->rx_desc;
|
||||
@@ -500,13 +511,9 @@ uint32_t emac_hal_receive_frame(emac_hal_context_t *hal, uint8_t *buf, uint32_t
|
||||
/* Last segment in frame */
|
||||
if (desc_iter->RDES0.LastDescriptor) {
|
||||
/* Get the Frame Length of the received packet: substruct 4 bytes of the CRC */
|
||||
len = desc_iter->RDES0.FrameLength - ETH_CRC_LENGTH;
|
||||
/* check if the buffer can store the whole frame */
|
||||
if (len > size) {
|
||||
/* return the real size that we want */
|
||||
/* user need to compare the return value to the size they prepared when this function returned */
|
||||
return len;
|
||||
}
|
||||
ret_len = desc_iter->RDES0.FrameLength - ETH_CRC_LENGTH;
|
||||
/* packets larger than expected will be truncated */
|
||||
copy_len = ret_len > size ? size : ret_len;
|
||||
/* update unhandled frame count */
|
||||
frame_count++;
|
||||
}
|
||||
@@ -530,15 +537,16 @@ uint32_t emac_hal_receive_frame(emac_hal_context_t *hal, uint8_t *buf, uint32_t
|
||||
}
|
||||
desc_iter = first_desc;
|
||||
for (iter = 0; iter < seg_count - 1; iter++) {
|
||||
write_len = copy_len < CONFIG_ETH_DMA_BUFFER_SIZE ? copy_len : CONFIG_ETH_DMA_BUFFER_SIZE;
|
||||
/* copy data to buffer */
|
||||
memcpy(buf + iter * CONFIG_ETH_DMA_BUFFER_SIZE,
|
||||
(void *)(desc_iter->Buffer1Addr), CONFIG_ETH_DMA_BUFFER_SIZE);
|
||||
memcpy(buf, (void *)(desc_iter->Buffer1Addr), write_len);
|
||||
buf += write_len;
|
||||
copy_len -= write_len;
|
||||
/* Set Own bit in Rx descriptors: gives the buffers back to DMA */
|
||||
desc_iter->RDES0.Own = EMAC_DMADESC_OWNER_DMA;
|
||||
desc_iter = (eth_dma_rx_descriptor_t *)(desc_iter->Buffer2NextDescAddr);
|
||||
}
|
||||
memcpy(buf + iter * CONFIG_ETH_DMA_BUFFER_SIZE,
|
||||
(void *)(desc_iter->Buffer1Addr), len % CONFIG_ETH_DMA_BUFFER_SIZE);
|
||||
memcpy(buf, (void *)(desc_iter->Buffer1Addr), copy_len);
|
||||
desc_iter->RDES0.Own = EMAC_DMADESC_OWNER_DMA;
|
||||
/* update rxdesc */
|
||||
hal->rx_desc = (eth_dma_rx_descriptor_t *)(desc_iter->Buffer2NextDescAddr);
|
||||
@@ -547,7 +555,7 @@ uint32_t emac_hal_receive_frame(emac_hal_context_t *hal, uint8_t *buf, uint32_t
|
||||
frame_count--;
|
||||
}
|
||||
*frames_remain = frame_count;
|
||||
return len;
|
||||
return ret_len;
|
||||
}
|
||||
|
||||
IRAM_ATTR void emac_hal_isr(void *arg)
|
||||
|
||||
@@ -242,6 +242,8 @@ typedef struct {
|
||||
#define EMAC_DMATXDESC_CHECKSUM_TCPUDPICMPSEGMENT 2 /*!< TCP/UDP/ICMP Checksum Insertion calculated over segment only */
|
||||
#define EMAC_DMATXDESC_CHECKSUM_TCPUDPICMPFULL 3 /*!< TCP/UDP/ICMP Checksum Insertion fully calculated */
|
||||
|
||||
_Static_assert(sizeof(eth_dma_tx_descriptor_t) == 32, "eth_dma_tx_descriptor_t should occupy 32 bytes in memory");
|
||||
|
||||
/**
|
||||
* @brief Ethernet DMA RX Descriptor
|
||||
*
|
||||
@@ -328,6 +330,8 @@ typedef struct {
|
||||
#define EMAC_DMADESC_OWNER_CPU (0)
|
||||
#define EMAC_DMADESC_OWNER_DMA (1)
|
||||
|
||||
_Static_assert(sizeof(eth_dma_rx_descriptor_t) == 32, "eth_dma_rx_descriptor_t should occupy 32 bytes in memory");
|
||||
|
||||
typedef struct {
|
||||
emac_mac_dev_t *mac_regs;
|
||||
emac_dma_dev_t *dma_regs;
|
||||
@@ -378,7 +382,7 @@ void emac_hal_stop(emac_hal_context_t *hal);
|
||||
|
||||
uint32_t emac_hal_get_tx_desc_owner(emac_hal_context_t *hal);
|
||||
|
||||
void emac_hal_transmit_frame(emac_hal_context_t *hal, uint8_t *buf, uint32_t length);
|
||||
uint32_t emac_hal_transmit_frame(emac_hal_context_t *hal, uint8_t *buf, uint32_t length);
|
||||
|
||||
uint32_t emac_hal_receive_frame(emac_hal_context_t *hal, uint8_t *buf, uint32_t size, uint32_t *frames_remain);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user