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.
工具与软件:
您好!
我将使用此 MCU 接收基于以太网的命令、然后发送相关但不同的 UART 数据(这最终是一条具有此总线上其他嵌入式模块的 RS -485总线)。 为了实现这一目标、我将 tcpEcho 和 uartEchoDma 示例工程组合在一起。 我已让每一个都独立工作。
问题是、当我同时包含两组代码时、项目将运行大约3秒、并且项目将跳至中止。 我已将 tcpTask 设置为优先级1、将 uartTask 设置为优先级2。 没有使用信标、我认为这样没什么问题、因为 tcpTask 在没有活动时似乎会退出。
我是否需要使用信标或事件来协调这两个任务? tcpTask 应该具有优先级、但如果没有任何以太网活动、我需要执行 uartTask。 我已提供软件文件。
谢谢!
挪亚
e2e.ti.com/.../6318.tcpEchoHooks.c
e2e.ti.com/.../5751.uartEcho.ce2e.ti.com/.../5751.main.ce2e.ti.com/.../EK_5F00_TM4C129EXL.c
你好、Noah、
抱歉、我目前正在度假一整周。 当我下周回来时、我会调查你的问题。 请预计我的回复会有延迟。
祝您度过愉快的假期!
我已经在两个任务之间执行了信标、现在、项目位于"semaphore_pend (uartSys.sema、BIOS_wait_forever);"之后的空闲任务内。
TCP 任务的"后台"似乎有很多事情要做(我的意思是调用所有功能以促进 TCP 操作)。 所需的操作是为 TCP 任务指定优先级、但是当此任务没有连接、也没有活动时、我希望 UART 任务被执行。
下面是我对这两个任务所做的更改。 它们使用相同的信标、并在另一模块中初始化。
//________________________________________________====
/**
@返回
-无效
处理 TCP 连接的任务。 可以有多个正在运行的任务
这个函数。
*/
void echFxn
(
UArg arg0、//<TI RTOS 参数0
UArg arg1 ///< TI RTOS 参数1
)
{
UART_Params uartParams;
const char echoPrompt[]="\fEchoing characters:\r\n";
InitUartParams(&uartParams);
#ifdef MIKROE_DEV
uart_handle uart2、uart4;
uint32_t count = 0;
uint32_t size = 0;
//uint32_t delay = 0;
char outputString[16];
char inputString[16];
static bool initComplete = false;
/// semaphore_post (uartSys.sema);
// Task_sleep(GetSleepTickCount());
/*循环永远回显*/
while (1)
{
system_printf ("正在运行 echoFxn 函数\n");
system_flush();
如果(Semaphore_getCount (uartSys.sema)=0){
system_printf ("Sem blocked in echoFxn\n");
system_flush();
}
/*获取资源的访问权限*/
Semaphore_pend (uartSys.sema、BIOS_wait_forever);
if (false == initComplete)
{
initComplete = true;
uart2 = UART_open (Board_UART2、&uartParams);
if (uart2 == NULL){
system_abort ("打开 UART 时出错");
}
InitUartParams(&uartParams);
uart4 = UART_open (Board_UART4、&uartParams);
if (uart4 == NULL){
system_abort ("打开 UART 时出错");
}
UART_write (uart2、echoPrompt、sizeof (echoPrompt));
}
snprintf (outputString、16、"计数为:%u"、count);
count++;
size = strlen (outputString);
UART_write (uart2、outputString、size);
UART_read (uart4、inputString、16);
snprintf (outputString、16、"%s"、inputString);
system_printf ("发送的字符串为:%s\r\n"、outputString);
system_flush();
Semaphore_post (uartSys.sema);
Task_sleep(GetSleepTickCount());
}
#else
字符输入;
uart_handle uart0;
uart0 = UART_open (Board_UART0、&uartParams);
if (uart0 => NULL){
system_abort ("打开 UART 时出错");
}
UART_write (uart0、echoPrompt、sizeof (echoPrompt));
/*循环永远回显*/
while (1){
UART_READ (uart0、&input、1);
UART_WRITE (uart0、&INPUT、1);
}
#endif
}
//________________________________________________====
/**
@返回
-无效
处理 TCP 连接的任务。 可以有多个正在运行的任务
这个函数。
*/
空 tcpWorker
(
UArg arg0、//<任务参数0
UArg arg1 ///<任务参数1
)
{
int32_t clientfd =(int32_t) arg0;
int32_t bytesRcvd;
int32_t 字节 Sent;
char buffer[TCPPACKETSIZE];
system_printf ("tcpWorker: start clientfd = 0x%x\n"、clientfd);
while ((bytesRcvd = recv (clientfd、buffer、TCPPACKETSIZE、0))> 0){
bytesSent = send (clientfd、buffer、bytesRcvd、0);
if (bytesSent < 0 || bytesSent!= bytesRcvd){
system_printf ("错误:发送失败。\n");
休息;
}
}
system_printf ("tcpWorker stop clientfd = 0x%x\n"、clientfd);
close (clientfd);
}
//________________________________________________====
/**
@返回
-无效
创建新任务来处理新的 TCP 连接。
*/
void tcpHandler
(
UArg arg0、//<任务参数0
UArg arg1 ///<任务参数1
)
{
int32_t status;
int32_t clientfd;
int32_t 服务器;
结构 Sockaddr_in localAddr;
struct sockaddr_in clientAddr;
int32_t optval;
int32_t optlen = sizeof (optval);
socklen_t addrlen = sizeof (clientAddr);
Task_Handle 任务处理;
Task_Params 任务参数;
Error_Block EB;
system_printf ("正在运行 tcpHandler 函数\n");
system_flush();
如果(Semaphore_getCount (tcpTaskSys.sema)=0){
system_printf ("在 tcpHandler\n"中阻止 Sem);
system_flush();
}
/*获取资源的访问权限*/
Semaphore_pend (tcpTaskSys.sema、BIOS_wait_forever);
Server =套接字(AF_INET、SOCK_STREAM、IPPROTO_TCP);
if (server ==-1){
system_printf ("错误:未创建套接字。\n");
shutdown (server);//goto shutdown;
}
memset (&localAddr、0、sizeof (localAddr));
localAddr.sin_family = AF_INET;
localAddr.sin_addr.s_addr = htonl (INADDR_ANY);
localAddr.sin_port = htons (arg0);
status = bind (server、(struct sockaddr *)&localAddr、sizeof (localAddr));
if (status ==-1){
system_printf ("错误:绑定失败。\n");
shutdown (server);//goto shutdown;
}
状态=监听(服务器、NUMTCPWORKERS);
if (status ==-1){
system_printf ("错误:监听失败。\n");
shutdown (server);//goto shutdown;
}
optval = 1;
if (setsockopt (server, SOL_SOCKET、SO_KEEPALIVE、&optval、optlen)< 0){
system_printf ("错误:setsockopt 失败\n");
shutdown (server);//goto shutdown;
}
while (clientfd =
接受(server、(struct sockaddr *)&clientAddr、&addrlen)!=-1)
{
system_printf ("tcpHandler: creating thread clientfd =%d\n"、clientfd);
/*初始化 Error_Block */
error_init (&E);
/*初始化默认值并设置参数。 */
Task_Params_(TaskParams(&T);
taskParams.arg0 =(UArg) clientfd;
taskParams.STACKSIZE = 1280;
taskParams.priority = 1;
taskHandle = Task_create ((Task_Func Ptr) tcpWorker、&taskParams、&eb);
if (taskHandle == NULL)
{
system_printf ("错误:无法创建新任务\n");
close (clientfd);
}
/* addrlen 是值结果参数、必须为下一个接受调用重置*/
addrlen = sizeof (clientAddr);
}
Semaphore_post (tcpTaskSys.sema);
Task_sleep(GetSleepTickCount());
system_printf ("错误:接受失败。\n");
system_flush();
//停机:
// if (服务器> 0){
//关闭(服务器);
//}
}
问题在于、当我同时包含两组代码时、项目将运行约3秒、并且跳至中止状态。
我想知道您分配的系统堆栈大小。 如果您单独运行以太网和 UART 并看到它们正常工作、那么我认为任务堆栈大小应该足够了。 它是我想知道的系统堆栈。 增加系统堆栈该怎么办。 它会产生影响吗? 它仍然会中止吗? 或者、中止将需要超过3秒的时间? 请参见下面的、在这里您可以更改系统堆栈和堆大小。 也许还可以增加任务堆栈并确保它们足够。 您可以使用 ROV 来找出实际使用的堆栈数量。
Charles
我今天花了大约一个小时来讨论这件事(当然不是足够长的时间来根源这件事)。 我将系统堆栈扩展到6200个。 在观察 ROV 时可以看到空闲任务用红色突出显示。 我稍后会做一些更多的故障排除,但这里有一些线索,我不能完全理解。
你好、Noah、
您能否看一下这两个帖子、看看它们是否有帮助。
Charles
简而言之、问题是我在项目的某个时间点包含了 USB 日志记录、但我忘记了这么做。 正是由于此原因导致空闲任务过高并致使工程调用 abort 函数。
删除与 USB 日志记录相关的代码后、您的建议提示我调查为什么调用空闲任务。 毕竟、只有在没有正在执行的任务时才调用空闲任务。 结果表明、信标的挂起和发布已造成意外的无效状态、在这种状态下、TCP 和 UART 任务同时暂停。
我删除了对信标的所有调用。 将两个任务置于同一优先级、并且通过使用 UART 任务中的任务休眠函数、该任务开始工作。 tcpEcho 和 UART 都正常工作。
其他问题包括 UART 任务没有延迟、因此它占用 MCU 的所有带宽。 我添加了一个10ms 的任务睡眠、以便能够调用 TCP 任务。
在最后一条注释中、在任务中使用 snprintf 是否有任何限制? 我观察到一些奇怪的行为,似乎是一个记忆泄漏。 我将对此进行深入研究、但想知道 TI 的 RTOS 是否有任何限制。
感谢您的支持!
你好、Noah、
很高兴您取得了良好的进展。
在最终备注中、在使用 snprintf 执行任务时是否存在任何限制? 我观察到一些奇怪的行为,似乎是一个记忆泄漏。 我将进一步对此进行探讨、但想知道 TI 的 RTOS 是否有任何限制
snprintf()是一个 C 库函数、用于将 printf()函数的输出重定向到缓冲区。 我真的不觉得在使用它时有问题。 TivaWare 库有一个较简单版本的 snprintf、称为 usnprintf。 请查阅 C:\ti\TivaWare_C_Series-2.2.0.295\utils\ustdlib.c 文件以了解各种 printf 函数。 我认为这些更简单的函数将占用更少的内存空间、并有望避免出现的某些内存问题。