硬汉嵌入式论坛

 找回密码
 立即注册
查看: 1795|回复: 6
收起左侧

使用FreeRTOS在SD卡驱动使用非系统延时导致上电重启不工作的情况

[复制链接]

5

主题

109

回帖

124

积分

初级会员

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

使用道具 举报

1万

主题

6万

回帖

10万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
107101
QQ
发表于 2017-12-7 11:36:09 | 显示全部楼层
把你函数void DemoFatFS(void)里面的while大循环加上,不要注释,而函数static void vTaskMsgPro(void *pvParameters)里面的  vTaskDelay(300);注释掉。

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

使用道具 举报

5

主题

109

回帖

124

积分

初级会员

积分
124
 楼主| 发表于 2017-12-7 14:00:57 | 显示全部楼层

回 eric2013 的帖子

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

并将你的 bsp_DelayMS(100);   函数所在位置修改为 vTaskDelay(100);就行。 (2017-12-07 11:36)
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开发板上运行正常,所以原因不是不能使用,应该是我的使用方式有问题,或是有些地方未注意到,恳请帮忙分析教导[s:151]
回复

使用道具 举报

1万

主题

6万

回帖

10万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
107101
QQ
发表于 2017-12-7 15:09:01 | 显示全部楼层

回 打洞者 的帖子

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

2. 将非系统延时函数bsp_DelayMS(100)替换为系统延时函数vTaskDelay(100),经测试工作正常,我想问的是非系统延时函数 .. (2017-12-07 14:00) 
1. 这个是阻塞式的延迟,这个任务阻塞后,低于此优先级的任务将得不到执行。
2. 那个是驱动,驱动仅调用一次,在bsp_Init初始化的时候仅调用一次,任务执行的时候不会再使用。
回复

使用道具 举报

5

主题

109

回帖

124

积分

初级会员

积分
124
 楼主| 发表于 2017-12-7 20:33:03 | 显示全部楼层

回 eric2013 的帖子

eric2013:

1. 这个是阻塞式的延迟,这个任务阻塞后,低于此优先级的任务将得不到执行。
2. 那个是驱动,驱动仅调用一次,在bsp_Init初始化的时候仅调用一次,任务执行的时候不会再使用。
1. 可以理解为任务中不可以使用非系统延时函数?
2. 我做了如下实验
哈哈哈.png
上表中包括我的测试条件及个人一些理解,和最终的疑问。
3.为了规避这样的事情发生,在任务中只使用系统延时函数即可,但有些情况使用非系统延时函数较为方便,比如某些设备的Demo,因为这些设备Demo程序会单独存在于文件中,或是在不考虑操作系统时而写的一些应用程序等。为了研究本质刨根问底,个人觉得还是有必要知晓其中机理,在此感谢大家了。
回复

使用道具 举报

1万

主题

6万

回帖

10万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
107101
QQ
发表于 2017-12-8 01:17:45 | 显示全部楼层

回 打洞者 的帖子

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

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

使用道具 举报

5

主题

109

回帖

124

积分

初级会员

积分
124
 楼主| 发表于 2017-12-8 09:25:25 | 显示全部楼层

回 eric2013 的帖子

eric2013:1. 可以加,比如DS18B20这种,是要加的微妙延迟的。
2. 以系统断电后重新上电为准。关于这个第2个问题,后面还是需要深入学习下RTOS工作原理。通过本质理解现象的效率更高些。
3. 这种大延迟,死等的程序一定要修改,最好改成事件触发的方式,后面你改的多了就熟练了。需要慢慢从 .. (2017-12-08 01:17) 
好的 多谢
暂且如此吧 待深入后续贴
回复

使用道具 举报

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

本版积分规则

QQ|小黑屋|Archiver|手机版|硬汉嵌入式论坛

GMT+8, 2024-5-18 05:31 , Processed in 0.259120 second(s), 28 queries .

Powered by Discuz! X3.4 Licensed

Copyright © 2001-2023, Tencent Cloud.

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