예제 #1
0
파일: eth.c 프로젝트: 0xBADCA7/lk
static status_t eth_send(const void *buf, size_t len)
{
    status_t err;
    __IO ETH_DMADescTypeDef *DmaTxDesc;

    LTRACEF("buf %p, len %zu\n", buf, len);

    DmaTxDesc = eth.EthHandle.TxDesc;

    /* is the buffer available? */
    if ((DmaTxDesc->Status & ETH_DMATXDESC_OWN) != 0) {
        LTRACEF("tx buffer not available\n");
        err = ERR_IO;
        goto error;
    }

    uint8_t *buffer = (uint8_t *)(DmaTxDesc->Buffer1Addr);
    memcpy(buffer, buf, len);

    HAL_StatusTypeDef e = HAL_ETH_TransmitFrame(&eth.EthHandle, len);

    err = (e == HAL_OK) ? NO_ERROR : ERR_IO;

error:
    /* When Transmit Underflow flag is set, clear it and issue a Transmit Poll Demand to resume transmission */
    if ((eth.EthHandle.Instance->DMASR & ETH_DMASR_TUS) != 0) {
        /* Clear TUS ETHERNET DMA flag */
        eth.EthHandle.Instance->DMASR = ETH_DMASR_TUS;

        /* Resume DMA transmission*/
        eth.EthHandle.Instance->DMATPDR = 0;
    }

    return err;
}
예제 #2
0
/**
 * @brief This function should do the actual transmission of the packet. The packet is
 * contained in the pbuf that is passed to the function. This pbuf
 * might be chained.
 *
 * @param netif the lwip network interface structure for this ethernetif
 * @param p the MAC packet to send (e.g. IP packet including MAC addresses and type)
 * @return ERR_OK if the packet could be sent
 *         an err_t value if the packet couldn't be sent
 *
 * @note Returning ERR_MEM here if a DMA queue of your MAC is full can lead to
 *       strange results. You might consider waiting for space in the DMA queue
 *       to become available since the stack doesn't retry to send a packet
 *       dropped because of memory failure (except for the TCP timers).
 */
