This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

[参考译文] RTOS/EK-TM4C1294XL:无论发送时间间隔如何、UDP 接收在12个数据包(每个1字节)后停止工作。

Guru**** 2473260 points


请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

https://e2e.ti.com/support/microcontrollers/arm-based-microcontrollers-group/arm-based-microcontrollers/f/arm-based-microcontrollers-forum/680732/rtos-ek-tm4c1294xl-udp-receive-stops-working-after-12-packets-1-byte-each-regardless-of-send-time-interval

器件型号:EK-TM4C1294XL

工具/软件:TI-RTOS

我正在尝试将 Tiva 设置为通过 UDP 接收单字节数据包。  我已经取得了一些成功:我可以正确接收数据包。 但是、在12个连续的数据包(每包1个字节)之后、我无法再接收数据包。 具体来说、fdSelect 函数会在没有超时的情况下挂起、如果我给它一个、则会超时。 我已经指出它  fdSelect  调用  fdPoll、这就是挂起。 以下是我的代码:

//
//配置 UDP
//
#define UDPPORT 5005/**


设置 UDP 任务。
*当设备连接到网络
时调用此挂钩,*并且连接可用。
*/
void networkOpenHook()
{
Task_handle taskHandle;
Task_Params taskParams;
ERROR_Block EB;

//确保错误块已初始化。
ERROR_INIT (&EB);

//创建 UDP 任务处理程序。
//第一个参数是任务侦听的端口。
//将其设置为高优先级任务。
Task_Params_init (&taskParams);
taskParams.STACKSIZE = 1024;
taskParams.priority = 1;
taskParams.arg0 = UDPPORT;
taskHandle = Task_create ((Task_FuncPtr) udpHandler、&taskParams、&EB);
if (taskHandle ==空)
system_printf ("无法创建 udpHandler 任务。\n");
} 

