我在STM32F7上用freeRtos、LwIP和netconn api实现了一个小型tcp客户端。我可以与服务器建立连接,并将一些数据发送到网络。我的问题是,从命令到我在网络上真正看到以太网数据之间有一个巨大的延迟(秒..(。看起来数据在一次性发送之前已经缓冲。
我知道TCP_NODELAY标志,并设置了它(使用tcp_nagle_disable(conn->pcb.tcp)
(,但它没有什么区别。以太网有效负载约为50字节,TCP_MSS为1460。netconn api看到数据被发送(netbuffer结构被更新,tcp_write()
和tcp_output()
被调用时没有错误(,但我的印象是,在low_level_output()
被调用并将数据缓冲区传递给DMA(带有HAL_ETH_TransmitFrame()
(后,它一直保持在那里,直到发生了什么事,一次发送了3或4个以太网数据包。
我不想永远等待回复,我在netconn_recv()
上设置了一个超时,启用LWIP_SO_RCVTIMEO
并调用netconn_set_recvtimeout()
。我将服务器设置为使用回声进行回复,但即使超时500毫秒,我也会丢失大部分回复。
这里有一些代码:
conn = netconn_new(NETCONN_TCP);
if (conn != NULL)
{
err = netconn_bind(conn, IP_ADDR_ANY, 0);
if (err == ERR_OK)
{
connect_error = netconn_connect(conn, &dest_addr, SRV_PORT);
if (connect_error == ERR_OK)
{
// set a timeout to avoid waiting forever
netconn_set_recvtimeout(conn, 500);
//TCP_NODELAY
tcp_nagle_disable(conn->pcb.tcp);
osSemaphoreRelease(tcpsem); // signal tcpsend
if (netconn_recv(conn, &buf) == ERR_OK)
{
//Parse message
do
{
// do stuff..
}
while (netbuf_next(buf) >0);
netbuf_delete(buf);
} else {
// TIMEOUT
}
}
/* Close connection */
netconn_close(conn);
}
netconn_delete(conn);
}
vTaskDelete(tcpsendTaskHandle);
vTaskDelete(NULL);
tcpsend
void tcpsend (void *data, size_t len)
{
// send the data to the connected connection
netconn_write(conn, data, len, NETCONN_NOFLAG);
}
tcpsend
static void tcpsend_thread (void *arg)
{
for (;;)
{
// semaphore must be taken before accessing the tcpsend function
osSemaphoreAcquire(tcpsem, portMAX_DELAY);
// build msg
if (ethPrepare(ðMsg) == ERR_OK)
{
// send the data to the server
tcpsend(ðMsg, ethMsg.ncSize);
}
vTaskDelay(100);
}
}
发现问题:我还忘记将TxBuffer内存设置为不可缓存可缓冲。。
一旦我在加载器脚本和ethernetif.c中为tx缓冲区添加了内存配置(我只为rx添加了它(,我就可以立即看到以太网数据包。