本文主要是介绍imx6ull Enhanced Periodic Interrupt Timer (EPIT),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
一、overview
EPIT是一个32位的计时器,能够在处理器很少干预的情况下以固定的时间间隔提供精确的中断。软件使能后,EPIT就开始计数。IMX6ULL有2个EPIT定时器。其框图如下所示:
1.1 epit 特性
EPIT具有以下主要特性:
•可选择时钟源的32位递减计数器
•12位预分频器,用于对输入时钟进行分频
•可即时编程的计数器值
•可以设置在低功耗和调试模式下,计数器仍然运行
•计数器达到比较值时产生中断
1.2操作模式
EPIT可以设置为set-and-forget或free-running模式,设置EPIT_CR[RLD]选择所需的模式。
① set-and-forget模式
要选择这种操作模式,将控制寄存器(EPIT_CR)中的RLD位置1。在这种模式下,计数器从加载寄存器(EPIT_LR)获取初始值,你不能直接写入初始值。每当计数器达到零时,EPIT_LR中的值就会加载到计数器中,计数器再次将此值减到零。要想立刻设置EPIT的计数值,不必等到它减小到0后再加载EPIT_LR。可以设置EPIT计数器覆盖使能位(EPIT_CR [IOVW]),并将所需的初始化值写EPIT_LR。
② free-runnning模式
选择此操作模式的话,需要清除RLD位。在这种模式下,计数器递减到0000 0000h时,会翻转到FFFF FFFFh。不会从加载寄存器重新加载新值。翻转后,计数器继续递减计数。要直接初始化计数器,需要设置EPIT计数器覆盖使能位(EPIT_CR[IOVW]),并将所需的初始化值写入EPIT_LR。
1.3比较事件
EPIT启动后,EPIT_CNR中的值递减,当它等于EPIT_CMPR的值时,就产生比较事件:设置比较状态标志,产生中断(如果控制寄存器中的OCIEN位是1的话)。可以设置控制寄存器中输出模式(OM)位,当发生比较事件时,对应的输出引脚如何动作:置位(set)、清除(clear)、翻转(toggle)或者不受影响。先讲个概念:翻转(rollover),就是当计数器值达到0x0000_0000时,它需要加载新值,这就叫rollover。如果需要在翻转时产生中断,则比较寄存器的取值要小心设置:
① 在set-and-forget模式下,应该取EPITx_LR的值;
② 在free-running模式下,应该取0xFFFF_FFFF。
下图显示了比较事件和中断的时序:
计数器值覆盖:可以在任何时候将EPIT计数器值设置为所需要的值,操作方法为:
① 设置控制寄存器中的IOVW位,即EPIT_CR[IOVW];
② 然后将值写入到加载寄存器,即EPIT_LR;
如果EPIT正在运行,则计数器将以新值继续计数。
二、EPIT寄存器
2.1 EPIT Control register (EPITx_CR)
位域 | 名 | 读写 | 描述 |
---|---|---|---|
[25:24] | CLKSRC | R/W | 时钟源选择,00:时钟源断开;01:Peripheral clk,即ipg_clk;10:Hign-frequency,即ipg_clk_highfreq;11:low-frequency,即ipg_clk_32k |
[23:22] | OM | R/W | 用来设置输出通道模式,00:输出引脚跟EPIT断开,即输出引脚不受影响;01:输出引脚翻转;10:输出引脚清0;11:输出引脚置位 |
[21] | STOPEN | R/W | stop mode时EPIT是否使能,0:在stop mode下,EPIT禁止1:在stop mode下,EPIT仍然使能 |
[19] | WAITEN | R/W | Wait mode时EPIT是否使能,0:在wait mode下,EPIT禁止1:在wait mode下,EPIT仍然使能 |
[18] | DBGEN | R/W | Debug mode时EPIT是否使能,0:在debug mode下,EPIT禁止1:在debug mode下,EPIT仍然使能 |
[17] | IOVW | EPIT计数器覆盖使能位,0:写入EPIT_LR的值不会覆盖EPIT计数器;1:写入EPIT_LR的值会马上覆盖EPIT计数器的值 | |
[16] | SWR | R/W | 软件复位,这位会自动清零,a. EPIT在复位状态时,该位自动置1b. 复位结束时,该位自动清0c. 设置该位为1时,会把所有寄存器设置为它们的默认值,EPITx_CR中这些位不受影响:EN、ENMOD、STOPEN、WAITEN、DBGEN |
[15:4] | PRESCALER | R/W | EPIT时钟的分频系数,0x000:除以1;0x001:除以2;……0xFFF:除以4096 |
[3] | RLD | R/W | 计数器模式(计数器加载模式),0:free-running mode,计数器到达0时,变为0xFFFFFFFF;1:set-and-forget mode,计数器到达0时,加载EPITx_LR的值 |
[2] | OCIEN | R/W | 输出比较中断使能,0:比较事件发生时,中断禁止;1:比较事件发生时,中断使能 |
[1] | ENMOD | R/W | 当EPIT重新使能后,主计数值从什么值开始计数:0:从上次关闭时的计数值继续计数;1:如果RLD为1,从加载计数器开始计数;如果RLD为0,从0xFFFF_FFFF开始计数;EPIT重新使能时,预分频计数器总是从0开始计数。 |
[0] | EN | R/W | EPIT使能位,0:EPIT禁止;1:EPIT使能 |
2.2 Status register (EPITx_SR)
位域 | 名 | 读写 | 描述 |
---|---|---|---|
[0] | OCIF | R/W | Output compare interrupt flag,0:比较事件未发生;1:比较事件已发生 |
2.3 Load register (EPITx_LR)
位域 | 名 | 读写 | 描述 |
---|---|---|---|
[31:0] | LOAD | R/W | 加载值 |
2.4 Compare register (EPITx_CMPR)
位域 | 名 | 读写 | 描述 |
---|---|---|---|
[31:0] | COMPARE | R/W | 比较值 |
2.5 Counter register (EPITx_CNR)
位域 | 名 | 读写 | 描述 |
---|---|---|---|
[31:0] | COUNT | R/W | EPIT计数器的值 |
三、编程
使用epit 产生定时中断
/* assume use ipc clk which is 66MHz, 1us against to 66 count */
#define USEC_TO_COUNT(us) (us * 66 - 1)void epit_init(EPIT_Type *base, unsigned int us)
{base->CR = 0;//software reset base->CR |= (1 << 16);/* wait for software reset self clear*/while((base->CR) & (1 << 16)) ;/** EPIT_CR* bit21 stopen; bit19 waiten; bit18 debugen* bit17 overwrite enable; bit3 reload* bit2 compare interrupt enable; bit1 enable mode*/base->CR |= (1 << 21) | (1 << 19) | (1 << 3) | (1 << 1);/** EPIT_CR* bit25-24: 00 off, 01 peripheral clock(ipg clk), 10 high, 11 low* bit15-4: prescaler value, divide by n+1*/base->CR &= ~((0x3 << 24) | (0xFFF << 4));base->CR |= (1 << 24);/* EPIT_CMPR: compare register */base->CMPR = 0;/* EPIT_LR: load register , assue use ipc clk 66MHz*/base->LR = USEC_TO_COUNT(us);
}void epit_enable_interrupt(EPIT_Type *base, int on)
{/* EPIT_CR bit2 OCIEN compare interrupt enable */if (on)base->CR |= (1 << 2);elsebase->CR &= ~(1 << 2);
}void epit_run(EPIT_Type *base, int on)
{/* EPIT_CR bit0 EN */if (on)base->CR |= (1 << 0);elsebase->CR &= ~(1 << 0);
}int main()
{boot_clk_init();gic_init();epit_init(EPIT1, 1000000);// set 1srequest_irq(EPIT1_IRQn, (irq_handler_t)EPIT1_handle_irq, NULL);gic_enable_irq(EPIT1_IRQn);epit_enable_interrupt(EPIT1, 1);epit_run(EPIT1, 1);while(1){}
}
这篇关于imx6ull Enhanced Periodic Interrupt Timer (EPIT)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!