08.TMS570LC43入门指南——RTI模块
文章目录
- 08.TMS570LC43入门指南——RTI模块
- 一、简介
- 二、认识 RTI
- 2.1 特性
- 2.2 总体模块介绍
- 2.3 计数操作介绍
- 2.4 中断/DMA 请求
- 三、项目实现
- 3.1 硬件部分
- 3.2 软件部分
- 3.2.1 HALCoGen 配置
- 3.2.2 CCS 配置
- 3.2.3 运行结果
- 五、写在最后
一、简介
在本章中,我们将学习使用 RTI
。了解过 STM32
系列芯片的朋友应该都知道,其拥有一个滴答定时器(Systick
),而在 TMS570LC43
上,也拥有类似的模块,其就是 —— RTI
。
通过本文,你将学习到以下内容:
- 认识
RTI
模块 - 使用
RTI
模块完成定时中断的相关操作
首先需要了解一下我所使用的开发环境:
- Windows 10 x64
- TMS570LC43开发板
二、认识 RTI
RTI
全称叫 Real-Time Interrupt Module
,即 实时中断模块。其也可以用于为 RTOS
系统提供时基。
2.1 特性
RTI
模块具有以下特点:
- 拥有两个 64 位计数器
- 拥有四个可配置的比较器用于生成操作系统的时基或
DMA
请求。每个事件可以由计数器 0 或 计数器 1 驱动 - 拥有一个可用于应用程序同步到
FlexRay
网络的计数器,其也能实现时钟校验功能 - 拥有快速使能/去使能事件
- 拥有两个时间戳(捕获)函数,用于系统或外设中断,每个计数器一个
- 拥有数字带窗看门狗
2.2 总体模块介绍
如下图所示为 RTI
框架示意图:
从图中我们可以知道,RTI
模块拥有两个 64 bit 的计数块。其中计数块 0 拥有额外的 FlexRay Macrotick(NTU0)
及 FlexRay Start of Cycle(NTU1)
功能模块。
比较单元将计数器与可编程值进行比较,当匹配时会产生四个独立的中断或 DMA
请求。每个比较寄存器都可以通过编程实现与计数器 0 或计数器 1 进行比较。
2.3 计数操作介绍
如下图所示为计数块框图:
如图中所示,每个计数器控制块都包含一个向上计数器(RTIUC0 或 RTIUC1)
和一个自由运行计数器 (RTIFRC0 或 RTIFRC1)
。
RTIUC0/1
由 RTICLK
时钟驱动,一直向上计数,直到到达向上比较计数器寄存器 (RTICPUC0/1)
中的比较值。当比较值匹配的时候后,RTIFRC0/1
递增,RTIUC0/1
重置为 0。如果 RTIFRC0/1
溢出,则向 VIM
生成中断。而自由运行计数器 (RTIFRC0/1)
频率计算公式为:
f R T I F R C x = { f R T I C L K R T I C P U C x + 1 当 R T I C P U C x ≠ 0 f R T I C L K 2 32 + 1 当 R T I C P U x = 0 f_{RTIFRCx} = \left\{\begin{matrix} \frac{f_{RTICLK}}{RTICPUCx + 1} & 当 RTICPUCx \ne 0 \\ \frac{f_{RTICLK}}{2^{32} + 1} & 当 RTICPUx = 0 \end{matrix}\right. fRTIFRCx={RTICPUCx+1fRTICLK232+1fRTICLK当RTICPUCx=0当RTICPUx=0
注意:不建议将
RTICPUCx
设置为 0,否则将会使得向上计数器在溢出后的两个RTICLK
时钟周期内数值为 0。
2.4 中断/DMA 请求
该芯片使用四个比较寄存器(RTICOMPy)
用于实现对 VIM
的中断请求或对 DMA
控制器的 DMA
请求。可以使用中断为操作系统提供不同时间的时基。每一个比较寄存器都可以配置为与 DTIFRC0
或 RTIFRC1
进行比较。当计数值与设置的比较值相等后将会产生中断。为了允许周期性中断,可以自动添加某个数值到 RTICOMPy
的比较值中。该值存储在更新比较寄存器(RTIUDCPy)
中,并将在匹配比较后添加到 RTICOMPy
中。生成的中断/DMA请求的周期可以用下面的公式计算:
t C O M P x = t R T I C L K × ( R T I C P U C y + 1 ) × R T I U D C P y t_{COMPx}=t_{RTICLK} \times \left (RTICPUCy + 1 \right) \times RTIUDCPy tCOMPx=tRTICLK×(RTICPUCy+1)×RTIUDCPy
当 R T I C P U C y ≠ 0 RTICPUCy \ne 0 RTICPUCy=0 时:
t C O M P x = t R T I C L K × ( 2 32 + 1 ) × R T I U D C P y t_{COMPx}= t_{RTICLK} \times \left(2^{32} + 1 \right) \times RTIUDCPy tCOMPx=tRTICLK×(232+1)×RTIUDCPy
当 R T I C P U C y = 0 RTICPUCy = 0 RTICPUCy=0 时:
t C O M P x = t R T I C L K × ( R T I C P U C y + 1 ) × 2 32 t_{COMPx} = t_{RTICLK} \times \left (RTICPUCy + 1 \right) \times 2^{32} tCOMPx=tRTICLK×(RTICPUCy+1)×232
下图展示了一个比较单元的框图。类似的结构在 RTI
中拥有四个。
当 RTIFRCx
寄存器溢出的情况下,可以生成溢出中断(OVLINTx)
。
另外,中断/DMA请求可以在 RTISETINTENA
寄存器中启用,在 RTICLEARINTENA
寄存器中禁用。挂起的中断将在RTIINTFLAG
寄存器中显示。
三、项目实现
通过前面的介绍,想必大家对 RTI
有了一定的了解,那么接下来,将带领大家使用 RTI
。希望这篇文章提供的方法教程能给各位大佬一点帮助。
首先需要明确的是,在本文中,项目将使用 RTI
产生 500ms 的定时中断,用于控制 LED2
的闪烁。
其实
RTI
很像STM32
中的滴答定时器(Tick Time)
,其都能够使用硬件产生固定时间间隔的信号,因此也常用于操作系统(RTOS)
中。
3.1 硬件部分
在本文中,有关硬件只使用到了 LED2
,其原理图如下所示:
因此,我们等会初始软件的时候,同时也需要初始化 GIOB_6
。
其在开发板上的位置如下图中黄色方框所示:
3.2 软件部分
3.2.1 HALCoGen 配置
有了硬件部分的了解,我们只需要初始化 GIOB_6
以及 RTI
即可,那么具体实现方式如下所示:
-
在
TMS570LC4357ZWT -> Driver Enable
中使能GIO
及RTI
驱动 -
在
GIO -> Port B
中对Bit 6
进行以下设置: -
因为我们要产生一个 500ms 的中断,因此在
RTI -> RTI1 Compare
中进行如下设置:
-
在
TMS570LC4357ZWT -> VIM Channel 0-31
中使能RTI Compare 0
中断,如下所示: -
配置完上述功能后,即可生成程序。依旧使用快捷键
F5
或依次点击File -> Generate Code
。
3.2.2 CCS 配置
生成文件后,依旧在 CCS
中进行编写逻辑代码操作。还是先找到我们的 HL_sys_main.c
文件。这里我给出我写的示例代码:
/* USER CODE BEGIN (0) */
/* USER CODE END *//* Include Files */#include "HL_sys_common.h"/* USER CODE BEGIN (1) */
#include "HL_system.h"
#include "HL_gio.h"
#include "HL_rti.h"
/* USER CODE END *//** @fn void main(void)
* @brief Application main function
* @note This function is empty by default.
*
* This function is called after startup.
* The user can use this function to implement the application.
*//* USER CODE BEGIN (2) */
#define LED2_BIT 6U
/* USER CODE END */int main(void)
{
/* USER CODE BEGIN (3) *//* 使能总中断 */_enable_IRQ_interrupt_();gioInit(); // GPIO 初始化rtiInit(); // RTI 初始化rtiEnableNotification(rtiREG1, rtiNOTIFICATION_COMPARE0); // 使能通知函数gioSetBit(gioPORTB, LED2_BIT, 0); // 关闭 LED2rtiStartCounter(rtiREG1, rtiCOUNTER_BLOCK0); // rti Block0 开始计数for (;;) {/* 循环,确保程序一直在运行 */}
/* USER CODE END */return 0;
}/* USER CODE BEGIN (4) *//** @brief : RTI通知函数* @param : [rtiREG]: rti端口寄存器* [notification]: 中断类型* @return : void* @author : Liu Jiahao* @date : 2024-08-20* @version : v1.0* @copyright : Copyright By Liu Jiahao, All Rights Reserved*/
void rtiNotification(rtiBASE_t *rtiREG, uint32 notification)
{if (rtiREG == rtiREG1) {switch (notification){case rtiNOTIFICATION_COMPARE0:gioToggleBit(gioPORTB, LED2_BIT); // 切换 LEDbreak;case rtiNOTIFICATION_COMPARE1:/* user code */break;case rtiNOTIFICATION_COMPARE2:/* user code */break;case rtiNOTIFICATION_COMPARE3:/* user code */break;case rtiNOTIFICATION_COUNTER0:/* user code */break;case rtiNOTIFICATION_COUNTER1:/* user code */break;case rtiNOTIFICATION_TIMEBASE:/* user code */break;default: break;}}
}
/* USER CODE END */
值得注意的是,需要使能 IRQ
中断 RTI
才能正常运行,即使用 _enable_IRQ_interrupt_()
使能中断。
另外,我在 rtiNotification
函数中罗列了所有 RTI
中断通知类型,当然,在此之前也需要我们使用 rtiEnableNotification
函数使能相应的中断类型。这些类型在 HL_rti.h
中均有说明。
3.2.3 运行结果
如下图所示为运行结果示意图:
如图所示,LED2
间隔闪烁,证明 RTI
间隔进行中断。
五、写在最后
本文介绍了 TMS570LC43上的 RTI 模块以及其使用方法。希望能够对大家的学习提供一点帮助。
在后续的文章中,将继续对 TMS570LC43x 进行详细的入门指导,欢迎读者关注!!!
目前暂时没有考虑整合的打算,所以各位读者如果需要看别的教程,可以点进 专栏 进行查找。在后续的更新中,将会逐步加入各个文章的链接,以便大家快速翻阅。另外源码会逐步开源。
欢迎广大读者提出问题以及修改意见,本人看到后会给予回应,欢迎留言,后续会逐步进行开源!!!
另外,由于文章是作者手打的文字,有些地方可能文字会出错,望谅解,也可私信联系我,我对其进行更改。
-
个人CSDN账号:刘梓谦_-CSDN博客
-
Gitee:刘佳豪 (liu-jiahaohappy) - Gitee.com
-
GitHub:Jiahao-Liu29 (github.com)