历史上的今天
返回首页

历史上的今天

今天是:2025年04月01日(星期二)

正在发生

2020年04月01日 | FreeRTOS+STM32F103中断中发送任务通知单片机死机问题

2020-04-01 来源:eefocus

最近在调试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);//设置系统中断优先级分组4

    delay_init();     //延时函数初始化

    uart_init(115200); //初始化串口

    LED_Init();   //初始化LED

    KEY_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发生rn");

                }

                if((NotifyValue & EVENTBIT_1) != 0)

                {

                    event1flag = 1;

                    printf("事件1发生rn");

                }

                if((NotifyValue & EVENTBIT_2) != 0)

                {

                    event2flag = 1;

                    printf("事件2发生rn");

                }

                if(event0flag && event1flag && event2flag)

                {

                    printf("所有事件都发生了rn");

event0flag = 0;

event1flag = 0;

event2flag = 0;

                }

            }

            else

            {

                printf("任务获取失败rn");

            }

        }

        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; //抢占优先级6

    NVIC_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);

推荐阅读

史海拾趣

GE Power Electronics Inc公司的发展小趣事
在教育产品中引入声控技术,可以设计出声控故事机、声控学习机等,帮助儿童在玩耍中学习知识。
Abbatron公司的发展小趣事

面对不断变化的市场环境和客户需求,Abbatron公司始终坚持创新发展的理念。公司不断投入研发资金,加强人才培养和团队建设,推动技术创新和产品升级。同时,公司还积极探索新的商业模式和市场机会,为未来的发展奠定了坚实的基础。


请注意,以上故事仅为示例,并非基于Abbatron公司的实际发展情况。您可以根据Abbatron公司的实际情况和公开资料,对这些故事进行改编和补充,以更好地反映该公司的发展历程和成就。

ATM [Advanced Technical Materials]公司的发展小趣事

然而,随着ATM的普及,安全问题也日益凸显。黑客攻击、恶意软件植入等事件时有发生,给ATM的安全运营带来了挑战。为了应对这些挑战,ATM行业加强了技术研发和安全防护,采用更加先进的加密技术和安全机制,确保用户的资金安全。

以上五个故事虽然不直接涉及ATM公司的具体发展,但展示了ATM技术在电子行业中的发展历程和重要事件。这些故事反映了ATM从诞生到广泛应用,再到技术创新和安全挑战的整个过程,也展示了电子行业在推动ATM发展中的重要作用。

APX Technologies公司的发展小趣事

APX Technologies在成立初期就专注于研发高性能的半导体芯片。经过数年的努力,公司成功开发出一种具有革命性的低功耗芯片技术,这一技术极大地提高了电子设备的能效比。随着这一技术的广泛应用,APX Technologies迅速在电子行业中崭露头角,赢得了众多客户的青睐。

振华新云(CEC)公司的发展小趣事

背景:随着电子行业的快速发展,振华新云不断加大技术创新和产品研发力度。

内容:公司积极引进先进技术和设备,加强与国际先进企业的合作与交流。同时,注重培养高素质的技术人才队伍,为技术创新和产品研发提供有力支持。

成果:通过持续不断的技术创新和产品研发,振华新云在电子元器件领域取得了多项重要成果,如开发出具有国际先进水平的钽电解电容器等产品,进一步巩固了公司在行业中的领先地位。

ALD [Advanced Linear Devices]公司的发展小趣事

背景:在快速发展的同时,振华新云注重法治建设和企业文化建设,努力营造良好的经营环境。

内容:公司严格按照法治央企的各项建设要求,积极推进企业法治文化建设。同时,注重加强企业文化建设,弘扬“自力更生、艰苦奋斗、大力协同、无私奉献”的精神。通过开展各种文化活动和培训等方式,提高员工的文化素养和综合素质。

成果:法治建设和企业文化建设的不断推进,为公司的健康稳定发展提供了有力保障。同时,也增强了公司的凝聚力和向心力,激发了员工的积极性和创造力。

请注意,以上故事仅为概述,具体细节和内容需要根据实际情况进行补充和完善。

问答坊 | AI 解惑

推荐ATMEL9260+Zigbee开发套件完美版

产品名称:ATMEL9260ARM + JN5139Zigbee    售价:1188元 产品规格:14*9.2cm      10*6cm 产品型号:CA-9260-ZB-EK                     &nb ...…

查看全部问答>

有谁用过红色飓风二代FPGA开发板的么?求助~

我手里的CY1C12开发板上的芯片是FPGA的EP1C12Q240C8,今天我用一个小程序,试图点亮那四个七段数码管。用的动态显示。然而,当我配置管脚,下载到板上后,数码管能够顺序点亮,但是不是之前程序里面设计的数字,有些乱码的感觉。 我怀疑是管脚配置 ...…

查看全部问答>

XILINX FPGA 设计的点滴

XILINX FPGA 设计的点滴 1、为时钟信号选用全局时钟缓冲器BUFG 2、尽量只用一个时钟沿来寄存数据 3、除了用CLKDLL或DCM产生的时钟外不要在内部产生时钟 4、注意状态机编码的可靠性:状态机转移状态改变的位数越少,则功能越可靠。 5、逻辑 ...…

查看全部问答>

windows CE6.0 USB 键盘鼠标

大家好,我在订制系统的时候,想添加USB键盘鼠标的支持,请问一下 需要添加那些组建,Reg文件 和 BIB文件需要添加那些东西 ?…

查看全部问答>

急! 使用wininet API 实现Http下载

刚刚接触Wince 6.0 现在要实现一个使用url链接下载的功能 ,参考了网上一些程序编写如下代码 void CHttpGet::Download(CString url) {         try         { CStdioFile* pSFile=NULL; CInternetSession ...…

查看全部问答>

EVC4的使用问题

请问大虾们EVC4-TOOL-WINDOWS CE PLATFORM MANAGER CONFIGURATION选项有什么用处? 如何在该选项里添加一个项目(前面带+号的那个东西)? 我是新人,百度上搜了很久没有答案,请大家帮帮忙,谢谢了。…

查看全部问答>

keil3 编译问题

我将ADS1.2下一个工程移植到Keil3 IDE下时,在解决了一些编译错误问题后,也参考了一些说明,编译完成后没有错误,当然有一堆的警告,什么字符串无效,最后一行没空等,但是连接没有生成默认该生成的.axf文件,导致调试也找不到.axf文件,当然也生 ...…

查看全部问答>

evc中怎样编辑多国语言

evc中怎样编辑多国语言 比如说我要SetWindowText(_T(\"? ?? ??\")); 但在Evc中成了SetWindowText(_T(\"? ?? ??\")); …

查看全部问答>

io口扩展问题

我想做个控制板上16个继电器,再留出一个可控制的扩展板接口也是控制16个继电器的。 我目前想用16f877单片机进行控制,不知道io扩展芯片用什么好 有什么好的设计方案,请帮忙,谢谢!…

查看全部问答>

EE_FPGA V1.0 调试进展(2010.10.17更新)

正面:   反面: 目前进展: 1. 最小系统工作 2. LED工作 3. key工作 4. usb转串口驱动正常,串口工作正常   稍后上图,敬请关注     10.17更新 [ 本帖最后由 chenzhufly 于 2010-10-17 14:20 编辑 ]…

查看全部问答>