STM32F401xx是意法半导体新推出的Cortex-M4内核的MCU,相较于已经非常流行的STM32F407xx和STM32F427xx等相同内核的MCU而言,其特点是功耗仅为128uA/MHz,且存在64pin封装的小封装器件。我设计一款新产品使用了STM32F401xx,想把自己熟悉的uC/OS-II实时操作系统移植到这款MCU上。懒得从底层开始从头移植,偷懒从原子的“探索者”开发板移植的uC/OS-II开始修改。完成后在板子上一跑,发现系统时钟总存在约5%的偏差。仔细搜索代码后才发现,问题在把原子的uC/OS-II移植直接用在STM32F401上时的一个小bug,把发现问题的过程和解决办法分享给大家。

以下原创内容欢迎网友转载,但请注明出处:http://cnblogs.com/helesheng

一、把探索者开发板移植的uC/OS-II用在STM32F401xx上

原子的探索者开发板使用了STM32F407ZG,其内核是和32F401xx 相同的Cortex-M4,外设也基本相同。简单地将原子在探索者开发板上移植的uC/OS-II工程中的Device修改为STM32F401RC,编译后发现大量的预定义找不到。想到可能是代表处理器的预定义的宏没有修改,在Option中的C/C++页中,将Preprocessor Symbols改为代表401的“STM32F401xx,USE_STDPERIPH_DRIVER”,直接编译通过,心中一阵窃喜。

图1 修改预定义

二、uC/OS-II系统时钟偏差的小问题

运行之前在其它款STM32上写的uC/OS-II程序,开始一切顺利,但随后用示波器仔细分析各个任务内部及相互间的时间关系时,发现总存在+5%左右的时间误差,即实际系统时钟的周期只有理论系统时钟的95%左右。以每秒系统节拍数OS_TICKS_PER_SEC设置为200为例,每个OSTimeDly(1);的任务延迟仅为4750us。

开始以为是原子编写的延迟函数void delay_ms(u16 nms);的问题,仔细阅读代码后发现,这个函数只是在调用系统延迟函数OSTimeDly();的基础之上,将无法由系统延迟实现的us级延迟改由硬延迟实现。虽然我个人非常不赞同这种做法,因为这会造成uC/OS-II时间调度的盲区,从而影响uC/OS-II系统的实时性。但这不至于造成系统时钟的偏差,继续查找问题的原因。

既然调用系统延迟函数OSTimeDly的过程没有问题,那么只可能是系统时钟本身出了问题。Cortex-M内核的uC/OS移植都会用了SysTick定时器的中断构建系统时钟,因此在SysTick上找原因。打开MDK,连接自制的STM32F401电路板和仿真器,进入Debug模式,运行程序,让uC/OS完成初始化配置,然后暂停程序;在外设(peripheral)菜单中找到SysTick定时器,界面如下图所示。

图2 System tick定时器状态监视器

其中重装寄存器中的值为0xC350,即50_000,仔细一想发现有问题——STM32F401的主频为84MHz,那要达到200Hz的系统时钟,无论如何都不可能把System Tick的初值配置为50_000啊!于是开始查找uC/OS移植代码中配置System Tick的部分,原来在探索者开发板移植代码中初始化延迟函数delay_init();中。看看原子的代码。

图3 delay_init();函数原来的代码

原子的代码简洁清晰,将System Tick的时钟配置为AHB时钟的1/8,在计算System Tick的初值。其中红圈中的一句是计算AHB时钟的八分之一,为后续计算定时器初始值做准备。但进一步仔细查看后发现变量SYSCLK中存放的AHB时钟数是以MHz作为单位的,对STM32F401xx而言,就是84。84无法整除8,而赋值语句左边的变量reload却是int型变量,从而导致了红圈中的一句计算误差。这样即使后一句将reload的单位切换回了Hz,也无法挽回前一句无法整除造成的计算误差。而这真是uC/OS系统时钟误差5%的真正原因!对这两句进行简单修改——现将SYSCLK折算为以Hz为单位,即可保证足够的计算精度。

图4 修改过的delay_init();函数代码

修改过后,uC/OS的系统时钟又恢复了原有的准确性。

究其原因并不是原子探索者开发板移植的uC/OS的问题,因为探索者采用的STM32F407ZG运行在168MHz,能够整除8,不存在这个问题。这里给大家展示这个过程,一是给大家在STM32F401上移植uC/OS做些探索,二是分享一下嵌入式调试和查找问题的点滴思路和心得。