空 udpHandler (UARg arg0、UARg arg1)
{
套接字 lSocket;
struct saddr_in sLocalAddr;
struct sockaddr_in client_addr;
结构时间 val 至;
fd_set readfds;
int addrlen = sizeof (client_addr);
INT 状态;
句柄 hBuffer;
IPN LocalAddress = 0;

int nbytes;
bool 标志= true;
char*缓冲区;

fdOpenSession (TaskSelf());

lSocket = socket (AF_iNet、SOCK_DGRAM、IPPROTO_UDP);
if (lSocket < 0){
System_printf ("udpHandler:套接字失败\n");
Task_exit();
返回;
}

memset ((char *)&sLocalAddr、0、sizeof (sLocalAddr));
sLocalAddr.Sin_Family = AF_iNet;
/sLocalAddr.Sin_len = sizeof (sLocalAddr);
sLocalAddr.Sin_addr.s_addr = LocalAddress;
sLocalAddr.Sin_port = htons (arg0);

status = bind (lSocket、(struct sockadr *)&sLocalAddr、sizeof (sLocalAddr));
如果(状态< 0){
system_printf ("udpHandler:绑定失败:返回:%d,错误:%d\n",状态,fdError());
fdClose (lSocket);
Task_exit();
返回;
}

TO.tv_sec = 5;
TO.tV_usec = 0;

//在我们接收数据时循环
静态 uint32_t TRIGGER_COUNT = 0;
while (flag){
fd_zero (readfds);
fd_set (lSocket、readfds);

if (fdSelect (0、readfds、NULL、NULL、&to)!= 1){
status = fdError();
system_printf ("等待客户机时超时\n"、状态);
system_printf ("udpHandler:迄今为止已收到%u 个触发器\n"、trigger_count);
system_flush();
继续;
}

nbytes = recvncfrom (lSocket、(void **)&buffer、MSG_WAITALL、(struct sockadr *)&client_addr、&addrlen、 hBuffer (&H);

if (nbytes >= 0){
//如果接收到应答字节,则回显该字节。
uint8_t data =*((uint8_t*) buffer);
if (data == 0xAA){
Sendto (lSocket、(char*)&data、1、0、(struct sockadr *)&client_addr、 sizeof (client_addr));
recvncfree (hBuffer);
System_printf ("udpHandler:将%u 回显到客户端。\n"、数据);
} 否则{
TRIGGER_COUNT++;
System_printf ("udpHandler:从客户端接收到%u。\n"、数据);
}
}
否则{
status = fdError();
if (status == EWOULDBLOCK){
System_printf ("udpHandler:等待客户端发送 UDP 数据。\n");
继续;
}
否则{
System_printf (
"udpHandler:Recvfrom Failed:returned:%d、error:%d\n"、
字节、状态);
fdClose (lSocket);
flag = false;
}
}


system_printf ("udpHandler:接收到%u 个触发器\n"、trigger_count);
System_printf ("udpHandler stop、lSocket = 0x%x\n"、lSocket);
system_flush();

if (lSocket){
fdClose (lSocket);
}

fdCloseSession(TaskSele());

/*
*由于 deleteTerminatedTasks 是在 cfg 文件中设置的,
*当空闲任务运行时,任务将被删除。
*
Task_exit();
} 

/*
=== main ====
*/
int main (void)
{
/*呼叫板初始化函数*/
Board_initGeneral();
Board_initEMAC();
Board_initGPIO();

/*打开用户 LED */
GPIO_WRITE (Board_LED0、Board_LED_ON);

//初始化 CONFIG_t 以使用全局螺线管
GLOBAL_CONFIG.MOTLEA = GLOBAL_MODERATLEA;
GLOBAL_CONFIG.num_MOTORS = NUM_MOTORS;

system_printf ("启动示例\n 系统提供程序设置为 SysMin。 "
"停止目标以查看 ROV 中的任何 SysMin 内容。\n");
/* SysMin 仅在您调用 flush 或 exit 时才会打印到控制台*/
system_flush();

/*启动 BIOS */
BIOS_start();

返回(0);
} 

我不知道它是否重要、但除了 UDP 代码之外、我还在运行 HTTP 服务器(成功)。  

 

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    您好、Cody、

    我要将此主题分配给工程师、但为了实现这一目标、您正在使用哪个 TIvaC 版本的 TI-RTOS?

    Todd
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    我将 TI-RTOS 用于 TivaC 版本2.16.00.08。

    谢谢、
    Cody
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    Cody、

    我尝试重现您的故障案例、但到目前为止、它一直在工作。 UDP 线程和 http 服务器之间可能存在一些交互?

    故障是否仅发生在1字节数据包或任何大小的数据包中?

    我安装了 TI-RTOS 2.16.00.08、构建了 udpEcho 示例、并与客户端一起运行、发送1字节数据包。 看起来工作正常。 也许您可以使用与基线相同的设置。

    为了帮助我们进一步调试、您是否会尝试以下操作。 在 CCS 表达式窗口中、输入以下两个变量并展开它们以查看各个元素。

    UDPS
    EMACSnow_Private

    在目标程序运行时、打开表达式窗口中的持续刷新按钮。 您应该会看到数字每秒更新一次。

    我希望看到 EMACSnow_prive.rxCount 每秒持续增加约4个计数。 如果 udpSendReceive 客户端未运行、您可能会看到 UDPS.RcvTotal 偶尔增加、但不会增加太多。  运行客户端应用程序几秒钟;您应该会看到 UDPS.RcvTotal 显著增加。

    当您遇到 UDP 线程锁定时、UPDD.RcvTotal 是否会继续增加? EMACSnow_Private.rxCount 如何?  您是否看到 EMACSnow_Private.rxDrop 开始增加?

    这些信息应有助于我们跟踪问题。

    我将继续调查我的最终结果

    ~Ramsey

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    Ramsey、

    仍然使用我的代码(在接收到特定字节时、udpEcho 被修改为仅回显)、我继续并观察 UDPS.RcvTotal、 EMACSnow_Private。rxCount 和 EMACSnow_Private。rxDrop。 我发现在12个1字节数据包之后、这些值都不会继续增加。

    因此、我更改了代码以始终回显接收到的数据、例如 udpEcho 程序。 现在一切都按预期工作、我可以无限期地继续接收数据包。 这对我来说是可行的,我只是认为没有必要总是回声。 如果您知道为什么有必要向客户发回回复、我会对此感兴趣? 据我了解 UDP、协议本身不需要它。  

    谢谢、

    Cody

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    Cody、

    我同意、UDP 协议不需要返回数据包。 它可能与向电路板发送 UDP 数据包的程序有关。 我假设您已经编写了自己的或修改了 udpSendReceive 示例程序。

    udpSendReceive 程序中、它发送数据缓冲区(256字节)、然后等待任何数据返回。 如果一毫秒后没有任何内容返回、它会再次发送缓冲区并再次等待。 这样做是因为 UDP 是一种"有损耗的"传输。

    一旦*ANY*数据返回,程序就会进入一个循环,等待整个缓冲区返回。

    但是、此逻辑可能存在问题。 发送原始缓冲区时、它可能已被碎片化成较小的数据包(可能为64字节)。 其中一些数据包可能会丢失。 当 Tiva 接收到数据包时、它只是将它们发回。 它不知道每个缓冲区需要多少个数据包。 因此、udpSendReceive 程序可能会一直等待数据的完整缓冲区返回、但如果丢失任何数据包、它将永远等待、因此不再发送任何数据。

    我想知道这可能是您看到的问题。 如果您的 Tiva 程序在不返回数据包的情况下占用数据包、那么发送程序可能会等待永远不会出现的数据、并且不会再发送任何数据包。 这只是我的猜测。

    ~Ramsey