一、问题描述
在一个使用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)工程代码

 int main(void)
{
    /*
      在启动调度前,为了防止初始化STM32外设时有中断服务程序执行,这里禁止全局中断(除了NMI和HardFault)。
      这样做的好处是:
      1. 防止执行的中断服务程序中有FreeRTOS的API函数。
      2. 保证系统正常启动,不受别的中断影响。
      3. 关于是否关闭全局中断,大家根据自己的实际情况设置即可。
      在移植文件port.c中的函数prvStartFirstTask中会重新开启全局中断。通过指令cpsie i开启,__set_PRIMASK(1)
      和cpsie i是等效的。
     */
    __set_PRIMASK();  
    
    /* 硬件初始化 */
    bsp_Init();
    
    /* 创建任务 */
    AppTaskCreate();
    
    /* 启动调度,开始执行任务 */
    vTaskStartScheduler();     /*
      如果系统正常启动是不会运行到这里的,运行到这里极有可能是用于定时器任务或者空闲任务的
      heap空间不足造成创建失败,此要加大FreeRTOSConfig.h文件中定义的heap大小:
      #define configTOTAL_HEAP_SIZE          ( ( size_t ) ( 30 * 1024 ) )
    */
    while();
} /*
*********************************************************************************************************
*    函 数 名: vTaskTaskUserIF
*    功能说明: 接口消息处理,这里用作LED闪烁    
*    形    参: pvParameters 是在创建该任务时传递的形参
*    返 回 值: 无
*   优 先 级: 1  (数值越小优先级越低,这个跟uCOS相反)
*********************************************************************************************************
*/
static void vTaskTaskUserIF(void *pvParameters)
{
    while()
    {
        bsp_LedToggle();
        vTaskDelay();
    }
} /*
*********************************************************************************************************
*    函 数 名: vTaskLED
*    功能说明: LED闪烁    
*    形    参: pvParameters 是在创建该任务时传递的形参
*    返 回 值: 无
*   优 先 级: 2  
*********************************************************************************************************
*/
static void vTaskLED(void *pvParameters)
{
    while()
    {
        bsp_LedToggle();
        vTaskDelay();
    }
} /*
*********************************************************************************************************
*    函 数 名: vTaskMsgPro
*    功能说明: 信息处理,这里是用作LED闪烁    
*    形    参: pvParameters 是在创建该任务时传递的形参
*    返 回 值: 无
*   优 先 级: 3  
*********************************************************************************************************
*/
static void vTaskMsgPro(void *pvParameters)
{
    while()
    {
        DemoFatFS();
        vTaskDelay();
    }
} /*
*********************************************************************************************************
*    函 数 名: vTaskStart
*    功能说明: 启动任务,也就是最高优先级任务,这里用作LED闪烁
*    形    参: pvParameters 是在创建该任务时传递的形参
*    返 回 值: 无
*   优 先 级: 4  
*********************************************************************************************************
*/
static void vTaskStart(void *pvParameters)
{
    while()
    {
        /* 按键扫描 */
        bsp_LedToggle();
        vTaskDelay();
    }
} /*
*********************************************************************************************************
*    函 数 名: AppTaskCreate
*    功能说明: 创建应用任务
*    形    参:无
*    返 回 值: 无
*********************************************************************************************************
*/
static void AppTaskCreate (void)
{
    xTaskCreate( vTaskTaskUserIF,       /* 任务函数  */
                 "vTaskUserIF",         /* 任务名    */
                 ,                   /* 任务栈大小,单位word,也就是4字节 */
                 NULL,                  /* 任务参数  */
                 ,                     /* 任务优先级*/
                 &xHandleTaskUserIF );  /* 任务句柄  */
    
    
    xTaskCreate( vTaskLED,            /* 任务函数  */
                 "vTaskLED",          /* 任务名    */
                 ,                 /* 任务栈大小,单位word,也就是4字节 */
                 NULL,                /* 任务参数  */
                 ,                   /* 任务优先级*/
                 &xHandleTaskLED ); /* 任务句柄  */
    
    xTaskCreate( vTaskMsgPro,             /* 任务函数  */
                 "vTaskMsgPro",           /* 任务名    */
                 ,                     /* 任务栈大小,单位word,也就是4字节 */
                 NULL,                   /* 任务参数  */
                 ,                       /* 任务优先级*/
                 &xHandleTaskMsgPro );  /* 任务句柄  */
    
    
    xTaskCreate( vTaskStart,             /* 任务函数  */
                 "vTaskStart",           /* 任务名    */
                 ,                    /* 任务栈大小,单位word,也就是4字节 */
                 NULL,                   /* 任务参数  */
                 ,                      /* 任务优先级*/
                 &xHandleTaskStart );   /* 任务句柄  */
}
 /*
*********************************************************************************************************
*    函 数 名: DemoFatFS
*    功能说明: FatFS文件系统演示主程序
*    形    参:无
*    返 回 值: 无
*********************************************************************************************************
*/
void DemoFatFS(void)
{
    uint8_t cmd;     /* 打印命令列表,用户可以通过串口操作指令 */
    DispMenu();
//    while(1)
    {
        bsp_Idle();        /* 这个函数在bsp.c文件。用户可以修改这个函数实现CPU休眠和喂狗 */         if (comGetChar(COM1, &cmd))    /* 从串口读入一个字符(非阻塞方式) */
        {
            printf("\r\n");
            switch (cmd)
            {
                case '':
                    printf("【1 - ViewRootDir】\r\n");
                    ViewRootDir();        /* 显示SD卡根目录下的文件名 */
                    break;                 case '':
                    printf("【2 - CreateNewFile】\r\n");
                    CreateNewFile();        /* 创建一个新文件,写入一个字符串 */
                    break;                 case '':
                    printf("【3 - ReadFileData】\r\n");
                    ReadFileData();        /* 读取根目录下armfly.txt的内容 */
                    break;                 case '':
                    printf("【4 - CreateDir】\r\n");
                    CreateDir();        /* 创建目录 */
                    break;                 case '':
                    printf("【5 - DeleteDirFile】\r\n");
                    DeleteDirFile();    /* 删除目录和文件 */
                    break;                 case '':
                    printf("【6 - TestSpeed】\r\n");
                    WriteFileTest();    /* 速度测试 */
                    break;                 default:
                    DispMenu();
                    break;
            }
        }
        
//        bsp_DelayMS(100);            /* 此延时将导致板子重新上电不工作 */
        
        /* 按键滤波和检测由后台systick中断服务程序实现,我们只需要调用bsp_GetKey读取键值即可。 */
        switch (bsp_GetKey())    /* bsp_GetKey()读取键值, 无键按下时返回 KEY_NONE = 0 */
        {
            case KEY_DOWN_K1:            /* K1键按下 */
                break;             case KEY_UP_K1:                /* K1键弹起 */
                break;             case KEY_DOWN_K2:            /* K2键按下 */
                break;             case KEY_UP_K2:                /* K2键弹起 */
                break;             case KEY_DOWN_K3:            /* K3键按下 */
                break;             case KEY_UP_K3:                /* K3键弹起 */
                break;             case JOY_DOWN_U:            /* 摇杆UP键按下 */
                break;             case JOY_DOWN_D:            /* 摇杆DOWN键按下 */
                break;             case JOY_DOWN_L:            /* 摇杆LEFT键按下 */
                break;             case JOY_DOWN_R:            /* 摇杆RIGHT键按下 */
                break;             case JOY_DOWN_OK:            /* 摇杆OK键按下 */
                break;             case JOY_UP_OK:                /* 摇杆OK键弹起 */
                break;             case KEY_NONE:                /* 无键按下 */
            default:
                /* 其它的键值不处理 */
                break;
        }
    }
}

