#申请原创# #技术资源#[url=home.php?mod=space&uid=760190]@21小跑堂 [/url]
在ARM内核的程序中实际使用中会用到各种延时程序,实现延时的方式也有很多种,有人会直接用软件方法堆积NOP()来实现,这种方**收到主频和编译器的优化影响,经常会出现不稳定情况。有人会用硬件定时器来实现,这种方法可以有效规避编译器优化的影响,但这种方法的移植性不好,换芯片可能就要重新调试。还有一种小众的用法是使用DWT来实现,但这是一种系统外设,专门用来为Cortex-M3及其以上芯片提供调试和追踪的硬件辅助功能,但在Cortex-M0/m0+上是没有的,也限制的使用条件。综合来看使用systick是比较理想的选择,但systick也有被OS占用的场景。 难道就无解了吗?NO! 现在为大家分享一种依赖systick但又不影响systick,还能实现各种延时的库---perf_counter,perf_counter是个开源库(https://github.com/GorgonMeducer/perf_counter)有着非常好的兼容性,支持 Arm Compiler 5(armcc) 和 Arm Compiler 6(armclang)和其它编译器。它不仅提供了源代码,还提供了编译好的 library (.lib)可供全系列Cortex-M处理器使用。 perf_counter在完全不影响 SysTick 已有功能的前提下,继续把systick榨干,perf_counter提供多种功能。简要功能如下:
- 提供一个精确的 delay_us() 函数;
- 提供一个精确测量任意代码块所实际占用系统周期数的方法;
- 实现一个记录从进入 main() 函数以来总共经历了多少个时钟周期(且在合理的时间范围内不会溢出)的计数器(时间戳);
- 用户已有的 SysTick 功能不能受到干扰;
- 比如用户使用 SysTick 作为RTOS的基准时钟(非Tickless模式);
- 比如用户使用 SysTick 作为普通的毫秒级延时(就像前面例子代码所展示的那样);
- 用户不需要修改自己任何已有的 SysTick 代码。
下面我来介绍一下perf_counter库在SWM34S上的使用方法(已MDK为例)---使用perf_counter库文件(.lib文件形式) 首先下载perf_counter文件 将lib文件夹内的lib文件添加到要用的工程 添加库文件的头文件路径 在使用文件内添加头文件 添加perf_counter初始化函数,这里需要注意传递的参数,如果自己的程序已经使用systick,如果已经使用需要传参为ture,如果没有使用需要传参fales 编译工程会有个警告 需要将语法支持改为gnu99或gnu11 在void SysTick_Handler(void)中断函数内添加user_code_insert_to_systick_handler();添加user_code_insert_to_systick_handler();的方式有两种 第一种方式,直接在SysTick_Handler(void)中添加,入下图所示 第二种方式,是添加systick_wrapper_ual.s文件实现 systick_wrapper_ual.s,的假设条件是已经实现SysTick_Handler(void)函数,如果没有这个函数就会有如下报错,解决办法就是添加个SysTick_Handler(void)函数即可(里面不用加任何操作)。 systick_wrapper_ual.s文件是由汇编编写的,使用的是Arm的老语法(Unified Assembly Language),如果你的工程使用的是 ArmCompiler 5(armcc),这里就没什么需要特别注意的了;如果你的工程使用的是 Arm Compiler 6(armclang),则你需要检查工程配置,以确保MDK能正确的选择对应的Assembler: 讲过上述移植操作,就可以使用perf_counter相关API了 相关API使用例子如下 通过上述API的使用,可以看到perf_counter库在工程中的部署。实现了ms us的精确延时,并且提供了测量程序运行时间的方式,为我们程序的使用和调试提供了非常大的帮助。 perf_counter 库还提供了一种系统时间戳的方式,我还没研究透,这里就不再介绍 在使用perf_counter时需要注意的是确保使用SystemCoreClock与 CPU 频率相同。
perf_counter的部署方式还有其他方式,我这里只介绍了最简单的一种,其他方式在开源链接里有介绍,需要的可以自己去研究一下
|