修改的代码
只需要修改stm32h7xx_hal_eth.c的代码
发送的修改
发送相关的有三个函数被修改
static uint32_t ETH_Prepare_Tx_Descriptors(ETH_HandleTypeDef *heth, ETH_TxPacketConfig *pTxConfig, uint32_t ItMode)
{
ETH_TxDescListTypeDef *dmatxdesclist = &heth->TxDescList;
uint32_t descidx = dmatxdesclist->CurTxDesc;
uint32_t firstdescidx = dmatxdesclist->CurTxDesc;
uint32_t descnbr = 0, idx;
ETH_DMADescTypeDef *dmatxdesc = (ETH_DMADescTypeDef *)dmatxdesclist->TxDesc[descidx];
ETH_BufferTypeDef *txbuffer = pTxConfig->TxBuffer;
uint32_t bd_count = 0;
/* Current Tx Descriptor Owned by DMA: cannot be used by the application */
if((READ_BIT(dmatxdesc->DESC3, ETH_DMATXNDESCWBF_OWN) == ETH_DMATXNDESCWBF_OWN) || (dmatxdesclist->PacketAddress[descidx] != NULL))
{
return HAL_ETH_ERROR_BUSY;
}
/***************************************************************************/
/***************** Context descriptor configuration (Optional) **********/
/***************************************************************************/
/* If VLAN tag is enabled for this packet */
if(READ_BIT(pTxConfig->Attributes, ETH_TX_PACKETS_FEATURES_VLANTAG) != 0U)
{
/* Set vlan tag value */
MODIFY_REG(dmatxdesc->DESC3, ETH_DMATXCDESC_VT, pTxConfig->VlanTag);
/* Set vlan tag valid bit */
SET_BIT(dmatxdesc->DESC3, ETH_DMATXCDESC_VLTV);
/* Set the descriptor as the vlan input source */
SET_BIT(heth->Instance->MACVIR, ETH_MACVIR_VLTI);
/* if inner VLAN is enabled */
if(READ_BIT(pTxConfig->Attributes, ETH_TX_PACKETS_FEATURES_INNERVLANTAG) != 0U)
{
/* Set inner vlan tag value */
MODIFY_REG(dmatxdesc->DESC2, ETH_DMATXCDESC_IVT, (pTxConfig->InnerVlanTag << 16));
/* Set inner vlan tag valid bit */
SET_BIT(dmatxdesc->DESC3, ETH_DMATXCDESC_IVLTV);
/* Set Vlan Tag control */
MODIFY_REG(dmatxdesc->DESC3, ETH_DMATXCDESC_IVTIR, pTxConfig->InnerVlanCtrl);
/* Set the descriptor as the inner vlan input source */
SET_BIT(heth->Instance->MACIVIR, ETH_MACIVIR_VLTI);
/* Enable double VLAN processing */
SET_BIT(heth->Instance->MACVTR, ETH_MACVTR_EDVLP);
}
}
/* if tcp segmentation is enabled for this packet */
if(READ_BIT(pTxConfig->Attributes, ETH_TX_PACKETS_FEATURES_TSO) != 0U)
{
/* Set MSS value */
MODIFY_REG(dmatxdesc->DESC2, ETH_DMATXCDESC_MSS, pTxConfig->MaxSegmentSize);
/* Set MSS valid bit */
SET_BIT(dmatxdesc->DESC3, ETH_DMATXCDESC_TCMSSV);
}
if((READ_BIT(pTxConfig->Attributes, ETH_TX_PACKETS_FEATURES_VLANTAG) != 0U)|| (READ_BIT(pTxConfig->Attributes, ETH_TX_PACKETS_FEATURES_TSO) != 0U))
{
/* Set as context descriptor */
SET_BIT(dmatxdesc->DESC3, ETH_DMATXCDESC_CTXT);
/* Set own bit */
SET_BIT(dmatxdesc->DESC3, ETH_DMATXCDESC_OWN);
/* Increment current tx descriptor index */
INCR_TX_DESC_INDEX(descidx, 1U);
/* Get current descriptor address */
dmatxdesc = (ETH_DMADescTypeDef *)dmatxdesclist->TxDesc[descidx];
descnbr += 1U;
/* Current Tx Descriptor Owned by DMA: cannot be used by the application */
if(READ_BIT(dmatxdesc->DESC3, ETH_DMATXNDESCWBF_OWN) == ETH_DMATXNDESCWBF_OWN)
{
dmatxdesc = (ETH_DMADescTypeDef *)dmatxdesclist->TxDesc[firstdescidx];
/* Clear own bit */
CLEAR_BIT(dmatxdesc->DESC3, ETH_DMATXCDESC_OWN);
return HAL_ETH_ERROR_BUSY;
}
}
/***************************************************************************/
/***************** Normal descriptors configuration *****************/
/***************************************************************************/
descnbr += 1U;
/* Set header or buffer 1 address */
WRITE_REG(dmatxdesc->DESC0, (uint32_t)txbuffer->buffer);
/* Set header or buffer 1 Length */
MODIFY_REG(dmatxdesc->DESC2, ETH_DMATXNDESCRF_B1L, txbuffer->len);
if(txbuffer->next != NULL)
{
txbuffer = txbuffer->next;
/* Set buffer 2 address */
WRITE_REG(dmatxdesc->DESC1, (uint32_t)txbuffer->buffer);
/* Set buffer 2 Length */
MODIFY_REG(dmatxdesc->DESC2, ETH_DMATXNDESCRF_B2L, (txbuffer->len << 16));
}
else
{
WRITE_REG(dmatxdesc->DESC1, 0x0);
/* Set buffer 2 Length */
MODIFY_REG(dmatxdesc->DESC2, ETH_DMATXNDESCRF_B2L, 0x0U);
}
if(READ_BIT(pTxConfig->Attributes, ETH_TX_PACKETS_FEATURES_TSO) != 0U)
{
/* Set TCP Header length */
MODIFY_REG(dmatxdesc->DESC3, ETH_DMATXNDESCRF_THL, (pTxConfig->TCPHeaderLen << 19));
/* Set TCP payload length */
MODIFY_REG(dmatxdesc->DESC3, ETH_DMATXNDESCRF_TPL, pTxConfig->PayloadLen);
/* Set TCP Segmentation Enabled bit */
SET_BIT(dmatxdesc->DESC3, ETH_DMATXNDESCRF_TSE);
}
else
{
MODIFY_REG(dmatxdesc->DESC3, ETH_DMATXNDESCRF_FL, pTxConfig->Length);
if(READ_BIT(pTxConfig->Attributes, ETH_TX_PACKETS_FEATURES_CSUM) != 0U)
{
MODIFY_REG(dmatxdesc->DESC3, ETH_DMATXNDESCRF_CIC, pTxConfig->ChecksumCtrl);
}
if(READ_BIT(pTxConfig->Attributes, ETH_TX_PACKETS_FEATURES_CRCPAD) != 0U)
{
MODIFY_REG(dmatxdesc->DESC3, ETH_DMATXNDESCRF_CPC, pTxConfig->CRCPadCtrl);
}
}
if(READ_BIT(pTxConfig->Attributes, ETH_TX_PACKETS_FEATURES_VLANTAG) != 0U)
{
/* Set Vlan Tag control */
MODIFY_REG(dmatxdesc->DESC2, ETH_DMATXNDESCRF_VTIR, pTxConfig->VlanCtrl);
}
/* Mark it as First Descriptor */
SET_BIT(dmatxdesc->DESC3, ETH_DMATXNDESCRF_FD);
/* Mark it as NORMAL descriptor */
CLEAR_BIT(dmatxdesc->DESC3, ETH_DMATXNDESCRF_CTXT);
/* If source address insertion/replacement is enabled for this packet */
if(READ_BIT(pTxConfig->Attributes, ETH_TX_PACKETS_FEATURES_SAIC) != 0U)
{
MODIFY_REG(dmatxdesc->DESC3, ETH_DMATXNDESCRF_SAIC, pTxConfig->SrcAddrCtrl);
}
/* only if the packet is split into more than one descriptors > 1 */
while (txbuffer->next != NULL)
{
/* Clear the LD bit of previous descriptor */
CLEAR_BIT(dmatxdesc->DESC3, ETH_DMATXNDESCRF_LD);
__DMB();//修改!!
/* set OWN bit of Last descriptor */
SET_BIT(dmatxdesc->DESC3, ETH_DMATXNDESCRF_OWN);
__DMB();//修改!!
/* Increment current tx descriptor index */
INCR_TX_DESC_INDEX(descidx, 1U);
/* Get current descriptor address */
dmatxdesc = (ETH_DMADescTypeDef *)dmatxdesclist->TxDesc[descidx];
/* Clear the FD bit of new Descriptor */
CLEAR_BIT(dmatxdesc->DESC3, ETH_DMATXNDESCRF_FD);
/* Current Tx Descriptor Owned by DMA: cannot be used by the application */
if((READ_BIT(dmatxdesc->DESC3, ETH_DMATXNDESCRF_OWN) == ETH_DMATXNDESCRF_OWN) || (dmatxdesclist->PacketAddress[descidx] != NULL))
{
descidx = firstdescidx;
dmatxdesc = (ETH_DMADescTypeDef *)dmatxdesclist->TxDesc[descidx];
/* clear previous desc own bit */
for(idx = 0; idx < descnbr; idx ++)
{
__DMB();//修改!!
CLEAR_BIT(dmatxdesc->DESC3, ETH_DMATXNDESCRF_OWN);
__DMB();//修改!!
/* Increment current tx descriptor index */
INCR_TX_DESC_INDEX(descidx, 1U);
/* Get current descriptor address */
dmatxdesc = (ETH_DMADescTypeDef *)dmatxdesclist->TxDesc[descidx];
}
return HAL_ETH_ERROR_BUSY;
}
descnbr += 1U;
/* Get the next Tx buffer in the list */
txbuffer = txbuffer->next;
/* Set header or buffer 1 address */
WRITE_REG(dmatxdesc->DESC0, (uint32_t)txbuffer->buffer);
/* Set header or buffer 1 Length */
MODIFY_REG(dmatxdesc->DESC2, ETH_DMATXNDESCRF_B1L, txbuffer->len);
if (txbuffer->next != NULL)
{
/* Get the next Tx buffer in the list */
txbuffer = txbuffer->next;
/* Set buffer 2 address */
WRITE_REG(dmatxdesc->DESC1, (uint32_t)txbuffer->buffer);
/* Set buffer 2 Length */
MODIFY_REG(dmatxdesc->DESC2, ETH_DMATXNDESCRF_B2L, (txbuffer->len << 16));
}
else
{
WRITE_REG(dmatxdesc->DESC1, 0x0);
/* Set buffer 2 Length */
MODIFY_REG(dmatxdesc->DESC2, ETH_DMATXNDESCRF_B2L, 0x0U);
}
if(READ_BIT(pTxConfig->Attributes, ETH_TX_PACKETS_FEATURES_TSO) != 0U)
{
/* Set TCP payload length */
MODIFY_REG(dmatxdesc->DESC3, ETH_DMATXNDESCRF_TPL, pTxConfig->PayloadLen);
/* Set TCP Segmentation Enabled bit */
SET_BIT(dmatxdesc->DESC3, ETH_DMATXNDESCRF_TSE);
}
else
{
/* Set the packet length */
MODIFY_REG(dmatxdesc->DESC3, ETH_DMATXNDESCRF_FL, pTxConfig->Length);
if(READ_BIT(pTxConfig->Attributes, ETH_TX_PACKETS_FEATURES_CSUM) != 0U)
{
/* Checksum Insertion Control */
MODIFY_REG(dmatxdesc->DESC3, ETH_DMATXNDESCRF_CIC, pTxConfig->ChecksumCtrl);
}
}
bd_count += 1U;
/* Mark it as NORMAL descriptor */
CLEAR_BIT(dmatxdesc->DESC3, ETH_DMATXNDESCRF_CTXT);
}
if(ItMode != ((uint32_t)RESET))
{
/* Set Interrupt on completion bit */
SET_BIT(dmatxdesc->DESC2, ETH_DMATXNDESCRF_IOC);
}
else
{
/* Clear Interrupt on completion bit */
CLEAR_BIT(dmatxdesc->DESC2, ETH_DMATXNDESCRF_IOC);
}
/* Mark it as LAST descriptor */
SET_BIT(dmatxdesc->DESC3, ETH_DMATXNDESCRF_LD);
__DMB();//修改!!
/* Set Own bit For End Desc */
SET_BIT(dmatxdesc->DESC3, ETH_DMATXNDESCRF_OWN);
/* Save the current packet address to expose it to the application */
dmatxdesclist->PacketAddress[descidx] = dmatxdesclist->CurrentPacketAddress;
dmatxdesclist->CurTxDesc = descidx;
/* disable the interrupt */
//__disable_irq();
//我最看不惯的就是关中断!!
//dmatxdesclist->BuffersInUse += bd_count + 1U;
/* Enable interrupts back */
//__enable_irq();
/* Return function status */
return HAL_ETH_ERROR_NONE;
}
HAL_StatusTypeDef HAL_ETH_Transmit(ETH_HandleTypeDef *heth, ETH_TxPacketConfig *pTxConfig, uint32_t Timeout)
{
uint32_t tickstart;
const ETH_DMADescTypeDef *dmatxdesc;
if(pTxConfig == NULL)
{
heth->ErrorCode |= HAL_ETH_ERROR_PARAM;
return HAL_ERROR;
}
if(heth->gState == HAL_ETH_STATE_READY)
{
/* Config DMA Tx descriptor by Tx Packet info */
if (ETH_Prepare_Tx_Descriptors(heth, pTxConfig, 0) != HAL_ETH_ERROR_NONE)
{
/* Set the ETH error code */
heth->ErrorCode |= HAL_ETH_ERROR_BUSY;
return HAL_ERROR;
}
dmatxdesc = (ETH_DMADescTypeDef *)(&heth->TxDescList)->TxDesc[heth->TxDescList.CurTxDesc];
/* Incr current tx desc index */
INCR_TX_DESC_INDEX(heth->TxDescList.CurTxDesc, 1U);
/* Start transmission */
/* issue a poll command to Tx DMA by writing address of next immediate free descriptor */
//WRITE_REG(heth->Instance->DMACTDTPR, (uint32_t)(heth->TxDescList.TxDesc[heth->TxDescList.CurTxDesc]));
__DMB();//修改!!
WRITE_REG(heth->Instance->DMACTDTPR, ((uint32_t)(heth->Init.TxDesc + (uint32_t)(ETH_TX_DESC_CNT - 1))));
tickstart = HAL_GetTick();
/* Wait for data to be transmitted or timeout occurred */
while((dmatxdesc->DESC3 & ETH_DMATXNDESCWBF_OWN) != (uint32_t)RESET)
{
if((heth->Instance->DMACSR & ETH_DMACSR_FBE) != (uint32_t)RESET)
{
heth->ErrorCode |= HAL_ETH_ERROR_DMA;
heth->DMAErrorCode = heth->Instance->DMACSR;
/* Set ETH HAL State to Ready */
heth->gState = HAL_ETH_STATE_ERROR;
/* Return function status */
return HAL_ERROR;
}
/* Check for the Timeout */
if(Timeout != HAL_MAX_DELAY)
{
if(((HAL_GetTick() - tickstart ) > Timeout) || (Timeout == 0U))
{
heth->ErrorCode |= HAL_ETH_ERROR_TIMEOUT;
heth->gState = HAL_ETH_STATE_ERROR;
return HAL_ERROR;
}
}
}
/* Return function status */
return HAL_OK;
}
else
{
return HAL_ERROR;
}
}
/**
* @brief Sends an Ethernet Packet in interrupt mode.
* @param heth: pointer to a ETH_HandleTypeDef structure that contains
* the configuration information for ETHERNET module
* @param pTxConfig: Hold the configuration of packet to be transmitted
* @retval HAL status
*/
HAL_StatusTypeDef HAL_ETH_Transmit_IT(ETH_HandleTypeDef *heth, ETH_TxPacketConfig *pTxConfig)
{
if(pTxConfig == NULL)
{
heth->ErrorCode |= HAL_ETH_ERROR_PARAM;
return HAL_ERROR;
}
if(heth->gState == HAL_ETH_STATE_READY)
{
/* Config DMA Tx descriptor by Tx Packet info */
if (ETH_Prepare_Tx_Descriptors(heth, pTxConfig, 1) != HAL_ETH_ERROR_NONE)
{
heth->ErrorCode |= HAL_ETH_ERROR_BUSY;
return HAL_ERROR;
}
/* Incr current tx desc index */
INCR_TX_DESC_INDEX(heth->TxDescList.CurTxDesc, 1U);
__DMB();//修改!!
/* Start transmission */
/* issue a poll command to Tx DMA by writing address of next immediate free descriptor */
//WRITE_REG(heth->Instance->DMACTDTPR, (uint32_t)(heth->TxDescList.TxDesc[heth->TxDescList.CurTxDesc]));
WRITE_REG(heth->Instance->DMACTDTPR, (uint32_t)(heth->TxDescList.TxDesc[ETH_TX_DESC_CNT-1]));
return HAL_OK;
}
else
{
return HAL_ERROR;
}
}
|