OpenEdv-开源电子网

 找回密码
 立即注册
正点原子全套STM32/Linux/FPGA开发资料,上千讲STM32视频教程免费下载...
查看: 4853|回复: 3

STM32F407 FreeRTOS低功耗模式实验外部中断死机

[复制链接]

2

主题

10

帖子

0

精华

新手上路

积分
38
金钱
38
注册时间
2018-8-19
在线时间
3 小时
发表于 2019-1-5 23:46:05 | 显示全部楼层 |阅读模式
5金钱
笔者正在学习STM32F407开发板,使用FreeRTOS并开启低功耗模式,代码与原子哥提供的大同小异,唯一的就是没有开启时间统计功能。
开发板下载完程序后,程序可以运行,而且运行正常,但一旦按下按键触发外部中断,LED要么一直亮,要么一直灭。
最终确认为开发板或操作系统死机,而且并未输出错误信息,不知是否有人碰到此问题。



主函数文件如下:
#include "Led.h"
#include "Key.h"
#include "FreeRTOS.h"
#include "task.h"
#include "io.h"
#include "ticks.h"
#include "queue.h"
#include "semphr.h"

#include "string.h"
/************************************************

FreeRTOS低功耗Tickless模式

************************************************/

/************************************************

需要设置configUSE_TICKLESS_IDLE为1,同时实现函PreSleepProcessing和PostSleepProcessing
可以频繁进出低功耗模式,但是在触发外部中断时死机,原因不明,慎用!!!
慎用!!!慎用!!!慎用!!!慎用!!!慎用!!!慎用!!!慎用!!!慎用!!!

************************************************/


//任务优先级
#define START_TASK_PRIO                1
//任务堆栈大小       
#define START_STK_SIZE                 256  
//任务句柄
TaskHandle_t StartTask_Handler;
//任务函数
void start_task(void *pvParameters);

//任务优先级
#define TASK1_TASK_PRIO                2
//任务堆栈大小       
#define TASK1_STK_SIZE                 256  
//任务句柄
TaskHandle_t Task1Task_Handler;
//任务函数
void task1_task(void *pvParameters);

//任务优先级
#define DATAPROCESS_TASK_PRIO 3
//任务堆栈大小       
#define DATAPROCESS_STK_SIZE  256
//任务句柄
TaskHandle_t DataProcess_Handler;
//任务函数
void DataProcess_task(void *pvParameters);

//二值信号量句柄
SemaphoreHandle_t BinarySemaphore;        //二值信号量句柄

//用于命令解析用的命令值
#define LED1ON        1
#define LED1OFF        2
#define BEEPON        3
#define BEEPOFF        4
#define COMMANDERR        0XFF


int main(void)
{
        NVIC_PriorityGroupConfig(NVIC_PriorityGroup_4);//设置系统中断优先级分组4
       
        OS_Ticks_Init();                //初始化延时函数
        OS_IO_Init(9600,1,1);             //初始化串口
        Led_Init();                        //初始化LED端口
       
        Key_Init(1,2,0);                                                        //初始化按键1,中断优先级2
        Key_Init(2,2,0);                                                        //初始化按键
        Clean_Key(1);
        Clean_Key(2);
               
        //创建开始任务
    xTaskCreate((TaskFunction_t )start_task,            //任务函数
                (const char*    )"start_task",          //任务名称
                (uint16_t       )START_STK_SIZE,        //任务堆栈大小
                (void*          )NULL,                  //传递给任务函数的参数
                (UBaseType_t    )START_TASK_PRIO,       //任务优先级
                (TaskHandle_t*  )&StartTask_Handler);   //任务句柄              
    vTaskStartScheduler();          //开启任务调度
}

//开始任务任务函数
void start_task(void *pvParameters)
{
    taskENTER_CRITICAL();           //进入临界区
       
        //创建二值信号量
        BinarySemaphore=xSemaphoreCreateBinary();       
    //创建TASK1任务
    xTaskCreate((TaskFunction_t )task1_task,            
                (const char*    )"task1_task",           
                (uint16_t       )TASK1_STK_SIZE,        
                (void*          )NULL,                  
                (UBaseType_t    )TASK1_TASK_PRIO,        
                (TaskHandle_t*  )&Task1Task_Handler);   
    //创建TASK2任务
    xTaskCreate((TaskFunction_t )DataProcess_task,     
                (const char*    )"keyprocess_task",   
                (uint16_t       )DATAPROCESS_STK_SIZE,
                (void*          )NULL,
                (UBaseType_t    )DATAPROCESS_TASK_PRIO,
                (TaskHandle_t*  )&DataProcess_Handler);
    vTaskDelete(StartTask_Handler); //删除开始任务
    taskEXIT_CRITICAL();            //退出临界区
}

