zoukankan      html  css  js  c++  java
  • 使用FreeRTOS在SD卡驱动使用非系统延时导致上电重启不工作的情况

    一、问题描述
    在一个使用FreeRTOS的工程中,只做了SD卡的驱动,由于RTOS使用了Systick,故非系统延时函数使用的是 DWT中的时钟周期(CYCCNT)计数功能,但是在SD卡驱动中使用了这个非系统延时导致,烧写程序后板子工作正常,而下电再上电后板子无反应,分析排查去掉了这个非系统延时后工作正常。

    二、使用环境
    1)开发环境使用的是MDK5.20,下载器为JLINK;
    2)软件工程是V6的FreeRTOS模板工程,SD卡驱动也是V6的,非系统延时函数所在文件为V6的 bsp_dwt.c;
    3)硬件板子是自己做的,MCU是STM32F429ZGT6;

    三、问题分析
    1)硬件板子已使用了一段时间,工作都正常包括下电再上电的情况,故该问题排出了硬件电路的问题;
    2)由于之前也遇见过这样的现象,再加之网络查找,和代码分析实验,最后将问题定在了延时 bsp_DelayMS(100);
    3)工程代码

      1 int main(void)
      2 {
      3     /* 
      4       在启动调度前,为了防止初始化STM32外设时有中断服务程序执行,这里禁止全局中断(除了NMI和HardFault)。
      5       这样做的好处是:
      6       1. 防止执行的中断服务程序中有FreeRTOS的API函数。
      7       2. 保证系统正常启动,不受别的中断影响。
      8       3. 关于是否关闭全局中断,大家根据自己的实际情况设置即可。
      9       在移植文件port.c中的函数prvStartFirstTask中会重新开启全局中断。通过指令cpsie i开启,__set_PRIMASK(1)
     10       和cpsie i是等效的。
     11      */
     12     __set_PRIMASK(1);  
     13     
     14     /* 硬件初始化 */
     15     bsp_Init(); 
     16     
     17     /* 创建任务 */
     18     AppTaskCreate();
     19     
     20     /* 启动调度,开始执行任务 */
     21     vTaskStartScheduler();
     22 
     23     /* 
     24       如果系统正常启动是不会运行到这里的,运行到这里极有可能是用于定时器任务或者空闲任务的
     25       heap空间不足造成创建失败,此要加大FreeRTOSConfig.h文件中定义的heap大小:
     26       #define configTOTAL_HEAP_SIZE          ( ( size_t ) ( 30 * 1024 ) )
     27     */
     28     while(1);
     29 }
     30 
     31 /*
     32 *********************************************************************************************************
     33 *    函 数 名: vTaskTaskUserIF
     34 *    功能说明: 接口消息处理,这里用作LED闪烁    
     35 *    形    参: pvParameters 是在创建该任务时传递的形参
     36 *    返 回 值: 无
     37 *   优 先 级: 1  (数值越小优先级越低,这个跟uCOS相反)
     38 *********************************************************************************************************
     39 */
     40 static void vTaskTaskUserIF(void *pvParameters)
     41 {
     42     while(1)
     43     {
     44         bsp_LedToggle(1);
     45         vTaskDelay(500);
     46     }
     47 }
     48 
     49 /*
     50 *********************************************************************************************************
     51 *    函 数 名: vTaskLED
     52 *    功能说明: LED闪烁    
     53 *    形    参: pvParameters 是在创建该任务时传递的形参
     54 *    返 回 值: 无
     55 *   优 先 级: 2  
     56 *********************************************************************************************************
     57 */
     58 static void vTaskLED(void *pvParameters)
     59 {
     60     while(1)
     61     {
     62         bsp_LedToggle(2);
     63         vTaskDelay(1000);
     64     }
     65 }
     66 
     67 /*
     68 *********************************************************************************************************
     69 *    函 数 名: vTaskMsgPro
     70 *    功能说明: 信息处理,这里是用作LED闪烁    
     71 *    形    参: pvParameters 是在创建该任务时传递的形参
     72 *    返 回 值: 无
     73 *   优 先 级: 3  
     74 *********************************************************************************************************
     75 */
     76 static void vTaskMsgPro(void *pvParameters)
     77 {
     78     while(1)
     79     {
     80         DemoFatFS();
     81         vTaskDelay(300);
     82     }
     83 }
     84 
     85 /*
     86 *********************************************************************************************************
     87 *    函 数 名: vTaskStart
     88 *    功能说明: 启动任务,也就是最高优先级任务,这里用作LED闪烁
     89 *    形    参: pvParameters 是在创建该任务时传递的形参
     90 *    返 回 值: 无
     91 *   优 先 级: 4  
     92 *********************************************************************************************************
     93 */
     94 static void vTaskStart(void *pvParameters)
     95 {
     96     while(1)
     97     {
     98         /* 按键扫描 */
     99         bsp_LedToggle(4);
    100         vTaskDelay(400);
    101     }
    102 }
    103 
    104 /*
    105 *********************************************************************************************************
    106 *    函 数 名: AppTaskCreate
    107 *    功能说明: 创建应用任务
    108 *    形    参:无
    109 *    返 回 值: 无
    110 *********************************************************************************************************
    111 */
    112 static void AppTaskCreate (void)
    113 {
    114     xTaskCreate( vTaskTaskUserIF,       /* 任务函数  */
    115                  "vTaskUserIF",         /* 任务名    */
    116                  512,                   /* 任务栈大小,单位word,也就是4字节 */
    117                  NULL,                  /* 任务参数  */
    118                  1,                     /* 任务优先级*/
    119                  &xHandleTaskUserIF );  /* 任务句柄  */
    120     
    121     
    122     xTaskCreate( vTaskLED,            /* 任务函数  */
    123                  "vTaskLED",          /* 任务名    */
    124                  512,                 /* 任务栈大小,单位word,也就是4字节 */
    125                  NULL,                /* 任务参数  */
    126                  2,                   /* 任务优先级*/
    127                  &xHandleTaskLED ); /* 任务句柄  */
    128     
    129     xTaskCreate( vTaskMsgPro,             /* 任务函数  */
    130                  "vTaskMsgPro",           /* 任务名    */
    131                  512,                     /* 任务栈大小,单位word,也就是4字节 */
    132                  NULL,                   /* 任务参数  */
    133                  3,                       /* 任务优先级*/
    134                  &xHandleTaskMsgPro );  /* 任务句柄  */
    135     
    136     
    137     xTaskCreate( vTaskStart,             /* 任务函数  */
    138                  "vTaskStart",           /* 任务名    */
    139                  512,                    /* 任务栈大小,单位word,也就是4字节 */
    140                  NULL,                   /* 任务参数  */
    141                  4,                      /* 任务优先级*/
    142                  &xHandleTaskStart );   /* 任务句柄  */
    143 }
      1 /*
      2 *********************************************************************************************************
      3 *    函 数 名: DemoFatFS
      4 *    功能说明: FatFS文件系统演示主程序
      5 *    形    参:无
      6 *    返 回 值: 无
      7 *********************************************************************************************************
      8 */
      9 void DemoFatFS(void)
     10 {
     11     uint8_t cmd;
     12 
     13     /* 打印命令列表,用户可以通过串口操作指令 */
     14     DispMenu();
     15 //    while(1)
     16     {
     17         bsp_Idle();        /* 这个函数在bsp.c文件。用户可以修改这个函数实现CPU休眠和喂狗 */
     18 
     19         if (comGetChar(COM1, &cmd))    /* 从串口读入一个字符(非阻塞方式) */
     20         {
     21             printf("
    ");
     22             switch (cmd)
     23             {
     24                 case '1':
     25                     printf("【1 - ViewRootDir】
    ");
     26                     ViewRootDir();        /* 显示SD卡根目录下的文件名 */
     27                     break;
     28 
     29                 case '2':
     30                     printf("【2 - CreateNewFile】
    ");
     31                     CreateNewFile();        /* 创建一个新文件,写入一个字符串 */
     32                     break;
     33 
     34                 case '3':
     35                     printf("【3 - ReadFileData】
    ");
     36                     ReadFileData();        /* 读取根目录下armfly.txt的内容 */
     37                     break;
     38 
     39                 case '4':
     40                     printf("【4 - CreateDir】
    ");
     41                     CreateDir();        /* 创建目录 */
     42                     break;
     43 
     44                 case '5':
     45                     printf("【5 - DeleteDirFile】
    ");
     46                     DeleteDirFile();    /* 删除目录和文件 */
     47                     break;
     48 
     49                 case '6':
     50                     printf("【6 - TestSpeed】
    ");
     51                     WriteFileTest();    /* 速度测试 */
     52                     break;
     53 
     54                 default:
     55                     DispMenu();
     56                     break;
     57             }
     58         }
     59         
     60 //        bsp_DelayMS(100);            /* 此延时将导致板子重新上电不工作 */
     61         
     62         /* 按键滤波和检测由后台systick中断服务程序实现,我们只需要调用bsp_GetKey读取键值即可。 */
     63         switch (bsp_GetKey())    /* bsp_GetKey()读取键值, 无键按下时返回 KEY_NONE = 0 */
     64         {
     65             case KEY_DOWN_K1:            /* K1键按下 */
     66                 break;
     67 
     68             case KEY_UP_K1:                /* K1键弹起 */
     69                 break;
     70 
     71             case KEY_DOWN_K2:            /* K2键按下 */
     72                 break;
     73 
     74             case KEY_UP_K2:                /* K2键弹起 */
     75                 break;
     76 
     77             case KEY_DOWN_K3:            /* K3键按下 */
     78                 break;
     79 
     80             case KEY_UP_K3:                /* K3键弹起 */
     81                 break;
     82 
     83             case JOY_DOWN_U:            /* 摇杆UP键按下 */
     84                 break;
     85 
     86             case JOY_DOWN_D:            /* 摇杆DOWN键按下 */
     87                 break;
     88 
     89             case JOY_DOWN_L:            /* 摇杆LEFT键按下 */
     90                 break;
     91 
     92             case JOY_DOWN_R:            /* 摇杆RIGHT键按下 */
     93                 break;
     94 
     95             case JOY_DOWN_OK:            /* 摇杆OK键按下 */
     96                 break;
     97 
     98             case JOY_UP_OK:                /* 摇杆OK键弹起 */
     99                 break;
    100 
    101             case KEY_NONE:                /* 无键按下 */
    102             default:
    103                 /* 其它的键值不处理 */
    104                 break;
    105         }
    106     }
    107 }

    问题就在上段代码第60行的延时函数 bsp_DelayMS(100); 

    四、解决过程

    eric2013

    把你函数void DemoFatFS(void)里面的while大循环加上,不要注释,而函数static void vTaskMsgPro(void *pvParameters)里面的  vTaskDelay(300);注释掉。

    并将你的 bsp_DelayMS(100);   函数所在位置修改为 vTaskDelay(100);就行。

    me

    1. 将函数void DemoFatFS(void)里面的while大循环加上,将导致系统其他3个任务不执行,一直执行 DemoFatFS任务,我之所以注释是因为任务本身已有while循环;

    2. 将非系统延时函数bsp_DelayMS(100)替换为系统延时函数vTaskDelay(100),经测试工作正常,我想问的是非系统延时函数bsp_DelayMS(100)为什么会导致这样的问题产生,难道FreeRTOS系统中不支持非系统延时函数,但我在学习V6-349-FreeRTOS实验_FreeRTOS+STemWin+FatFS+USB Devicet综合例程时,看到在触摸屏驱动和外部SDRAM驱动文件中多次使用了非系统延时函数bsp_DelayMS(),这也是我在本工程中加入bsp_dwt.c文件使用非系统延时函数bsp_DelayMS()的缘由,该综合例程经我在V6开发板上运行正常,所以原因不是不能使用,应该是我的使用方式有问题,或是有些地方未注意到,恳请帮忙分析教导

    eric2013

    1. 这个是阻塞式的延迟,这个任务阻塞后,低于此优先级的任务将得不到执行。
    2. 那个是驱动,驱动仅调用一次,在bsp_Init初始化的时候仅调用一次,任务执行的时候不会再使用。

    me

    1. 可以理解为任务中不可以使用非系统延时函数?
    2. 我做了如下实验

    上表中包括我的测试条件及个人一些理解,和最终的疑问。
    3.为了规避这样的事情发生,在任务中只使用系统延时函数即可,但有些情况使用非系统延时函数较为方便,比如某些设备的Demo,因为这些设备Demo程序会单独存在于文件中,或是在不考虑操作系统时而写的一些应用程序等。为了研究本质刨根问底,个人觉得还是有必要知晓其中机理,在此感谢大家了。

    eric2013

    1. 可以加,比如DS18B20这种,是要加的微妙延迟的。
    2. 以系统断电后重新上电为准。关于这个第2个问题,后面还是需要深入学习下RTOS工作原理。通过本质理解现象的效率更高些。
    3. 这种大延迟,死等的程序一定要修改,最好改成事件触发的方式,后面你改的多了就熟练了。需要慢慢从裸机的编程思想转换到RTOS上面来。

    me

    好的 多谢
    暂且如此吧 待深入后续贴

  • 相关阅读:
    加了一句话
    由于数据库 'XXX' 离线,无法打开该数据库。
    Linux命令list
    js 数组去重
    JSON.parse(JSON.stringify()) 实现对对象的深度拷贝,从而互不影响
    docker
    Node child_process Study.2
    node assert模块 Study.1
    git 合并本地分支到远程分支
    Vue 项目搭建
  • 原文地址:https://www.cnblogs.com/skullboyer/p/8085335.html
Copyright © 2011-2022 走看看