th1 线程为什么会永远执行下去不停呢?
第35行我只之让它循环了20次
补上46-48行才让它运行一段时间后停下来
/*
* Copyright (c) 2006-2021, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2021-08-24 RT-Thread first version
*/
#include <rtthread.h>
#define DBG_TAG "main"
#define DBG_LVL DBG_LOG
#define MB1_SIZE_MAX 10
#include <rtdbg.h>
rt_thread_t th1 , th2;
rt_mq_t mymsq = NULL;
rt_mailbox_t mb1 = NULL;
typedef struct
{
uint16_t buf;
rt_mailbox_t mb_t;
}MYMSG;
void th1_entry(void *parameter)
{
uint16_t mbrx = 0;
MYMSG myMsg = {10, mb1};
rt_thread_mdelay(5000);
rt_kprintf("\nTx: %d\n", myMsg.buf);
rt_mq_send(mymsq, (void*)&myMsg, sizeof(MYMSG));
for (int i=0;i<20;i++){
if (rt_mb_recv(mb1, (rt_ubase_t *)&mbrx, 1500) != RT_EOK){
mbrx = 0;
rt_kprintf("Tx: %d ack: %d resending...\n", myMsg.buf, mbrx);
}
if (mbrx > 0) {
if (mbrx == 1) {
myMsg.buf++;
} else if (mbrx == 2) {
myMsg.buf += 2;
}
// if (myMsg.buf > 35){
// break;
// }
rt_kprintf("Tx: %d ack: %d sending next msg...\n", myMsg.buf, mbrx);
rt_mq_send(mymsq, (void*)&myMsg, sizeof(MYMSG));
}
}
}
void th2_entry(void *parameter)
{
MYMSG myMsg;
for(;;){
rt_thread_mdelay(50);
rt_mq_recv(mymsq, (void*)&myMsg, sizeof(MYMSG), RT_WAITING_FOREVER);
if ((myMsg.buf % 3) == 0){
rt_mb_send(myMsg.mb_t, 1);
rt_kprintf("\nRx: %d ack: 1\n",myMsg.buf);
} else {
rt_mb_send(myMsg.mb_t, 2);
rt_kprintf("\nRx: %d ack: 2\n",myMsg.buf);
}
}
}
int main(void)
{
mymsq = rt_mq_create("mq1", 10, sizeof(MYMSG), RT_IPC_FLAG_FIFO);
mb1 = rt_mb_create("mb1", MB1_SIZE_MAX, RT_IPC_FLAG_FIFO);
th1 = rt_thread_create("th1", th1_entry,RT_NULL,512, 21, 0);
if(th1 == RT_NULL){
LOG_E("th1 rt_thread_create failed...\n");
return -ENOMEM;
}
th2 = rt_thread_create("th2", th2_entry,RT_NULL,512, 20, 81);
if(th1 == RT_NULL){
LOG_E("th2 rt_thread_create failed...\n");
return -ENOMEM;
}
rt_thread_startup(th1);
rt_thread_startup(th2);
return 0;
}
问题补充。
按照你说的修改以后,debug下的hard fault没有了,但是i还是0~2之间跳。把int i放到for前面也没用
这个工程是用RTT studio 默认生成的,只修改了main函数。
我这个板子是买的正点的潘多拉的L475,如果用他们提供的DEMO模板来做,main.c文件换成我这个例子之后,for循环20次就能后跳出
我看区别主要为,RTT studio 默认生成用的是GCC,正点是用MDK移植的,用的是ARMCC
@cypressxt 这个跟编译器没关系。i 变量意外修改,rt_mb_recv 也不能够清零这个 i 的值。
继续尝试一下,用一个全局变量代替 i 这个局部变量。或者把 i 改成 static的。
上面我说的第四条也改过来了?这里虽然有问题,但是看不到怎么跟栈联系上的,把i这个变量清零了
@出出啊 124条都改了,第三条应该不存在,只写了main文件,其余都是studio生成的。使用静态变量自然没有问题,i==20就结束了。或者线程里不使用rt_mb_recv,局部i也不会被修改。真的很纳闷。
@出出啊 我把th1改成静态的也不好使
@出出啊 解决了,但还是不明原理。。。
把
改成
就行了。。。为啥?
在MDK里不这么改也是正常的,为啥???
@cypressxt 不是,你理解错意思了,改 i 变量,不是改那个线程入口函数。改函数没用。
下面这个函数里的 mbrx myMsg i 这仨变量全换成全局变量。
如果你的代码只有这点儿,看不出来哪儿有问题,这里应该没错了
@cypressxt 这么改是把 rst 当替死鬼了,前边你也看到了,i 从 1变成0。说明有地方把栈上的最后一个变量给清零了。
你现在多给了个变量,rst 就冲在了 i 前边被清零了。但是正常的返回结果也是 0.这样你根本看不出问题来了。
这个 bug 很妙啊。
建议打开当前线程栈内存,单步调试这里
rt_mb_recv
,把 rst 还去掉还用 i ,你可能会发现代码走到哪一步被清零的。不同编译器编译出来的代码稍微不一样,内存布局,code 的地址等等,有些隐藏问题就是被上面你这样的代码遮掩过去了,但是并不代表没有问题。
@出出啊 感谢,我现在明白了!就用你说的看内存的方法,找到问题在哪里了!
变量uint16_t mbrx占用地址是153A和153B,int i占用地址是153C到153F。本来mbrx是16位的,修改它不会影响到int i。但是这里它被强转了!
(rt_ubase_t *)是一个指向4字节变量的指针。当收到邮件以后,在小端模式下,153A到153D被修改为01 00 00 00或者02 00 00 00,地址153C和153D都被修改成0了,于是i在小端模式下就变成0了。
解决方法是把uint16_t mbrx改成uint32_t mbrx就可以了!
@出出啊 和编译器还是有关系的,MDK下i被优化了,栈地址中找不到i,至于i跑哪段地址里去了……再MDK里研究了半天也没搞明白
@cypressxt 呃,疏忽了。这种参数直接定义成 rt_ubase_t 也是行的,省心
和编译器相关的就是,它们分配的局部变量的顺序不一样,mbrx 和 i 放一起了,而且是 mbrx 在前 i 在后就出错了。但凡 i 大于 65536 i 也不会变成 0,调整变量顺序这一点儿忽略了。