//task1任务函数
void task1_task(void *pvParameters)
{
        static u8 sta1=0;
        while(1)
        {
                if(sta1)
                        Led_Off(1);
                else
                        Led_On(1);
                sta1=!sta1;
               
                if(Read_Key(1))
                {
                        if(BinarySemaphore!=NULL)
                                xSemaphoreGive(BinarySemaphore);        //释放二值信号量
                        Clean_Key(1);
                }
               
        vTaskDelay(20);                     //延时10,10个时钟节拍       
        }
}

//DataProcess_task函数
void DataProcess_task(void *pvParameters)
{
        BaseType_t err=pdFALSE;
        static u8 sta2=0;
       
        while(1)
        {
                if(BinarySemaphore!=NULL)
                {
                        err=xSemaphoreTake(BinarySemaphore,portMAX_DELAY);        //获取信号量
                        if(err==pdTRUE)                                                                                //获取信号量成功
                        {
                                sta2=!sta2;
                        }
                }
                else if(err==pdFALSE)
                {
                        vTaskDelay(10);      //延时10ms,也就是10个时钟节拍       
                }
                if(sta2)
                        Led_On(2);
                else
                        Led_Off(2);
        }
}




//进入低功耗模式前需要处理的事情
//ulExpectedIdleTime:低功耗模式运行时间
void PreSleepProcessing(uint32_t ulExpectedIdleTime)
{
        printf("a");
        //关闭某些低功耗模式下不使用的外设时钟,
//        RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB, DISABLE);
//        RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOC, DISABLE);       
//        RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOD, DISABLE);       
//        RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOE, DISABLE);       
//        RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOF, DISABLE);       
//        RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOG, DISABLE);       
//        RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOH, DISABLE);          
}

//退出低功耗模式以后需要处理的事情
//ulExpectedIdleTime:低功耗模式运行时间
void PostSleepProcessing(uint32_t ulExpectedIdleTime)
{
        printf("b");
        //退出低功耗模式以后打开那些被关闭的外设时钟
//        RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB, ENABLE);
//        RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOC, ENABLE);       
//        RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOD, ENABLE);       
//        RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOE, ENABLE);       
//        RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOF, ENABLE);       
//        RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOG, ENABLE);       
//        RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOH, ENABLE);                      
}


最佳答案

查看完整内容[请看2#楼]

问题已经解决了,就是在按键中断里为了消除抖动使用了延时函数,延时函数使用的是滴答计时器完成的。。。。。。 该问题已经解决,原因不在于外部中断,而是在按键中断中使用了滴答计时器做延时来消抖,但滴答计时器已关闭,所以直接死机 目前解决此问题的方式是条件编译,即不使用低功耗模式下才编译那部分延时,这部分功能需在后期进行完善。
正点原子逻辑分析仪DL16劲爆上市
回复

使用道具 举报

2

主题

10

帖子

0

精华

新手上路

积分
38
金钱
38
注册时间
2018-8-19
在线时间
3 小时
 楼主| 发表于 2019-1-5 23:46:06 | 显示全部楼层
问题已经解决了,就是在按键中断里为了消除抖动使用了延时函数,延时函数使用的是滴答计时器完成的。。。。。。

该问题已经解决,原因不在于外部中断,而是在按键中断中使用了滴答计时器做延时来消抖,但滴答计时器已关闭,所以直接死机
目前解决此问题的方式是条件编译,即不使用低功耗模式下才编译那部分延时,这部分功能需在后期进行完善。
回复

使用道具 举报

2

主题

10

帖子

0

精华

新手上路

积分
38
金钱
38
注册时间
2018-8-19
在线时间
3 小时
 楼主| 发表于 2019-1-6 00:00:37 | 显示全部楼层
那么,剩下的问题就是如何在低功耗模式的按键中断下消抖呢?
回复

使用道具 举报

2

主题

10

帖子

0

精华

新手上路

积分
38
金钱
38
注册时间
2018-8-19
在线时间
3 小时
 楼主| 发表于 2019-1-6 00:01:24 | 显示全部楼层
一波操作猛如虎。。。
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则



关闭

原子哥极力推荐上一条 /2 下一条

正点原子公众号

QQ|手机版|OpenEdv-开源电子网 ( 粤ICP备12000418号-1 )

GMT+8, 2024-11-22 22:58

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

快速回复 返回顶部 返回列表