imx6ull General Purpose Timer (GPT)

发布于:2023-05-01 ⋅ 阅读:(349) ⋅ 点赞:(0)

一、overview

GPT有一个32位的向上计数器,可以将外部引脚上的事件捕获到GPT寄存器中,捕获触发可以编程设置为上升沿或下降沿触发,甚至双边沿触发。GPT还可以在输出比较引脚上产生一个事件,并当计时器达到编程值时产生一个中断。GPT有一个12位的预分频,来对多个时钟源进行分频。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-q1iNBT1y-1632660745309)(E:\u-boot\pic\GPT.jpg)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-IfXbX4V6-1632660745311)(E:\u-boot\pic\gpt clock.jpg)]

1.1 特性

① 一个带有时钟源选择的32位递增计数器,时钟源包括外部时钟。
② 两个具有可编程触发沿的输入捕捉通道。
③ 具有可编程输出模式的三个输出比较通道,还有一个“force compare”功能。
④ 可以通过编程,让它在低功耗(low power)和调试(debug)模式下运行。
⑤ 可以在捕获(capture),比较(compare)和翻转(rollover)事件时产生中断。
⑥ 两种计数模式:重新启动(restart)或自由运行(free-run)模式。

1.2 操作模式

① 重新启动计数模式(Restart mode):
在重启模式下(可通过GPT控制寄存器GPT_CR选择),当计数器达到比较值时,计数器将复位并从0x00000000重新开始计数。
重新启动功能仅与比较通道1相关联。对通道1的比较寄存器的任何写操作都将复位GPT计数器。这样做是为了避免在进行计数时将比较值从较高的值更改为较低的值时可能丢失比较事件。对于其他两个比较通道,当发生比较事件时,计数器不会复位。

② 自由运行模式(free-run mode):
在自由运行模式下,当所有三个通道发生比较事件时,计数器不会复位;而是,计数器继续计数直到0xffffffff,然后翻转(变为0x00000000)。

1.3 时钟

可以从4个时钟源中选择一个输入到预分频器的时钟,分别为:
① 高频参考时钟(ipg_clk_highfreq),
② 低频参考时钟(ipg_clk_32k),
③ 外围时钟(ipg_clk),
④ 外部时钟(GPT_CLK)
⑤ 晶体振荡器时钟(ipg_clk_24M)

时钟源选择的操作流程:
① 通过在GPT_CR寄存器中设置EN = 0来禁用GPT;
② 禁用GPT中断寄存器(GPT_IR);
③ 将输出模式配置为未连接/断开连接:往GPT_CR中的OM1,OM2,OM3写0;
④ 禁用输入捕获模式:往GPT_CR的IM1和IM2中写入零;
⑤ 在GPT_CR寄存器中将时钟源CLKSRC更改为所需的值;
⑥ 将GPT_CR寄存器中的SWR位置1;
⑦ 清除GPT状态寄存器(GPT_SR)(该寄存器是往相应位写1清0);
⑧ 在GPT_CR寄存器中设置ENMOD = 1,以使GPT计数器为0x00000000;
⑨ 在GPT_CR寄存器中启用GPT(EN = 1);
⑩ 启用GPT中断寄存器(GPT_IR)。

1.4 GPT 的输入捕获

​ GPT有两个输入捕获通道,每个输入捕获通道都有:一个专用的捕获引脚,捕获寄存器和输入边沿检测/选择逻辑。每个输入捕获功能都有一个状态标记位,并且可以向处理器发出中断服务请求。
​ 我们先设置好捕获引脚的边沿检测/选择逻辑,当该引脚上发生指定的边沿转换时,GPT_CNT的内容被捕捉到相应的捕捉寄存器中,并设置适当的中断状态标志。如果该中断被使能了,它就可以产生中断。
​ 有哪些边沿检测/选择逻辑?上升沿,下降沿,双边沿,或者禁用捕获。
​ 捕获事件与计数器的时钟同步。假设当前正在记录一个事件,如果紧接着立刻发生另一个事件,那么第2个事件可能会丢失。当前事件正在记录时,至少一个时钟周期之后发生的事件,才能保证不丢失。可以随时读取输入捕获寄存器,而不会影响它们的值。具体时序图如下所示:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-8qxvK66V-1632660745313)(E:\u-boot\pic\gpt 输入捕获.jpg)]

1.5 GPT的输出比较

​ GPT中有三个输出比较通道,它们都使用同一个计数器(GPT_CNT),输入捕获通道也是使用这个计数器。

​ 软件上先设置输出比较寄存器,当GPT_CNT的值与输出比较寄存器匹配时,GPT就会设置“输出比较状态标志”(output compare status flag)为1,并产生中断。

​ 并且,根据设置的不同,输出比较定时器对应的引脚将被置位(set)、清除(clear)、翻转(toggle)或者不受影响,或输出一个低脉冲(脉冲持续时间为定时器的时钟源的周期)。

