cancel
Showing results for 
Search instead for 
Did you mean: 

nx_tcp_socket_send Cannot send continuously in while

Hhaon.1
Associate II
 while(1)
  {
    TX_MEMSET(data_buffer, '\0', sizeof(data_buffer));
    
    /* allocate the packet to send over the TCP socket */
    ret = nx_packet_allocate(&AppPool, &data_packet, NX_IPv4_TCP_PACKET, TX_WAIT_FOREVER);
 
    if (ret != NX_SUCCESS)
    {
    	printf("aaaa1\r\n");
      break;
    }
 
    /* append the message to send into the packet */
    ret = nx_packet_data_append(data_packet, (VOID *)data_buffer, sizeof(data_buffer), &AppPool, TX_WAIT_FOREVER);
 
    if (ret != NX_SUCCESS)
    {
    	printf("aaaa2\r\n");
     // nx_packet_release(data_packet);
      break;
    }
 
   
    ret = nx_tcp_socket_send(&TCPSocket, data_packet, 30000 );
 
    if (ret != NX_SUCCESS)
    {
    	printf("tcp send error:%#x\r\n",ret);
        break;
    }
 
  }

hardware:STM32H747I-DISCO

i want send TCP data continuously  in a while ;

but this is a problem; Error message after sending 5 data;errcode is 0x38 ;But I'm sure the Internet is good;

so i check code i find ;

HAL_ETH_Transmit_IT -- > ETH_Prepare_Tx_Descriptors return HAL_ETH_ERROR_BUSY;

if((READ_BIT(dmatxdesc->DESC3, ETH_DMATXNDESCWBF_OWN) == ETH_DMATXNDESCWBF_OWN) || (dmatxdesclist->PacketAddress[descidx] != NULL))
  {
    return HAL_ETH_ERROR_BUSY;
  }

so How to solve this problem?

5 REPLIES 5
alister
Lead

>so How to solve this problem?

Increasing your number of tx dma descriptors will help a bit.

If the app sends packets faster than they can be transmitted, your driver needs to push back (block) or drop.

>i want send TCP data continuously in a while ;

It may look like in the app. But TCP guarantees in-order delivery and to do that it waits for an ACK to each segment it's sent and retries etc. The more and the faster you send, the more buffers it needs, and again, like with the DMA descriptors, when those run out, the app can't expect to send more.

how to check how many descriptors are available? is there such a function?

The app probably shouldn't try to monitor how many Tx DMA Descriptors are available. This ticket's about TCP, so that being the case, the TCP stack is already monitoring the round-trip time for sends to and the acknowledges from the other end, and for the other end's capacity to receive data before it sends.

These are some ideas...

  1. Assess the likely max send rate, and burstiness, and dimension a suitable number of buffers (where the app puts its packet data to send) and number of Tx DMA Descriptors (the memory the ethernet driver prepares, telling the ETH peripheral's DMA engine where the packet headers prepared by the TCP stack and of the packet buffers prepared by the app are in memory and their lengths).
  2. Consider how TCP works, e.g. guaranteeing reliable and in-order delivery, and waiting for an ack from the other end for each send, and possibly retrying the send if that's not received after some time, and that as the app's number of buffers must be limited, and if one send isn't acknowledged and all its buffers become queued waiting to send, the TCP can't continue and the connection will fail. Try to defer the preparing and sending of packet data as late as possible, perhaps using some call-back from the TCP stack indicating the other end's ready to receive it, and/or by devising some signalling mechanism from the other end in your protocol over TCP, thereby limiting the number of buffers queued, waiting to send, per connection and try to limit the number of concurrent connections, etc.
  3. Consider whether the data really warrants TCP. With UDP, the app design may merely choose some nominal send rate, and if the app implementation finds its available buffers are low or zero, that'd indicate the ethernet network's very busy and it might merely skip the send. A design might include a running packet count or similar in its protocol over UDP that the other end might use to understand sequencing and missed packets if it needs to know that.

 

UINT nx_tcp_socket_queue_depth_notify_set(NX_TCP_SOCKET *socket_ptr, VOID(*tcp_socket_queue_depth_notify)(NX_TCP_SOCKET *));

Description
This service sets the transmit queue depth update notify function specified by the application, which iscalled whenever the specified socket determines that it has released packets from the transmit queue such that the queue depth is no longer exceeding its limit. If an application would be blocked on transmit due to queue depth,the callback function serves as a notification to the application that itmay start transmitting again. This service is available only if the NetXDuo library is built with the option NX_ENABLE_TCP_QUEUE_DEPTH_UPDATE_NOTIFYdefined.

Yes that's a good strategy to schedule sends so the max number of buffers queued to send is low, and so you don't need more buffers than necessary, conserving memory.