最近在调试FreeRTOS系统遇到了一个比较奇怪的问题,在STM32F103最小系统上调试任务通知模拟事件标志组功能时,中断一触发,单片机就会死机。通过查询方式发送任务通知没任何问题,一旦用按键触发外部中断,在中断中发送任务通知时,单片机就死机。在编译时程序无任何报错。
相关代码如下:

#include "sys.h"
#include "delay.h"
#include "usart.h"
#include "led.h"
#include "key.h"
#include "exti.h"#include "FreeRTOS.h"
#include "task.h"
#include "timers.h"TaskHandle_t EventGroupHandler;                //事件标志组句柄#define EVENTBIT_0  (1<<0)                           //事件位
#define EVENTBIT_1  (1<<1)
#define EVENTBIT_2  (1<<2)#define EVENTBIT_ALL  (EVENTBIT_0|EVENTBIT_1|EVENTBIT_2)void start_task(void *pvParameters);
void eventSetBit_task(void *pvParameters);
void eventGroup_task(void *pvParameters);
void eventQuery_task(void *pvParameters);int main(void)
{NVIC_PriorityGroupConfig(NVIC_PriorityGroup_4);//设置系统中断优先级分组4delay_init();                     //延时函数初始化uart_init(115200);                 //初始化串口LED_Init();                          //初始化LEDKEY_Init();IO_Exti_Init();//创建开始任务xTaskCreate(start_task,                   //任务函数的指针"start_task",                //任务的文本名字,只会在调试中用到100,                   //栈深度NULL,                  //没有任务参数1,                      //任务优先级NULL                 //不会用到任务句柄);vTaskStartScheduler();          //开启任务调度
}
void start_task(void *pvParameters)
{taskENTER_CRITICAL();xTaskCreate(eventSetBit_task, "eventSetBit_task", 100, NULL, 2, NULL);      //创建设置事件位任务xTaskCreate(eventGroup_task, "eventGroup_task", 100, NULL, 3, &EventGroupHandler);     //创建事件标志组处理任务vTaskDelete(NULL);taskEXIT_CRITICAL();
}
//设置事件位任务
void eventSetBit_task(void *pvParameters)
{u8 key = 0;u8 i = 0;while(1){if(EventGroupHandler != NULL){key = KEY_Scan( 0 );switch( key ){case 1:xTaskNotify(EventGroupHandler, EVENTBIT_1, eSetBits);break;case 2:xTaskNotify(EventGroupHandler, EVENTBIT_2, eSetBits);break;}}i++;if(i > 50){i = 0;LED1 = !LED1;}vTaskDelay(10);}
}
//事件标志组处理任务
void eventGroup_task(void *pvParameters)
{u8 num = 0;BaseType_t err;uint32_t NotifyValue;static u8 event0flag, event1flag, event2flag;while(1){if(EventGroupHandler != NULL){err = xTaskNotifyWait((uint32_t   )0x00,         //进入函数不清除bit(uint32_t     )0xFFFFFFFF,      //退出函数清除所有bit(uint32_t*  )&NotifyValue, //存储任务通知值(TickType_t )portMAX_DELAY);   //阻塞时间if(err == pdPASS){if((NotifyValue & EVENTBIT_0) != 0){event0flag = 1;printf("事件0发生\r\n");}if((NotifyValue & EVENTBIT_1) != 0){event1flag = 1;printf("事件1发生\r\n");}if((NotifyValue & EVENTBIT_2) != 0){event2flag = 1;printf("事件2发生\r\n");}if(event0flag && event1flag && event2flag){printf("所有事件都发生了\r\n");event0flag = 0;event1flag = 0;event2flag = 0;}}else{printf("任务获取失败\r\n");}}else{vTaskDelay(10);}}
}

中断部分代码如下:

#include "exti.h"
#include "key.h"
#include "led.h"
#include "delay.h"
#include "FreeRTOS.h"
#include "task.h"#define EVENTBIT_0  (1<<0)
extern TaskHandle_t EventGroupHandler;void IO_Exti_Init(void)
{EXTI_InitTypeDef EXTI_InitStructure;NVIC_InitTypeDef NVIC_InitStructure;KEY_Init();RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);GPIO_EXTILineConfig(GPIO_PortSourceGPIOB, GPIO_PinSource0);EXTI_InitStructure.EXTI_Line = EXTI_Line0;EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising;EXTI_InitStructure.EXTI_LineCmd = ENABLE;EXTI_Init(&EXTI_InitStructure);NVIC_InitStructure.NVIC_IRQChannel = EXTI0_IRQn;NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x05;    //抢占优先级6NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x00;NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;NVIC_Init(&NVIC_InitStructure);
}
void EXTI0_IRQHandler(void)
{BaseType_t  xHigherPriorityTaskWoken;delay_xms(20);if(KEY == 1){xTaskNotifyFromISR((TaskHandle_t )EventGroupHandler,     //任务句柄(uint32_t     )EVENTBIT_0,            //要更新的位(eNotifyAction   )eSetBits,              //按位更新(BaseType_t*      )xHigherPriorityTaskWoken);portYIELD_FROM_ISR(xHigherPriorityTaskWoken);}EXTI_ClearITPendingBit(EXTI_Line0);
}

通过单步调试后发现代码一执行到

xTaskNotifyFromISR((TaskHandle_t )EventGroupHandler,     //任务句柄(uint32_t     )EVENTBIT_0,            //要更新的位(eNotifyAction   )eSetBits,              //按位更新(BaseType_t*      )xHigherPriorityTaskWoken);

这块时单片机就会死机,也就是在中断中一发送任务通知,程序出现了异常,通过对比原子的代码和PDF上的说明没发现这段代码有什么问题,对比FreeRTOS的配置文件也没有发现有什么问题,网上搜索了一下,也没找到有效的解决办法,最后没办法了只能把中断函数中的代码一行一行屏蔽找原因,后来发现将 BaseType_t xHigherPriorityTaskWoken; 这个变量的定义放到中断外部时,代码就可以正常运行,难道是在中断执行的时候,内部变量xHigherPriorityTaskWoken存储地址被覆盖了?于是将这个变量在中断函数内部声明为静态变量,代码也可以正常运行。
这说明了xHigherPriorityTaskWoken这个变量的确是在中断函数运行过程中存储的数据丢失了,导致任务通知的返回值存储失效,代码出现了异常。
通过观察FreeRTOS中调试的其他项目代码,这个变量一般都是在函数内部定义的,在中断中也是在函数内部定义的,代码都可以正常运行。唯独在使用发送任务通知xTaskNotifyFromISR()这个功能时,出现了这样情况。不知道是代码其他地方有问题,还是这时FreeRTOS本身的BUG。
不过程序死机的问题暂时只能这样解决了。
修改后的代码如下:

BaseType_t  xHigherPriorityTaskWoken;        //必须定义在中断外面,如果定义在中断代码内,程序会死机
void EXTI0_IRQHandler(void)
{//static BaseType_t  xHigherPriorityTaskWoken;     //如果要定义在函数内部时,这个变量必须声明为静态变量,否则程序会死机delay_xms(20);if(KEY == 1){xTaskNotifyFromISR((TaskHandle_t  )EventGroupHandler,     //任务句柄(uint32_t     )EVENTBIT_0,            //要更新的位(eNotifyAction   )eSetBits,              //按位更新(BaseType_t*      )xHigherPriorityTaskWoken);portYIELD_FROM_ISR(xHigherPriorityTaskWoken);}EXTI_ClearITPendingBit(EXTI_Line0);
}

解决方法暂时为 xHigherPriorityTaskWoken 变量要么定义在中断函数外,如果要定义在中断函数内部时,必须声明为静态变量。

FreeRTOS+STM32F103中断中发送任务通知单片机死机问题相关推荐

  1. 单片机 架构 程序 经验总结_单片机“死机”了怎么办?看看一个资深工程师的经验总结...

    原标题:单片机"死机"了怎么办?看看一个资深工程师的经验总结 单片机(Microcontroller,MCU) 又称为微控制器或嵌入式控制器,体积虽小,但使用方便,应用范围广泛,在 ...

  2. 单片机死机了,该怎么办?

    一.振荡器停止振荡 又可以分为电源电压不稳,或者强干扰引起的振荡器停振. 二.PC指针跑飞 电源电压不稳或强干扰引起PC跑飞,如果看门狗不好,也会引起死机. 三. 设计上对长引出线的IO没有保护,静电 ...

  3. 单片机c语言调用函数费时,下头函数,只要被调用就会导致单片机死机,请大家帮忙分析...

    当前位置:我的异常网» C语言 » 下头函数,只要被调用就会导致单片机死机,请大家帮 下头函数,只要被调用就会导致单片机死机,请大家帮忙分析 www.myexceptions.net  网友分享于:2 ...

  4. enc28j60发送大量数据时死机

    我用的是lwip,enc28j60作为网卡,发送大量数据时死机,无法ping通,一度以为是lwip协议栈的问题. 经过半个月的查询,发现时enc28j60电流的问题. 可以加大电流,enc28j60即 ...

  5. 单片机死机常见原因分析

    在日常的单片机开发中,不可避免会遇上死机的现象,让人摸不着头脑,更严重的是死机并不能轻易复现的情况,下面我就说一些我在开发过程中遇到过的情况. 变量溢出或变量未初始化 这里的变量溢出指的是变量定义的数 ...

  6. 问题二十三:C++中debug简单的运行死机问题

    其实,"模拟不同材料颜色"章节中,刚添加完相关code之后,运行出现过死机. 将采样次数尽可能降低,简化过程,方便分析问题. 在main()函数添几条log,为了判断死在main( ...

  7. 关于解决windows10运行机械硬盘中的游戏时遭遇死机重启后硬盘消失的方法

    事情的起因是:当在windows10中运行机械硬盘F盘的英雄联盟客户端时出现死机,用任务管理器也无法解决时,直接关机重启. 特点:重启后发现开机很慢,F盘消失了,并且电脑变得很卡,每次点开一个应用进程 ...

  8. 单片机程序跑飞死机的几种原因

    在使用单片机过程中,经常会出现程序运行一段时间后,不能够正常相应的情况.一般分为软件原因和硬件原因,其中硬件原因比较容易查,软件原因就较为复杂. 软件导致单片机死机的原因 1.指针异常 指针未初始化或 ...

  9. 【5种灵活有效方式】如何从死机手机中恢复内部数据?

    我的手机掉在地上,现在无法开机.我丢失了所有联系人.图片和重要文件.无奈之下,我需要恢复数据.但是如何从死机中恢复内部数据呢? 我们使用移动设备的最重要原因之一是打电话和发送消息.但有时,我们使用相同 ...

最新文章

  1. Java NIO理解与使用
  2. dozer bean_使用Dozer框架进行Bean操作
  3. 2019贵州大学计算机研究生,贵州大学2019年硕士研究生招生拟录取名单公示(一)...
  4. Class 18 - 1 图形验证码的识别
  5. 戴尔推出PowerEdge T30,主打小型办公和家庭办公市场
  6. C# Global定时执行Global文件aTimer处理
  7. UItextInput-Protocol
  8. 对java类中注释的认识
  9. imagenet2012数据集
  10. mysql列行条件,返回满足mysql表中列的多个条件的行
  11. Oracle9i中监视索引的使用
  12. snmpwalk工具使用
  13. iOS13.0上适配深色模式
  14. 你创业为什么会失败?
  15. 2023年徐汇区文化发展专项资金扶持项目申报指南
  16. 凌晨 12 点突发 Istio 生产事故!一顿操作猛如虎解决了
  17. Ajax速通(四)——axios
  18. 一键分享到新浪微博、腾讯微博、搜狐微博、人人网、开心网、百度收藏等js代码大全...
  19. kubernetes 【组件】ingress 如何通过域名访问您的应用
  20. 发光二极管的keil代码c语言,用Keil点亮一个发光二极管

热门文章

  1. Fedora10使用若干问题
  2. Dockerfile封装Django镜像
  3. [洛谷P2073] 送花
  4. 每天CookBook之Python-048
  5. 【Java】关于Java编程软件idea快捷键的使用
  6. c语言的44种运算符,C语言重要知识点总结【9】:C语言运算符(详解)
  7. mysql ext_RHEL5+postfix+mysql+extmai(源代码)(一)
  8. dbutils mysql_使用DBUtils控制mysql事务
  9. avs3 ts格式封装 标准_第480期【软件】吊打格式工厂—高清视频转换器WonderFox HD Video便携版...
  10. txt替换回车键符号怎么打_电脑键盘上那个点符号怎么打出来的?