​ 还有一个“强制比较(forced-compare)”功能,一旦设置,就会马上产生比较事件;不管当前计数器值是否等于比较值。强制比较的产生的事件,跟正常的输出事件相同,只是它不会设置状态标记位并且不会产生中断。一旦设置force-compare位,该事件会即刻产生,这个位是自动清除的,读的话一直零。

​ 下图是输出比较时的时序图:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Sj4rM6Pc-1632660745315)(E:\u-boot\pic\gpt 输入比较.jpg)]

1.6 GPT 中断

GPT可以产生6种不同的中断:
① 翻转中断(Rollover Interrupt)
当GPT计数器达到0xffffffff,然后重新设置为0x00000000并继续计数时,将产生翻转中断。
翻转中断通过GPT_IR寄存器中的ROVIE位来使能。相关的状态位是GPT_SR寄存器中的ROV位。
② 输入捕获中断1、2
捕获事件发生后,相应的输入捕获通道会产生一个中断。
“捕获事件中断”通过IF2IE和IF1IE位(在GPT_IR寄存器中)使能;相应的状态位是IF2和IF1(在GPT_SR寄存器中)。
发生捕获事件时会产生中断,但是该中断无论是否被处理,都不会影响下次捕获事件的发生。当再次发生捕获事件时,无论之前的中断是否被处理了,捕获寄存器都会被再次更新。

③ 输出比较中断1、2、3
当比较事件发生后,相应的输出比较通道会产生一个中断。
“比较事件中断”由OF3IE,OF2IE和OF1IE位(在GPT_IR寄存器中)使能;相应的状态位是OF3,OF2和OF1(在GPT_SR寄存器中)。
“强制比较(Force compare)”不会产生中断。

二、GPT寄存器

2.1 GPT Control Register (GPTx_CR)

位域 读写 描述
[31] FO3 R/W 强制输出通道3,用于设置强制比较(Force compare),写0:没影响写1:强制比较,会导致相应的输出引脚状态发生变化,但是OFn不受影响
[30] FO2 R/W 同上
[29] FO1 R/W 同上
[28:26] OM3 R/W 用来设置输出通道3的工作模式,000:输出引脚跟GPT断开,即输出引脚不受影响;001:输出引脚翻转;010:输出引脚清0;011:输出引脚置位;1xx:输出引脚产生一个低脉冲
[25:23] OM2 R/W 用来设置输出通道2的工作模式,跟OM3类似
[22:20] OM1 R/W 用来设置输出通道1的工作模式,跟OM3类似
[19:18] IM2 R/W 用来设置输入通道2的工作模式,00:捕获功能关闭;01:捕获上升沿;10:捕获下降沿;11:同时捕获上升和下降沿
[15] SWR R/W 软件复位,会自动清零,a. GPT在复位状态时,该位自动置1b. 复位结束时,该位自动清0c. 设置该位为1时,会把所有寄存器设置为它们的默认值,GTPx_CR中这些位不受影响:EN、ENMOD、STOPEN、WAITEN、DBGEN
[10] EN_24M R/W 是否使用24M晶振作为GPT时钟,0:不使用1:使用硬件复位时,该位被设置为0;软件复位不影响该位
[9] FRR R/W 用来选择“Restart”模式或“Free-Run”模式,0:Restart模式(比较事件发生后,计数值清0,重新计数)1:Free-Run模式(比较事件不影响计数值,计数值到达0xFFFFFFFF才清0)
[8:6] CLKSRC R/W 时钟源选择,000:时钟源断开;001:Peripheral Clock (ipg_clk);010:High Frequency Reference Clock (ipg_clk_highfreq);011:External Clock;100:Low Frequency Reference Clock (ipg_clk_32k);101:Crystal oscillator as Reference Clock (ipg_clk_24M)
[5] STOPEN R/W stop mode时GPT是否使能,0:在stop mode下,GPT禁止1:在stop mode下,GPT仍然使能
[4] DOZEEN R/W Doze mode时GPT是否使能,0:在doze mode下,GPT禁止1:在doze mode下,GPT仍然使能
[3] WAITEN R/W Wait mode时GPT是否使能,0:在wait mode下,GPT禁止1:在wait mode下,GPT仍然使能
[2] DBGEN R/W Debug mode时GPT是否使能,0:在debug mode下,GPT禁止1:在debug mode下,GPT仍然使能
[1] ENMOD R/W 当EPIT重新使能后,主计数器和预分频器计数器从什么值开始计数,0:从上次关闭时的计数值继续计数;1:主计数器、预分频计数器都从0开始计数
[0] EN R/W GPT使能位,0:GPT禁止;1:GPT使能

2.2 GPT Prescaler Register (GPTx_PR)

位域 读写 描述
[15:12] PRESCALER24M R/W 时钟源在24M晶振时,GPT时钟的分频系数
[11:0] PRESCALER R/W 选择其它时钟源时,GPT时钟的分频系数

2.3 GPT Status Register (GPTx_SR)

