Linux NXP (I.MX6ULL) GPT高精度延时定时器

GPT 定时器简介

GPT 定时器全称为 General Purpose Timer,GPT 定时器是一个 32 位向上定时器(也就是从 0X00000000 开始向上递增计数), GPT 定时器也可以跟一个值进行比较,当计数器值和这个值相等的话就发生比较事件,产生比较中断。GPT 定时器有一个 12 位的分频器,可以对 GPT 定时器的时钟源进行分频。

1、GPT 定时器特性如下:

①、一个可选时钟源的 32 位向上计数器。

②、两个输入捕获通道,可以设置触发方式。

③、三个输出比较通道,可以设置输出模式。

④、可以生成捕获中断、比较中断和溢出中断。

⑤、计数器可以运行在重新启动(restart)或(*运行)free-run 模式。

2、GPT 定时器的可选时钟源如下图所示:

Linux NXP (I.MX6ULL) GPT高精度延时定时器
从上图中可以看出一共有五个时钟源,分别为: ipg_clk_24MGPT_CLK(外部时钟)ipg_clkipg_clk_32k 和== ipg_clk_highfreq==。本博文选择 ipg_clk 为 GPT 的时钟源, ipg_clk_66MHz。

3、GPT 定时器结构如下图所示:

Linux NXP (I.MX6ULL) GPT高精度延时定时器

3.1、GPT 定时器结构中各部分意义如下:

①、此部分为 GPT 定时器的时钟源,前面已经说过了,本章例程选择 ipg_clk 作为 GPT 定时器时钟源。

②、此部分为 12 位分频器,对时钟源进行分频处理,可设置 0~ 4095,分别对应 1~ 4096 分频。

③、经过分频的时钟源进入到 GPT 定时器内部 32 位计数器。

④和⑤、这两部分是 GPT 的两路输入捕获通道,本章不讲解 GPT 定时器的输入捕获。

⑥、此部分为输出比较寄存器,一共有三路输出比较,因此有三个输出比较寄存器,输出比较寄存器是 32 位的。

⑦、此部分位输出比较中断,三路输出比较中断,当计数器里面的值和输出比较寄存器里面的比较值相等就会触发输出比较中断。

4、GPT 定时器有两种工作模式

重新启动(restart)模式和*运行(free-run)模式,这两个工作模式的区别如下:

重新启动(restart)模式:当 GPTx_CR(x=1, 2)寄存器的 FRR 位清零的时候 GPT 工作在此模式。在此模式下,当计数值和比较寄存器中的值相等的话计数值就会清零,然后重新从0X00000000 开始向上计数,只有比较通道 1 才有此模式!向比较通道 1 的比较寄存器写入任何数据都会复位 GPT 计数器。对于其他两路比较通道(通道 2 和 3),当发生比较事件以后不会复位计数器。

*运行(free-run)模式:当 GPTx_CR(x=1, 2)寄存器的 FRR 位置 1 时候 GPT 工作在此模式下,此模式适用于所有三个比较通道,当比较事件发生以后并不会复位计数器,而是继续计数,直到计数值为 0XFFFFFFFF,然后重新回滚到 0X00000000。

5、 GPT 定时器几个重要的寄存器

5.1、GPT 的配置寄存器 GPTx_CR

Linux NXP (I.MX6ULL) GPT高精度延时定时器

寄存器 GPTx_CR 我们用到的重要位如下:

描述
SWR(bit15) 复位 GPT 定时器,向此位写 1 就可以复位 GPT 定时器,当 GPT 复位完成以后此为会自动清零。
FRR(bit9) 运行模式选择,当此位为 0 的时候比较通道 1 工作在重新启动(restart)模式。当此位为 1 的时候所有的三个比较通道均工作在*运行模式(free-run)。
CLKSRC(bit8:6) GPT 定时器时钟源选择位,为 0 的时候关闭时钟源;为 1 的时候选择ipg_clk 作为时钟源;为 2 的时候选择 ipg_clk_highfreq 为时钟源;为 3 的时候选择外部时钟为时钟源;为 4 的时候选择 ipg_clk_32k 为时钟源;为 5 的时候选择 ip_clk_24M 为时钟源。本章例程选择 ipg_clk 作为 GPT 定时器的时钟源,因此此位设置位 1(0b001)。
ENMOD(bit1) GPT 使能模式,此位为 0 的时候如果关闭 GPT 定时器,计数器寄存器保存定时器关闭时候的计数值。此位为 1 的时候如果关闭 GPT 定时器,计数器寄存器就会清零。EN(bit): GPT 使能位,为 1 的时候使能 GPT 定时器,为 0 的时候关闭 GPT 定时器。

5.2、GPT 定时器的分频寄存器 GPTx_PR

Linux NXP (I.MX6ULL) GPT高精度延时定时器
寄存器 GPTx_PR 我们用到的重要位如下:

描述
PRESCALER(bit11:0) 这就是 12 位分频值,可设置 0~ 4095,分别对应 1~4096 分频。

5.3、GPT 定时器的状态寄存器 GPTx_SR

Linux NXP (I.MX6ULL) GPT高精度延时定时器
寄存器 GPTx_SR 重要的位如下:

描述
ROV(bit5) 回滚标志位,当计数值从 0XFFFFFFFF 回滚到 0X00000000 的时候此位置 1。
IF2~IF1(bit4:3) 输入捕获标志位,当输入捕获事件发生以后此位置 1,一共有两路输入捕获通道。如果使用输入捕获中断的话需要在中断处理函数中清除此位。
OF3~OF1(bit2:0) 输出比较中断标志位,当输出比较事件发生以后此位置 1,一共有三路输出比较通道。如果使用输出比较中断的话需要在中断处理函数中清除此位。

接着看一下 GPT 定时器的计数寄存器 GPTx_CNT,这个寄存器保存着 GPT 定时器的当前计数值。最后看一下 GPT 定时器的输出比较寄存器 GPTx_OCR,每个输出比较通道对应一个输出比较寄存器,因此一个 GPT 定时器有三个 OCR 寄存器,它们的作都是相同的。以输出比较通道 1 为例,其输出比较寄存器为 GPTx_OCR1,这是一个 32 位寄存器,用于存放 32 位的比较值。当计数器值和寄存器 GPTx_OCR1 中的值相等就会产生比较事件,如果使能了比较中断的话就会触发相应的中断。

6、定时器实现高精度延时原理

高精度延时函数的实现肯定是要借助硬件定时器,使用 GPT 定时器来实现高精度延时。如果设置 GPT 定时器的时钟源为 ipg_clk=66MHz,设置 66 分频,那么进入 GPT定时器的最终时钟频率就是 66/66=1MHz,周期为 1us。 GPT 的计数器每计一个数就表示“过去”了 1us。如果计 10 个数就表示“过去”了 10us。通过读取寄存器 GPTx_CNT 中的值就知道计了个数,比如现在要延时 100us,那么进入延时函数以后纪录下寄存器 GPTx_CNT 中的值为 200,当 GPTx_CNT 中的值为 300 的时候就表示 100us 过去了,也就是延时结束。 GPTx_CNT 是个32 位寄存器,如果时钟为 1MHz 的话, GPTx_CNT 最多可以实现 0XFFFFFFFFus=4294967295us≈4294s≈72min。也就是说 72 分钟以后 GPTx_CNT 寄存器就会回滚到 0X00000000,也就是溢出,所以需要在延时函数中要处理溢出的情况。