正点原子[第二期]Linux之ARM(MX6U)裸机篇学习笔记-16讲 EPIT定时器

发布于:2024-05-17 ⋅ 阅读:(96) ⋅ 点赞:(0)

前言:

本文是根据哔哩哔哩网站上“正点原子[第二期]Linux之ARM(MX6U)裸机篇”视频的学习笔记,在这里会记录下正点原子 I.MX6ULL 开发板的配套视频教程所作的实验和学习笔记内容。本文大量引用了正点原子教学视频和链接中的内容。

引用:

正点原子IMX6U仓库 (GuangzhouXingyi) - Gitee.com

《【正点原子】I.MX6U嵌入式Linux驱动开发指南V1.5.2.pdf》

正点原子资料下载中心 — 正点原子资料下载中心 1.0.0 文档

正文:

本文是 “正点原子[第二期]Linux之ARM(MX6U)裸机篇--第16 讲” 的读书笔记。第16讲主要是介绍I.MX6U处理器的EPIT定时器。本节将参考正点原子的视频教程第16讲和配套的正点原子开发指南文档进行学习。

0. 概述

定时器是最常见的外设,常常需要使用定时器来完成精准的定时功能,I.MX6U 提供了多种硬件定时器,有些定时器功能非常强大。本章我们从最基本的EPIT定时器开始,学习如何配置EPIT定时器,使其按照给定的时间,周期性的产生定时器中断,在定时器中断里面我们可以做其他处理,比如翻转LED灯。

1. EPIT定时器原理

EPIT的全称是:Enhanced Period Interrupt Timer,直译过来就是增强的周期中断定时器,它主要是完成周期性中断的。当学过STM32的话应该知道,STM32里面的定时器还有很多其他的功能,比如输入捕获,PWM输出等等。但是I.MX6U的EPIT定时器只是完成周期性中断定时的功能,仅此一项功能。至于输入捕获,PWM输出灯这些功能,I.MX6U由其他的外设来完成。

EPIT是一个32位定时器,在处理器几乎不用介入的情况下提供精准的定时中断,软件使能以后EPIT就会开始运行,EPIT定时器有如下特点:

  1. 时钟源可选的32位向下定时器
  2. 12位分频值
  3. 当计数值和比较值相等的时候产生中断

EPIT定时器的结构如下图所示:

  1. 这是一个多路选择器,用来选择EPIT定时器的时钟源,EPIT共有三个时钟源可以选择 ipg_clk, ipg_clk_32k, ipg_clk_highfrq
  2. 这是一个12位的分频器,负责对时钟源进行分频,12位对应的值是0~4095,对应着1~4096分频
  3. 经过分频的时钟进入到EPIT定时内部,在EPIT定时器内部有三个重要的寄存器:技术寄存器(EPIT_CR),加载寄存器(EPIT_LR)和比较寄存器(EPIT_CMPR),这3个寄存器都是32位的。EPIT是一个向下计数器,也就是说给它一个初始值,它就会从这个给定的初始值开始递减,直到减为0,计数寄存器里面保存的就是当前的计数值。如果EPIT工作在 set-and-forget 模式下,当计数寄存器里面的值减少到0,EPIT就会重新从加载寄存器读取数值到技术寄存器里面,重新开始向下计数。比较寄存器里面保存的数值用于和计数寄存器里面的计数值比较,如果相等的话就会产生一个比较事件。
  4. 比较器
  5. EPIT可设置引脚输出,如果设置了的话就会通过制定的引脚输出信号。
  6. 产生比较中断,也就是定时中断。

EPIT定时器有两种工作模式: set-and-forget 和 free-running ,这两个工作模式的区别如下:

  • set-and-forget 模式:EPITx_CR(x=1,2)寄存器的RLD位置1的时候EPIT工作在此模式下,在此模式下EPIT的计数器值从加载寄存器EPITx_LR中获取初始值,不能直接向计数寄存器写入数据。不管什么时候,只要计数器计数到0,那么就会从加载寄存器EPITx_LR中重新加载数据到计数器中,周而复始。
  • free-running模式:EPITx_CR寄存器的RLD位清零的时候EPIT定时器工作在此模式下,当计数器数到0以后会重新从 0xFFFFFFFF 开始计数,并不是从加载寄存器EPITx_LR中获取数据。

