痞子衡嵌入式:介绍i.MXRT定时器PIT的多通道链接模式及其在coremark测试工程里的应用
大家好,我是痞子衡,是正经搞技术的痞子。今天痞子衡给大家介绍的是i.MXRT定时器PIT的多通道链接模式及其在coremark测试里的应用。
早在 2018 年 i.MXRT 系列跨界处理器刚推出的时候,痞子衡就写了一篇 《i.MXRT1052性能实测(CoreMark)》,文章详细介绍了在 i.MXRT 上如何一步一步地移植标准 coremark 程序,这篇文章阅读量还不错,据说很多人移植 coremark 都是看得这篇文章。
当时痞子衡把移植好的 coremark 工程也一起开源了出来,并且这个仓库痞子衡也是在不断维护的(增加新 MCU 型号支持,以及除了 coremark 之外的一些其他经典程序)。最近有同事向痞子衡反映,这个 coremark 测试工程里关于计时部分有一些可以改进的地方,痞子衡看了一下,确实可以改进,这便是今天本文要聊的主题:
一、i.MXRT上的定时器简介
工欲善其事,必先利其器。在改进 coremark 测试工程里计时功能之前,我们先来了解一下 i.MXRT 上都有哪些跟计时/计数相关的模块,分别是什么特点,下面是详细列表。单从计时功能角度考虑,SysTick、GPT、PIT、TMR 都是不错的选择。
| 定时器 | 基本特性 | 应用特色 |
|---|---|---|
| SysTick | 24bit 计数器 | 系统(内核)时钟节拍 |
| GPT | 32bit 计数器 | 计时,外部信号捕获,比较 |
| PIT | 32bit 计数器 x 4 ch(可级联) | 系统生命周期计时,触发DMA |
| TMR | 16bit 计数器 x 4 ch(可级联) | 混合功能:计时,信号捕获,正交解码 |
| eFlexPWM | 16bit 计数器 x 6 ch | PWM信号生成 |
| QDC | 16bit,32bit - 5 ch | 连接位置/速度传感器,正交解码 |
| WDOG | 给定时间选项/16bit | 系统复位 |
二、计时设计对coremark测试程序影响
我们知道 coremark 标准的测试逻辑是在某配置参数组合下单位时间内跑了多少次 coremark 程序,一般情况下要求至少跑 10s 以上,因此计时部分的设计是很重要的。
在早期 i.MXRT1050 coremark 工程里,痞子衡选用了 PIT(channel 0 - 32bit)负责计时,为 PIT 配置的时钟源是 24MHz 外部 OSC,定时器一次超时耗时约 178s,这种情况下,痞子衡也没有使能 PIT 中断,假定了一次 coremark 程序跑完不会碰到超时的情况,但显然这种设计是不完善的。
此外我们知道定时器时钟源频率越高,计时粒度越细,计时时间也就越精确。大部分定时器时钟源都可以配到系统 IPG bus 总线频率(在 i.MXRT10xx 上可到 125MHz/150MHz,在 i.MXRT1170 上可到 240MHz),我们可以尝试将定时器设到最高频率的时钟源,这时候就不得不考虑定时器超时中断处理问题了。
使能定时器超时中断,可以保证计时的严谨性,解决了 coremark 程序运行时间和次数的限制。但是频繁的定时器中断响应也会不断打断 coremark 程序的执行,对最终跑分结果产生不利影响,这个问题同样需要解决。
三、PIT定时器多通道链接模式
前面说了 SysTick、GPT、PIT、TMR 都可以用作 coremark 测试工程定时器,但最终痞子衡还是选定了 PIT,因为 PIT 是最适合作为系统运行生命周期总计时器的,这主要得益于 PIT 内部有 4 个 32bit 计时器,并且可以链接使用(串连)。
要是将 4 个 32bit 计数器串成一个 128bit 超强计数器(channel 0 计数溢出,channel 1 计数加 1...),即使系统运行到地老天荒都不会出现一次超时(这里指最后一链 channel 3 中断触发),所以也就根本不用管定时器中断处理的事。
PIT 通道链接模式使能也很简单,主要在 PIT->CHANNEL[x].TCTRL[CHN] 位上,这个位开启后,channel x 就和 channel x-1 连了起来。下面是 channel 0 和 channel 1 串连组成 64bit 计数器的初始化代码:
void timer_pit_init(void)
{
// Turn on PIT: MDIS = 0, FRZ = 0
PIT->MCR = 0x00;
// Set up timer 1 to max value
PIT->CHANNEL[1].LDVAL = 0xFFFFFFFF; // setup timer 1 for maximum counting period
PIT->CHANNEL[1].TCTRL = 0; // Disable timer 1 interrupts
PIT->CHANNEL[1].TFLG = 1; // clear the timer 1 flag
PIT->CHANNEL[1].TCTRL |= PIT_TCTRL_CHN_MASK; // chain timer 1 to timer 0
PIT->CHANNEL[1].TCTRL |= PIT_TCTRL_TEN_MASK; // start timer 1
// Set up timer 0 to max value
PIT->CHANNEL[0].LDVAL = 0xFFFFFFFF; // setup timer 0 for maximum counting period
PIT->CHANNEL[0].TFLG = 1; // clear the timer 0 flag
PIT->CHANNEL[0].TCTRL = PIT_TCTRL_TEN_MASK; // start timer 0
}
实际上我们也根本不需要 128bit 计数器,64bit 计数器就完全够用了,就以 150MHz 时钟源来说,超时一次需要约 3899 年,谁需要操心 3899 年后的事情呢?此外,在 channel 0 和 channel 1 串联的情况下,PIT 还提供了一个 64bit lifetime 计数器,直接读这个计数器就能获取当前 channel 0,1 串连的计数值,不用考虑手动读 channel 0,1 计数值可能会发生的潜在翻转问题(rollover)。
你看,使能了 PIT 通道链接用法后就完美地解决了 coremark 测试程序计时设计问题。
uint64_t timer_pit_get_ticks() {
uint64_t valueH;
volatile uint32_t valueL;
#if defined(FSL_FEATURE_PIT_HAS_LIFETIME_TIMER) && (FSL_FEATURE_PIT_HAS_LIFETIME_TIMER == 1)
valueH = PIT->LTMR64H;
valueL = PIT->LTMR64L;
#else
do
{
valueL = PIT->CHANNEL[0].CVAL;
valueH = PIT->CHANNEL[1].CVAL;
} while (valueL < PIT->CHANNEL[0].CVAL);
#endif // FSL_FEATURE_PIT_HAS_LIFETIME_TIMER
return ~((valueH << 32) | valueL);
}
四、关于coremark上计时的其他改进点
最后再提两个 coremark 测试程序设计小改进点,一是在一些双核型号上(比如 i.MXRT1170, CM7 和 CM4),如果两个核同时跑 coremark 程序要用到不同 PIT 的话,需要检查它们是不是共用一个时钟开关,防止出现 CM7 上跑完了 coremark 之后关掉 PIT,影响 CM4 那边 coremark 程序对 PIT 寄存器的访问。
第二个改进点是 core_main.c 里的 main() 函数在打印 Total ticks 时会将 u64 型的 total_time 变量强制转为 u32 型,以便于 %lu 格式化输出(32位无符号整数),这里最好还是保留原来 u64 精度,痞子衡尝试了 %llu 格式化输出(64位无符号整数),结果在 ee_printf() 下不生效,所以做了个如下手动转换版:
MAIN_RETURN_TYPE main(void) {
// 代码省略...
uint64_t total_time;
total_time=get_time();
//ee_printf("Total ticks : %lu\n",(ee_u32)total_time);
if (total_time & (~(uint64_t)0xFFFFFFFF))
{
ee_printf("Total ticks : ");
ee_printf("%lu", (ee_u32)(total_time / 1000000000));
ee_printf("%lu\n",(ee_u32)(total_time % 1000000000));
}
else
{
ee_printf("Total ticks : %lu\n",(ee_u32)total_time);
}
// 代码省略...
}
至此,i.MXRT定时器PIT的多通道链接模式及其在coremark测试里的应用痞子衡便介绍完毕了,掌声在哪里~~~
欢迎订阅
文章会同时发布到我的 博客园主页、CSDN主页、知乎主页、微信公众号 平台上。
微信搜索"痞子衡嵌入式"或者扫描下面二维码,就可以在手机上第一时间看了哦。