问题就在上段代码第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

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

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

  1. sd 卡驱动--基于高通平台

    点击打开链接 内容来自以下博客: http://blog.csdn.net/qianjin0703/article/details/5918041 Linux设备驱动子系统第二弹 - SD卡 (有介绍 ...

  2. SD卡驱动分析(二)

    三.下面分析一下高通的android2.3的代码中SD卡驱动的流程. 在kernel中,SD卡是作为平台设备加入到内核中去的,在/kernel/arch/arm/mach-msm/devices-ms ...

  3. SD卡驱动分析(一)

    Android下的SD卡驱动与标准LINUX下的SD卡驱动好像没有太大的区别,这里就以高通的ANDROID 2.3以代表,来简要分析一下LINUX下SD卡驱动的写法.由于小弟的技术有限,分析的有错的地 ...

  4. tiny4412 --Uboot移植(6) SD卡驱动,启动内核

    开发环境:win10 64位 + VMware12 + Ubuntu14.04 32位 工具链:linaro提供的gcc-linaro-6.1.1-2016.08-x86_64_arm-linux-g ...

  5. NUC972当检测到sd卡时,在sd卡驱动中操作gpio开启sd卡的电源,解决sd卡因低电压有时识别不正常的问题

    1.根据硬件原理图,找到对应控制sd卡电源的gpio引脚,并在sd卡驱动文件中定义操作改该引脚的宏 2.在sd卡检测函数中,使用glib增加开sd卡电源的操作,如此当sd卡每次被检测到时,驱动中就会自 ...

  6. Linux SD卡驱动开发(四) —— SD 控制器之真正的硬件操作

    前面对SD卡控制器有了一个主要的介绍.事实上SD控制器层更过的意义是为core层提供一种操作SD卡硬件的一种方法.当然不同的控制器对硬件控制的方法不尽同样,可是他们终于都能像core层提交一个统一的封 ...

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

    作者信息 作者: 彭东林 邮箱:pengdonglin137@163.com QQ:405728433 平台简介 开发板:tiny4412ADK + S700 + 4GB Flash 要移植的内核版本 ...

  8. SD卡 驱动层测速

    init_timer(&timer1); timer1.function = test_time; timer1.data = ; timer1.expires = jiffies + mse ...

  9. sd卡脱机烧写系统的方法(测试成功)

    一.sd卡烧写系统的基本思路: (1)把uboot.bin烧写到sd卡 (2)把image整个文件夹复制到sd卡 (3)开发板从sd卡启动,就开始自动烧写到nandflash中了. 二.烧写uboot ...