在STM32F401上移植uC/OS的一个小问题 [原创]的更多相关文章

  1. FMX相当于在界面上自己又做了一个小操作系统

    FMX的自画界面我也不看好,比如复制粘贴,太丑了,系统做得很好很精细的复制粘贴界面,就是无法调出,比如MIUI,复制粘贴还能有个放大镜,可以选择到屏幕边缘的文字,可以选择剪贴板内多个可粘贴的文字:还有 ...

  2. 关于uC/OS的简单学习(转)

    1.微内核 与Linux的首要区别是,它是一个微内核,内核所实现的功能非常简单,主要包括: 一些通用函数,如TaskCreate(),OSMutexPend(),OSQPost()等. 中断处理函数, ...

  3. uc/os iii移植到STM32F4---IAR开发环境

    也许是先入为主的原因,时钟用不惯Keil环境,大多数的教程都是拿keil写的,尝试将官方的uc/os iii 移植到IAR环境. 1.首先尝试从官网上下载的官方移植的代码,编译通过,但是执行会报堆栈溢 ...

  4. uC/OS - III 移植 IAR平台

    关于移植uC/OS-III 网上已经有很多教程了此处只是做个记录 首先下载源码然后解压得到下面的文件: 然后在模版工程里新建各种文件夹: 最后全部都添加进工程: OK了,编译一下,惊呆了,竟然 0错误 ...

  5. uC/OS II原理分析及源码阅读(一)

    uC/OS II(Micro Control Operation System Two)是一个可以基于ROM运行的.可裁减的.抢占式.实时多任务内核,具有高度可移植性,特别适合于微处理器和控制器,是和 ...

  6. 【小梅哥SOPC学习笔记】NIOS II处理器运行UC/OS II

    SOPC开发流程之NIOS II 处理器运行 UC/OS II 这里以在芯航线FPGA学习套件的核心板上搭建 NIOS II 软核并运行 UCOS II操作系统为例介绍SOPC的开发流程. 第一步:建 ...

  7. 在秉火STM32F429挑战者开发板上移植Huawei LiteOS指南

    昨天在B站上突然看到了一个短视频,是在正点原子的战舰V3开发板上移植华为的Huawei LiteOS操作系统,就是这个视频:看完鸿蒙OS发布会,试用华为的物联网操作系统Lite OS(B站),于是呢, ...

  8. 树莓派3b在rt-thread上移植LittlevGL

    树莓派3b在rt-thread上移植LittlevGL 目录 树莓派3b在rt-thread上移植LittlevGL 1.本文概述 2.资源准备 3.上手体验 4.rt-thread与lvgl进行无缝 ...

  9. 在 Linux 的 KVM虚拟机 上安装 Mac OS 系统的研究总结

    在 Linux 的 KVM虚拟机 上安装 Mac OS 系统的研究总结 一.资料来源:    网上一共找到两个方法,一个是视频上的教程,一个是网页资料. 二.视频资料方法内容:1.install qe ...

随机推荐

  1. 22、编译安装nginx及性能优化

    22.1.编译安装nginx: 1.下载nginx: [root@slave-node1 ~]# mkdir -p /tools/ [root@slave-node1 ~]# cd /tools/ [ ...

  2. Redis:Java链接redis单节点千万级别数据 写入,读取 性能测试

    本文是对Redis 单节点,针对不同的数据类型,做插入行测试. 数据总条数为:10058624 环境说明:             Redis 未做任何优化, 单节点    (服务器上, 内存64G) ...

  3. 8 shell if else

    if 语句的判断条件,从本质上讲,判断的就是命令的退出状态. 语句 语句格式 同一行书写 注意点 用例1 用例2 if 语句 if  conditionthen  statement(s)fi if  ...

  4. mysql过滤表中重复数据,查询相同数据的特定一条

    待操作的表如下: p.p1 { margin: 0; font: 16px Menlo; color: rgba(0, 0, 0, 1) } span.s1 { font-variant-ligatu ...

  5. (转) PHP实现从1累加到100(1+2+….+100=)的几种思路,挺有意思的!!!

    一个经典的小学问题也是一个简单的PHP小应用,1+2+3--100=多少?使用PHP应该怎么写? 这里总结了以下几种思路: 1.普通PHPer: $sum=0;for($i=1;$i<=100; ...

  6. Java程序设计(2021春)——第二章课后题(选择题+编程题)答案与详解

    Java程序设计(2021春)--第二章课后题(选择题+编程题)答案与详解 目录 Java程序设计(2021春)--第二章课后题(选择题+编程题)答案与详解 第二章选择题 2.1 面向对象方法的特性 ...

  7. C语言:打印所有char字符

    #include <stdio.h> int main() { int aa; char bla; for(aa=0;aa<=255;aa++) { if(aa%10==0 and ...

  8. [刘阳Java]_MySQL数据优化总结_查询备忘录

    数据库优化是在后端开发中必备技能,今天写一篇MySQL数据优化的总结,供大家看看 一.MySQL数据库优化分类 我们通过一个图片形式来看看数据优化一些策略问题 不难看出,优化有两条路可以选择:硬件与技 ...

  9. 【LeetCode】496.下一个更大元素I

    496.下一个更大元素I 知识点:栈:HashMap: 题目描述 给你两个 没有重复元素 的数组 nums1 和 nums2 ,其中nums1 是 nums2 的子集. 请你找出 nums1 中每个元 ...

  10. Hive——元数据表含义

    Hive--元数据表含义 1.VERSION   -- 查询版本信息   Field Type Comment   VER_ID bigint(20) ID主键   SCHEMA_VERSION va ...