痞子衡嵌入式:介绍i.MXRT定时器PIT的多通道链接模式及其在coremark测试工程里的应用的更多相关文章
- 痞子衡嵌入式:i.MXRT中FlexSPI外设对AHB Burst Read特性的支持
大家好,我是痞子衡,是正经搞技术的痞子.今天痞子衡给大家介绍的是FlexSPI外设对AHB Burst Read特性的支持. 痞子衡之前写过一篇关于FlexSPI LUT的文章 <从头开始认识i ...
- 痞子衡嵌入式:串行NOR Flash的Continuous read模式下软复位后i.MXRT无法启动问题解决方案之RESET#
大家好,我是痞子衡,是正经搞技术的痞子.今天痞子衡给大家介绍的是i.MXRT上使能NOR Flash的Continuous read模式在软复位后无法正常启动问题的解决经验. 前一篇文章 <在i ...
- 痞子衡嵌入式:i.MXRT中不支持DQS的FlexSPI引脚组连接Flash下载与启动注意事项
大家好,我是痞子衡,是正经搞技术的痞子.今天痞子衡给大家分享的是i.MXRT中不支持DQS的FlexSPI引脚组连接Flash下载与启动注意事项. 最近痞子衡在支持一个印度客户,这个客户项目主芯片选择 ...
- 痞子衡嵌入式:i.MXRT全系列下FlexSPI外设AHB Master ID定义与AHB RX Buffer指定的异同
大家好,我是痞子衡,是正经搞技术的痞子.今天痞子衡给大家介绍的是i.MXRT全系列下FlexSPI外设AHB Master ID定义与AHB RX Buffer指定的异同. 因为 i.MXRT 全系列 ...
- 痞子衡嵌入式:i.MXRT连接特殊Octal Flash时(OPI DTR模式下反转字节序)下载与启动注意事项(以MX25UM51245为例)
大家好,我是痞子衡,是正经搞技术的痞子.今天痞子衡给大家介绍的是OPI DTR模式下反转字节序的Octal Flash在i.MXRT下载与启动注意事项. 在恩智浦官方参考设计板 MIMXRT595-E ...
- 痞子衡嵌入式:i.MXRT中FlexSPI外设不常用的读选通采样时钟源 - loopbackFromSckPad
大家好,我是痞子衡,是正经搞技术的痞子.今天痞子衡给大家分享的是i.MXRT中FlexSPI外设不常用的读选通采样时钟源 - loopbackFromSckPad. 最近碰到一个客户,他们在 i.MX ...
- 痞子衡嵌入式:串行NOR Flash的页编程模式对于量产时间的影响
大家好,我是痞子衡,是正经搞技术的痞子.今天痞子衡给大家分享的是串行NOR Flash的页编程模式对于量产时间的影响. 任何嵌入式产品最终都绕不开量产效率话题,尤其是对于主控是非内置 Flash 型 ...
- 痞子衡嵌入式:IAR在线调试时设不同复位类型可能会导致i.MXRT下调试现象不一致(J-Link / CMSIS-DAP)
大家好,我是痞子衡,是正经搞技术的痞子.今天痞子衡给大家分享的是IAR在线调试时设不同复位类型可能会导致i.MXRT下调试现象不一致. 做Cortex-M内核MCU嵌入式软件开发,可用的集成开发环境( ...
- 痞子衡嵌入式:Keil在线调试时设不同复位类型可能会导致i.MXRT下调试现象不一致(J-Link/DAPLink)
大家好,我是痞子衡,是正经搞技术的痞子.今天痞子衡给大家分享的是Keil在线调试时设不同复位类型可能会导致i.MXRT下调试现象不一致. 本篇是 <IAR EWARM复位类型>.<M ...
随机推荐
- Ubuntu16安装Nvidia驱动(GTX1060显卡)
欢迎访问我的GitHub https://github.com/zq2599/blog_demos 内容:所有原创文章分类汇总及配套源码,涉及Java.Docker.Kubernetes.DevOPS ...
- HDU 1576 A/B (两种解法)
原题链接:http://acm.hdu.edu.cn/showproblem.php?pid=1576 分析:等式枚举法,由题意可得:, ,代入 , 得:,把变量 合在一起得: :即满足 为 倍 ...
- python极简教程04:进程和线程
测试奇谭,BUG不见. 大家好,我是谭叔. 这一场,主讲python的进程和线程. 目的:掌握初学必须的进程和线程知识. 进程和线程的区别和联系 终于开始加深难度,来到进程和线程的知识点~ 单就这两个 ...
- 从AAB文件生成APK文件
开头先说方法 1.下载 bundletool 2.开始生成 java -jar bundletool.jar build-apks --bundle=[aab文件路径(例如:C:\Users\Admi ...
- IDEA maven 项目修改代码不生效,mvn clean、install 后才生效
Maven项目进行修改代码后我们重新运行代码,查看我们target目录下的class文件是否发生了变化. 如何查看class文件,鼠标移到项目,点击右键,然后点击 show in Explore ...
- Spring系列1:Spring基本概念
本文内容 什么是Spring? 为什么学Spring? 本系列包含哪些技术? 本系列适合哪些人? 什么是Spring? 基本概念 Spring 框架为现代基于 Java 的企业应用程序提供了一个全面的 ...
- echart 横轴倾斜
xAxis: [ { type: 'category', data:[], axisLabel: { interval:0, rotate:40 }, grid: { left: '10%', bot ...
- JUC之线程池的实现原理以及拒绝策略
线程池实现原理 向线程池提交任务后,线程池如何来处理这个任务,之前我们了解了7个参数,我们通过这些参数来串联其线程池的实现原理. 1.在创建了线程池后,开始等待请求 2.当调用execute()方法添 ...
- 【解决了一个小问题】golang xorm中使用where id in (xxx),没办法使用参数替换
代码中使用XORM来从数据库查询数据,有类似如下的代码: session.Where("id in (?)", strings,Join(arr, ",")) ...
- Open虚拟专用网络
目录 一:OpenVPN虚拟网络专用 1.简介: 2.OpenVPN的作用 3.远程访问VPN服务 4.OpenVPN两种类型的VPN体系结构 5.全面解析OpenVPN执行流程 6.Openvpn定 ...