位域 读写 描述
[5] ROV R/W 计数器的值是否到达了0xFFFFFFFF(Rollover),0:Rollover未发生;1:Rollover已发生
[4] IF2 R/W 输入捕获通道2的事件是否已经发生,0:未发生;1:已发生
[3] IF1 R/W 输入捕获通道1的事件是否已经发生,0:未发生;1:已发生
[2] OF3 R/W 输出比较通道3的事件是否已经发生,0:未发生;1:已发生
[1] OF2 R/W 输出比较通道2的事件是否已经发生,0:未发生;1:已发生
[0] OF1 R/W 输出比较通道1的事件是否已经发生,0:未发生;1:已发生

2.4 GPT Interrupt Register (GPTx_IR)

位域 读写 描述
[5] ROVIE R/W Rollover中断使能位(计数值达到0xFFFFFFFF),0:Rollover中断禁止;1:Rollover中断使能
[4] IF2IE R/W 输入捕获通道2的中断使能位,0:中断禁止;1:中断使能
[3] IF1IE R/W 输入捕获通道1的中断使能位,0:中断禁止;1:中断使能
[2] OF3IE R/W 输出比较通道3的中断使能位,0:中断禁止;1:中断使能
[1] OF2IE R/W 输出比较通道2的中断使能位,0:中断禁止;1:中断使能
[0] OF1IE R/W 输出比较通道1的中断使能位,0:中断禁止;1:中断使能

2.5 GPT Output Compare Register y (GPTx_OCRy)

GPT输出比较寄存器,有GPTx_OCR1-3共3个输出比较寄存器。

当计数器达到输出比较寄存器的值时,将在相应通道上产生事件。

当GPT使用Restart mode时,写入比较寄存器的同时会复位GPT计数器。

写寄存器的值在一个时钟周期后生效,读寄存器的值会立即返回。

位域 读写 描述
[31:0] COMP R/W 比较值

2.6 GPT Input Capture Register y (GPTx_ICRy)

GPT输入捕获寄存器,有GPTx_ICR1-2共两个输入捕获寄存器。它们是只读寄存器,用于保存相应输入捕获通道中,发生捕获事件发生时计数器的值。

位域 读写 描述
[31:0] CAPT R/W 发生捕获事件时,GPT计数器的值

2.7 GPT Counter Register (GPTx_CNT)

GPT计数器寄存器,主计数值,它是只读寄存器;读取GPT计数器的值,不影响计数过程。

位域 读写 描述
[31:0] COUNT R/W GPT计数器的值

三、编程

使用gpt产生通道1输出比较并产生中断

void gpt_poll_init(GPT_Type *base)
{
	/* bit15 SWR, Software reset*/
	base->CR |= (1 << 15);
	/* Wait reset finished. */
	while((base->CR >> 15) & 0x1) {}

	/*
	 *bit10: Enable 24 MHz clock input from crystal
	 *bit9: 0 restart mode, 1 free-run mode:set 0
	 *bit8-6: Clock Source select :001 Peripheral Clock (ipg_clk)
	 *bit5: GPT Stop Mode enable
	 *bit3: GPT Wait Mode enable.
	 *bit1: GPT Enable Mode
	 */	
	base->CR = (1 << 6) | (1 << 5) | (1 << 3) | (1 << 1);

	/*
	 *bit15-bit12:PRESCALER24M
	 *bit11-0:PRESCALER
	 */
	base->PR = 0;
}

void gpt_poll_restart(GPT_Type *base, enum gpt_comp_channel chan, unsigned int us)
{
	base->OCR[chan] =  USEC_TO_COUNT(us);
	/* write 1 to clear int status to avoid unexpected compare event*/
	base->SR |= (1 << chan);
	/* enable interrupt*/
	base->IR |= (1 << chan);
	/* gpt enable*/
	base->CR |= (1 << 0);
	/*wait for compare flag set*/
	while(!((base->SR >> chan) & 0x1)) 
		;
	/* gpt disable*/
	base->CR &= ~(1 << 0);
	/* disable interrupt*/
	base->IR &= ~(1 << chan);
	/* write 1 to clear int status*/
	base->SR |= (1 << chan);
}
void gpt_run(GPT_Type *base, int on)
{
	/* bit0: GPT Enable */
	if (on)
		base->CR |= (1 << 0);
	else
		base->CR &= ~(1 << 0);
}
void GPT1_COMP1_handle_irq(void)
{
	printf("GPT1 comp0 interrupt happened\r\n");
	/* 
	 * bit0: OF1 Output Compare 1 Flag
	 * write 1 clear it */
	GPT1->SR |= 1;
	//do_something_want
}

void main()
{
	gpt_init(GPT1, OUT_COMP1, 1000000);// set 1s
	request_irq(GPT1_IRQn, (irq_handler_t)GPT1_COMP1_handle_irq, NULL);
	gic_enable_irq(GPT1_IRQn);
	gpt_enable_interrupt(GPT1, IR_OF1IE, 1);
	gpt_run(GPT1, 1);
	while(1){}
}


网站公告

今日签到

点亮在社区的每一天
去签到