随机推荐

  1. 在SpringMVC中使用HandlerInterceptor来实现拦截器功能

    需求:我们需要在请求某些特定的URL(URL格式为Restful格式)时添加拦截器,以实现进行权限控制. 如:/ResourcePlan/projectCode/P1503127828/PROJECT ...

  2. 利用数据库触发器让字段与自增长Id相关联

    十年河东,十年河西,莫欺少年穷 学无止境,精益求精 今天是数据库脚本类的代码,所以不想过多阐述 如下数据表: create table Card( Id ,) primary key, CardNo ...

  3. MGR主从不一致问题排查与修复

    运行环境 linux:CentOS release 6.8 (Final) kernel:2.6.32-642.6.2.el6.x86_64 mysql Server version: 5.7.21- ...

  4. Python从菜鸟到高手(5):数字

    1 基础知识   Python语言与其他编程语言一样,也支持四则运算(加.减.乘.除),以及圆括号运算符.在Python语言中,数字分为整数和浮点数.整数就是无小数部分的数,浮点数就是有小数部分的数. ...

  5. java垃圾回收诡异现象

    在知乎上看到一篇提问,于是做了个实验帮助他解答,这里整理成一篇文章分享一下. 先看代码如下代码: /** * Created on 2017/12/16. * * -verbose:gc -XX:+U ...

  6. webvirtmgr-重命名kvm虚拟机的名称

    之前部署了Webvirtmgr平台管理kvm虚拟机,由于虚拟机在创建时名称是顺便起的,后续在虚拟机上部署了部分业务.为了便于管理,最好将虚拟机的名称重置下. 现在说下如何修改kvm中虚拟机的名称: 比 ...

  7. Mysql双主热备+LVS+Keepalived高可用操作记录

    MySQL复制能够保证数据的冗余的同时可以做读写分离来分担系统压力,如果是主主复制还可以很好的避免主节点的单点故障.然而MySQL主主复制存在一些问题无法满足我们的实际需要:未提供统一访问入口来实现负 ...

  8. linux-shell-命令总结

    第一种方法执行: 第二种方法执行: 第三种方法执行: 第四种方法:执行 第三种和第四种方法都是在新的进程里执行程序   函数方法 方法就是一个命令,命令写在字符串的第一个位置 type:可以接外部命令 ...

  9. 第一个Sprint

    项目名字:四则运算APP 开发环境:java 团队名称:会飞的小鸟 团队成员:陈志棚  李炫宗   刘芮熔  徐侃  罗伟业 一.经过宿舍世纪讨论后我们剔除了一些不合理的设计,比如网站管理员这一部分在 ...

  10. PAT 1033 旧键盘打字

    https://pintia.cn/problem-sets/994805260223102976/problems/994805288530460672 旧键盘上坏了几个键,于是在敲一段文字的时候, ...