使用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("\r\n");
 22             switch (cmd)
 23             {
 24                 case ‘1‘:
 25                     printf("【1 - ViewRootDir】\r\n");
 26                     ViewRootDir();        /* 显示SD卡根目录下的文件名 */
 27                     break;
 28
 29                 case ‘2‘:
 30                     printf("【2 - CreateNewFile】\r\n");
 31                     CreateNewFile();        /* 创建一个新文件,写入一个字符串 */
 32                     break;
 33
 34                 case ‘3‘:
 35                     printf("【3 - ReadFileData】\r\n");
 36                     ReadFileData();        /* 读取根目录下armfly.txt的内容 */
 37                     break;
 38
 39                 case ‘4‘:
 40                     printf("【4 - CreateDir】\r\n");
 41                     CreateDir();        /* 创建目录 */
 42                     break;
 43
 44                 case ‘5‘:
 45                     printf("【5 - DeleteDirFile】\r\n");
 46                     DeleteDirFile();    /* 删除目录和文件 */
 47                     break;
 48
 49                 case ‘6‘:
 50                     printf("【6 - TestSpeed】\r\n");
 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

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

时间: 2024-10-06 04:16:27

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

在CC2541上移植SD卡驱动

CC2541不知道现在还有没有人用,当初算是BLE芯片里头资料比较丰富的一个,只是硬件资源太菜了,51内核真是捉急.去年因为某些原因,在上面实现了SD卡驱动,估计还没有人做过,现在把过程发出来,让大家瞧瞧. CC2541本来是用于低功耗蓝牙通信的,一般也不会有人用来扩展SD卡.不过肯定还是存在一些特殊需求用户,对吧.高速的SD卡驱动一般都用SDIO总线,CC2541自然只能用SPI总线了,速度不会太快,SPI时钟只能到4M.而且受限于CC2541的BLE协议栈,不能存太多的东西,否则时间过长会影

CE SD卡驱动开发(Zylonite)(转)

2008-06-05 09:45 1. WINCE 下的SD卡驱动架构 Wince 下SD卡驱动协议栈组成 : HOST硬件底层部分 (主控制端驱动)       SDHC_XXX.DLL BUS 中间逻辑命令层 (总线驱动)         SDBUS.DLL CLIENT上层(客户端驱动)                SDMEMORY.DLL 主控制端驱动    主控制端驱动控制包含主控制器硬件,遵循主控制端驱动接口,它被用于总线驱动通信和设置操作参数.主控制器驱动接口提供一个硬件提取层,

制作SD(8G)卡Linux镜像,使得ZC706开发板可以从SD卡启动进入Linux系统

转自网络,供学习记录使用,红色部分是我实验时,这篇文章和网站稍有出入的地方. 目的:制作SD(8G)卡Linux镜像,使得ZC706开发板可以从SD卡启动进入Linux系统 在http://wiki.analog.com/resources/eval/user-guides/ad-fmcomms2-ebz/quickstart/zynq(姑且把这个链接成为链接1吧)链接中找到 图1 点击绿色字体的链接,下载镜像原始文件.这里有不同时期的版本,本说明中选择 图2 下载的原始文件为:2014_R2-

uboot移植之uboot中的SD卡驱动解析

1:地址对硬件操作的影响 (1)操作系统(指的是linux)下MMU肯定是开启的,也就是说linux驱动中肯定都使用的是虚拟地址.而纯裸机程序中根本不会开MMU,全部使用的是物理地址.这是裸机下和驱动中操控硬件的一个重要区别. (2)uboot早期也是纯物理地址工作的,但是现在的uboot开启了MMU做了虚拟地址映射,这个东西驱动也必须考虑.查uboot中的虚拟地址映射表,发现210开发板里面,除了0x30000000-0x3FFFFFFF映射到了0xC0000000-0xCFFFFFFF之外,

基于tiny4412的Linux内核移植 -- SD卡驱动移植(五)

作者信息 作者: 彭东林 邮箱:[email protected] QQ:405728433 平台简介 开发板:tiny4412ADK + S700 + 4GB Flash 要移植的内核版本:Linux-4.4.0 (支持device tree) u-boot版本:友善之臂自带的 U-Boot 2010.12 (为支持uImage启动,做了少许改动) busybox版本:busybox 1.25 SD卡:Kingston SDHC 4GB 交叉编译工具链: arm-none-linux-gnue

通过SD卡来安装Linux系统

一.制作SD启动卡(安装Linux)步骤: 烧写原理:superboot-6410.bin(bootloader)+内核镜像文件+根文件系统 1.将SD卡插入USB接口的读卡器,并插在PC的USB口 2.在SD卡目录下新建“images”目录 3.复制“superboot-6410.bin”到“images”目录下 4.在“images”目录下新建“Linux”子目录 5.分别复制内核镜像文件和跟文件系统镜像文件到“Linux”子目录 内核:zlmage 根文件系统 MLC:rootfs_qto

sd卡脱机烧写系统的方法

一.sd卡烧写系统的基本思路: (1)把uboot.bin烧写到sd卡 (2)把image整个文件夹复制到sd卡 (3)开发板从sd卡启动,就开始自动烧写到nandflash中了. 二.烧写uboot.bin到sd卡 (1)sd卡分区和格式化(烧写第一步) <1>把卡插入pc,windows下格式化 <2>点vm右下链接sd卡到linux,然后在终端输入: #dmesg|tail //查看挂载点 #df—h  //查看sd卡文件挂载位置 #umount /media/      /

ubuntu禁用n卡驱动(进系统卡死)

显卡驱动 该发行版依旧内置了Nouveau 开源驱动,这是导致频繁死机的直接原因.接下来要做的三件事情是: 禁用Nouveau 内核模块 安装Intel HD 530 驱动(二选一) 安装NVIDIA 闭源驱动(二选一) 禁用Nouveau 内核模块 首先添加一个blacklist: # vi /etc/modprobe.d/blacklist-nouveau.conf 在这个文件中写入以下内容: 1 2 3 4 5 blacklist nouveau blacklist lbm-nouveau

非热插拔的SD卡在userDebug版本上可以识别,在user版本上偶尔不能识别

hi,      非热插拔的SD卡在userDebug版本上可以识别,在user版本上偶尔不能识别,不能识别的原因是kernel log中根本就没有检测到卡.user版本不能识别的概率在50%左右.userdebug都可以识别. 而user和userdebug的kernel在时间和速度上有些差别,sd卡驱动是否会有同步方面的bug?还是其他什么原因 >>>>>>>>>>>>>>>>>>>>