static err_t low_level_output(
  struct netif *netif,
  struct pbuf  *p
)
{
  err_t        errval;
  struct pbuf *q;
  uint8_t     *buffer =
    (uint8_t *) ( EthHandle.TxDesc->Buffer1Addr );
  __IO ETH_DMADescTypeDef *DmaTxDesc;
  uint32_t                 framelength = 0;
  uint32_t                 bufferoffset = 0;
  uint32_t                 byteslefttocopy = 0;
  uint32_t                 payloadoffset = 0;

  DmaTxDesc = EthHandle.TxDesc;
  bufferoffset = 0;

  /* copy frame from pbufs to driver buffers */
  for ( q = p; q != NULL; q = q->next ) {
    /* Is this buffer available? If not, goto error */
    if ( ( DmaTxDesc->Status & ETH_DMATXDESC_OWN ) != (uint32_t) RESET ) {
      errval = ERR_USE;
      goto error;
    }

    /* Get bytes in current lwIP buffer */
    byteslefttocopy = q->len;
    payloadoffset = 0;

    /* Check if the length of data to copy is bigger than Tx buffer size*/
    while ( ( byteslefttocopy + bufferoffset ) > ETH_TX_BUF_SIZE ) {
      /* Copy data to Tx buffer*/
      memcpy( (uint8_t *) ( (uint8_t *) buffer + bufferoffset ),
        (uint8_t *) ( (uint8_t *) q->payload + payloadoffset ),
        ( ETH_TX_BUF_SIZE - bufferoffset ) );

      /* Point to next descriptor */
      DmaTxDesc = (ETH_DMADescTypeDef *) ( DmaTxDesc->Buffer2NextDescAddr );

      /* Check if the buffer is available */
      if ( ( DmaTxDesc->Status & ETH_DMATXDESC_OWN ) != (uint32_t) RESET ) {
        errval = ERR_USE;
        goto error;
      }

      buffer = (uint8_t *) ( DmaTxDesc->Buffer1Addr );

      byteslefttocopy = byteslefttocopy - ( ETH_TX_BUF_SIZE - bufferoffset );
      payloadoffset = payloadoffset + ( ETH_TX_BUF_SIZE - bufferoffset );
      framelength = framelength + ( ETH_TX_BUF_SIZE - bufferoffset );
      bufferoffset = 0;
    }

    /* Copy the remaining bytes */
    memcpy( (uint8_t *) ( (uint8_t *) buffer + bufferoffset ),
      (uint8_t *) ( (uint8_t *) q->payload + payloadoffset ),
      byteslefttocopy );
    bufferoffset = bufferoffset + byteslefttocopy;
    framelength = framelength + byteslefttocopy;
  }

  /* Prepare transmit descriptors to give to DMA */
  HAL_ETH_TransmitFrame( &EthHandle, framelength );
  num_ethernet_tx_msg++;

  errval = ERR_OK;

error:

  /* When Transmit Underflow flag is set, clear it and issue a Transmit Poll Demand to resume transmission */
  if ( ( EthHandle.Instance->DMASR & ETH_DMASR_TUS ) != (uint32_t) RESET ) {
    /* Clear TUS ETHERNET DMA flag */
    EthHandle.Instance->DMASR = ETH_DMASR_TUS;

    /* Resume DMA transmission*/
    EthHandle.Instance->DMATPDR = 0;
  }

  return errval;
}
BaseType_t xNetworkInterfaceOutput(
xNetworkBufferDescriptor_t * const pxDescriptor, BaseType_t xReleaseAfterSend) {

	uint8_t *buffer = (uint8_t *) (heth_global.TxDesc->Buffer1Addr);
	__IO ETH_DMADescTypeDef *DmaTxDesc;
	uint32_t framelength = 0;
	uint32_t byteslefttocopy = 0;
	uint32_t payloadoffset = 0;
	DmaTxDesc = heth_global.TxDesc;

	uint8_t errval;

	/* copy frame from pbufs to driver buffers */

	/* Is this buffer available? If not, goto error */
	if ((DmaTxDesc->Status & ETH_DMATXDESC_OWN) != (uint32_t) RESET) {
		errval = pdFAIL;
		goto error;
	}

#if( ipconfigDRIVER_INCLUDED_TX_IP_CHECKSUM != 0 )
	{
		ProtocolPacket_t *pxPacket;

		/* If the peripheral must calculate the checksum, it wants
		 the protocol checksum to have a value of zero. */
		pxPacket = (ProtocolPacket_t *) (pxDescriptor->pucEthernetBuffer);

		if (pxPacket->xICMPPacket.xIPHeader.ucProtocol == ipPROTOCOL_ICMP) {
			pxPacket->xICMPPacket.xICMPHeader.usChecksum = (uint16_t) 0u;
		}
	}
#endif

	/* Get bytes in current lwIP buffer */
	byteslefttocopy = pxDescriptor->xDataLength;
	framelength = byteslefttocopy; // copy of frame length
	payloadoffset = 0;

	/* Check if the length of data to copy is bigger than Tx buffer size*/
	while ((byteslefttocopy) > ETH_TX_BUF_SIZE) {
		/* Copy data to Tx buffer*/
		memcpy((uint8_t*) ((uint8_t*) buffer),
				(uint8_t*) ((uint8_t*) pxDescriptor->pucEthernetBuffer + payloadoffset),
				(ETH_TX_BUF_SIZE));

		/* Point to next descriptor */
		DmaTxDesc = (ETH_DMADescTypeDef *) (DmaTxDesc->Buffer2NextDescAddr);

		/* Check if the buffer is available */
		if ((DmaTxDesc->Status & ETH_DMATXDESC_OWN) != (uint32_t) RESET) {
			errval = pdFAIL;
			goto error;
		}

		// memcpy( (uint8_t*)((uint8_t*)buffer), (uint8_t*)((uint8_t*)pxDescriptor->pucEthernetBuffer + payloadoffset), byteslefttocopy );
		buffer = (uint8_t *) (DmaTxDesc->Buffer1Addr);

		byteslefttocopy -= (ETH_TX_BUF_SIZE);
		payloadoffset += (ETH_TX_BUF_SIZE);

	}

	/* Copy the remaining bytes */
	memcpy((uint8_t*) ((uint8_t*) buffer),
			(uint8_t*) ((uint8_t*) pxDescriptor->pucEthernetBuffer + payloadoffset),
			byteslefttocopy);

	/* Prepare transmit descriptors to give to DMA */
	HAL_ETH_TransmitFrame(&heth_global, framelength);

	gdb.monit.tx_eth_frames++;

	/* Call the standard trace macro to log the send event. */
	iptraceNETWORK_INTERFACE_TRANSMIT();

	errval = pdPASS;

	error:

	if (xReleaseAfterSend != pdFALSE) {
		/* It is assumed SendData() copies the data out of the FreeRTOS+TCP Ethernet
		 buffer.  The Ethernet buffer is therefore no longer needed, and must be
		 freed for re-use. */
		vReleaseNetworkBufferAndDescriptor(pxDescriptor);
	}

	/* When Transmit Underflow flag is set, clear it and issue a Transmit Poll Demand to resume transmission */
	if ((heth_global.Instance->DMASR & ETH_DMASR_TUS) != (uint32_t) RESET) {
		/* Clear TUS ETHERNET DMA flag */
		heth_global.Instance->DMASR = ETH_DMASR_TUS;

		/* Resume DMA transmission*/
		heth_global.Instance->DMATPDR = 0;
	}

	return errval;

}