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. 运行cmd时提示你可能没有适当的权限访问该项目

    Windows无法访问指定设备.路径或文件.你可能没有适当的权限访问该项目.   方法/步骤   在C:\Windows\System32目录下中找到cmd.exe文件   右键点击 "属性 ...

  2. iOS工程师如何恍然大悟?

    聊聊行情?为什么总有人在乎旁人的看法而忽略自己的初衷? 虽然iOS开发市场说不上好但也绝不算坏,想没想过那些煽风点火说iOS不行的人在做什么? 真的转行从头开始? 错.大错特错! 在劝退你的同时他们会 ...

  3. Blazor 组件入门指南

    翻译自 Waqas Anwar 2021年3月19日的文章 <A Beginner's Guide to Blazor Components> [1] Blazor 应用程序是组件的组合, ...

  4. 解决MyEclipse一直在Updating indexes的文题

    Updating indexes是Maven在下载更新,这个需要手动去设置即可:  Window --> Preferences --> Maven4MyEclipse --> 去除 ...

  5. [转]12个scp传输文件的命令栗子

    原文地址: https://www.cnblogs.com/voidy/p/4215891.html copy原文是为了修改部分错误以及便于记录自己的笔记.英文原文点:这里 安全复制 Scp(Secu ...

  6. wireshark 调试 https/http2和grpc流量

    本文浏览器以 Chrom 为例 平常需要抓包的场景比较少,记录一下防止下次忘记配置 1. 解析 TLS 在本地创建用于保存 ssl logfile 的文件(文件可以存放到任意位置), 并添加到环境变量 ...

  7. Linux从头学03:如何告诉 CPU,代码段、数据段、栈段在内存中什么位置?

    作 者:道哥,10+年的嵌入式开发老兵. 公众号:[IOT物联网小镇],专注于:C/C++.Linux操作系统.应用程序设计.物联网.单片机和嵌入式开发等领域. 公众号回复[书籍],获取 Linux. ...

  8. CF1444D Rectangular Polyline[题解]

    Rectangular Polyline 题目大意 给定 \(h\) 条长度分别为 \(l_1,l_2,--,l_h\) 的水平线段以及 \(v\) 条长度分别为 \(p_1,p_2,--.p_v\) ...

  9. passwd 简单记录

    passwd [选项] 登录名 -e,--expire 强制用户密码过期 这时候需要使用root账户给tel用户重新设置密码 -l,--lock 锁定指定用户密码 -u, --unlock 给指定账户 ...

  10. SQLITE数据库不支持远程访问

    SQLITE数据库不支持远程访问 import sqlite3 conn=sqlite3.connect("dailiaq.db") cur=conn.cursor() def c ...