1.1 EPIT定时器关联的 EPITx_XX 寄存器如下

寄存器 描述
EPITx_CR Control Register 控制寄存器
EPITx_SR Status Regisetr 状态寄存器
EPITx_LR Load Register 加载寄存器
EPITx_CMPR Compare Register 比较寄存器
EPITx_CNR Counter Register 计数寄存器

1.2 EPIT 比较重要的几个寄存器

 加下来看一下GPIT重要的几个寄存器,第一个就是EPIT的配置寄存器EPITx_CR,此寄存器的结构如下图所示:

EPITx_CR控制寄存器 描述
CLKSRC bit[25:24]

EPIT时钟源选择位,为0时关闭时钟源,1时使用ipg_clk时钟源,2时使用ipg_clk_higrfreq时钟源,3时使用 ipg_clk_32k 时钟源。

在本例程中,我们设置为 1,也就是选择 ipg_clk 作为 EPIT 的时钟源, ipg_clk=66MHz。

IOVW bit[17]

EPIT计数值覆盖写使能。为0写EPIT LR加载寄存器不影响计数寄存器里的值,为1写EPIT LR加载寄存器会立即覆盖写计数寄存器。

PRESCALAR bit[15:4]

EPIT时钟源分配值,可设置范围0~4095,分别对应1~4096分频。
RLD bit[3] EPIT工作模式,为0的时候工作在free-running模式,为1的时候工作在set-and-forget模式。本章例程设置为1,也就是工作在set-and-forget模式
OCIEN bit[2] 比较中断使能位,为0时关闭比较中断,为1的时候使能比较中断。本章实验使能比较中断。
ENMOD bit[1] 设置计数器初始值,为0时计数器初始值等于上次关闭EPIT定时器以后计数器里面的值,为1的时候来源于加载寄存器。
EN bit[0] EPIT使能位,为0的时候关闭EPIT,为1的时候使能EPIT。

寄存器EPITx_SR 寄存器结构如下图所示:

寄存器EPITx_SR寄存器只有一个有效位,那就是 OCIF(Outpurt Comparte Interrupt Flag)bit[0],为0时表示没有比较事件发生,为1的时候表示有比较事件发生。当比较事件发生以后需要手动清除此位,此位是写1清零。

关于 EPIT 的寄存器就介绍到这里,关于这些寄存器详细的描述,请参考《I.MX6ULL 参考手册》第 1174 页的 24.6 小节。

2. EPIT定时器程序编写

本章我们使用EPIT产生功能定时中断,然后在中断服务函数里面翻转LED0,接下来以EPIT1为例,讲解需要哪些步骤来实现这个功能。EPIT1的配置步骤如下

  1. 设置EPIT1的时钟源
    设置EPIT1_CR寄存器的 CLKSEL bit[25:24]位,选择 EPIT1的时钟源。
  2. 设置分频值
    设置EPIT1_CR寄存器的 PRESCALER bit[15:4]位,设置分频值
  3. 设置工作模式
    设置EPIT1_CR寄存器的 RLD bit[3] 位,设置计数器的初始值来源。
  4. 设置计数值的初始值来源
    设置EPIT1_CR寄存器的 ENMODE bit[1] 位,设置计数器的初始值来源。
  5. 使能比较中断
    我们要使用到比较中断,因此需要设置EPIT1_CR寄存器的 OCIEN bit[2] 位,使能比较中断。
  6. 设置加载值和比较值
    设置寄存器EPIT1_LR中国加载值和寄存器EPIT1_CMPR中的比较值,通过这两个寄存器就可以决定计时器的中断周期。
  7. EPIT1中断设置和中断服务函数编写
    使能GIC中对应的EPIT1中断,注册中断服务函数,如果需要的话还可以设置中断优先级。最后编写中断服务函数。
  8. 使能EPIT1定时器
    配置好EPIT1以后就可以使能EPIT1了,通过EPIT1_CR寄存器的 EN bit[0] 位来设置。

通过以上几步我们就配置好EPIT了,通过EPIT的比较中断来实现LED0的翻转。

2.1 本节用到的硬件资源

  •  LED0
  • 定时器EPIT1

本实验通过EPIT的中断来控制LED0的亮灭,LED0的硬件原理前面已经介绍过了。

EIPT定时器输出比较中断的中断ID号为 88=56+32:

2.2 实验程序编写