Linux Bare Machine Development|EPIT Timer

Keywords: Linux IoT imx6ull

EPIT Timer

1.Introduction to EPIT Timer

EPIT (Enhanced Periodic Interrrupt Timer), an enhanced periodic interrupt timer, is primarily used to complete the periodic interrupt timer. EPIT is a 32-bit timer that provides precise timing interrupts when enabled. Its structure is illustrated below

  1. Multiplexer to select clock source, there are 3 options
  2. 12-bit frequency divider for 1~4096 frequency division
  3. Three important registers within EPIT: count register (EPIT_CNR), load register (EPIT_LR), and comparison register (EPIT_CMPR)
  4. comparator
  5. Settable pin output
  6. Produces a comparison interrupt, i.e. a timed interrupt

EPIT timer has two working modes, which are controlled by the RLD bit of the EPITx_CR register

  • set-and-forget mode: RLD position 1, counter count to 0, data is reloaded from the load register into the counter
  • free-running mode: RLD bit clear 0, counter count to 0, start counting from 0xFFFFFFFF again, not from load register

Two important configuration registers EPITx_CR and EPITx_SR

  • The EPITx_CR configuration registers are structured as follows: clock source (CLKSRC), frequency division value (PRESCALAR), working mode (RLD), comparative interrupt enable (OCIEN), counter initial value (ENMOD, EPIT enable (EN)

  • The EPITx_SR state register is structured as follows: A comparison interrupt flag bit (OCIF) of 0 indicates that no comparison event has occurred, and a comparison event has occurred.

The configuration steps to generate a timer interrupt using EPIT1 are as follows:

  1. Set EPIT1 clock source
  2. Set crossover value
  3. Set working mode
  4. Set Counter Initial Value Source
  5. Enables comparison of interrupts
  6. Set Load Value and Comparison Value
  7. Interrupt Setup and Interrupt Service Function Writing
  8. Enable EPIT1 timer

2. Hardware Introduction

Hardware resources used in this routine:

  • LED0
  • Timer EPIT1

Control of LED 0 light up and down by EPIT1 interrupt

3. Programming

  • Create a new epittimer folder, write EPIT timer driver files bsp_epittimer.c and bsp_epittimer.h
void epit1_init(unsigned int frac, unsigned int value);
void epit1_irqhandler(void);
/* @description		: Initialize EPIT timer.
 *					  EPIT The timer is a 32-bit down counter and the clock source uses ipg=66Mhz	 
 * @param - frac	: The frequency division value, which ranges from 0 to 4095, corresponds to 1 to 4096 frequency division, respectively.
 * @param - value	: Count down values.
 * @return 			: nothing */
void epit1_init(unsigned int frac, unsigned int value){
	if(frac > 0XFFF)
		frac = 0XFFF;
		
	EPIT1->CR = 0;	/* Clear CR Register First */
	
	/* CR Registers:
     * bit25:24 01 Clock source selection Peripheral clock=66MHz
     * bit15:4  frac Crossover value
     * bit3:	1  Reload values from LR when counter reaches 0
     * bit2:	1  Compare Interrupt Enables
     * bit1:    1  The initial count value comes from the LR register value
     * bit0:    0  Turn off EPIT1 first */
	EPIT1->CR = (1<<24 | frac << 4 | 1<<3 | 1<<2 | 1<<1);	
	EPIT1->LR = value;	/* Countdown value */
	EPIT1->CMPR	= 0;	/* Comparing registers, interrupts occur when the counter value is equal to the register value */
	/* Enable corresponding interrupts in GIC 			*/
	GIC_EnableIRQ(EPIT1_IRQn);
	/* Register interrupt service functions 			*/
	system_register_irqhandler(EPIT1_IRQn, (system_irq_handler_t)epit1_irqhandler, NULL);	
	EPIT1->CR |= 1<<0;	/* Enable EPIT1 */ 
}

/* EPIT Interrupt Handling Function */
void epit1_irqhandler(void){ 
	static unsigned char state = 0;
	state = !state;
	if(EPIT1->SR & (1<<0)){ 		/* Judging the occurrence of comparative events */
		led_switch(LED0, state); 	/* Timer cycle to, reverse LED */
	}	
	EPIT1->SR |= 1<<0; 				/* Clear interrupt flag bits */
}
  • Main Program main.c Writing
int main(void){
	int_init(); 				/* Initialization interrupt (must be called first!) */
	imx6u_clkinit();			/* Initialize the system clock 			*/
	clk_enable();				/* Enable all clocks 			*/
	led_init();					/* Initialize led 			*/
	beep_init();				/* Initialize beep	 		*/
	key_init();					/* Initialization key 			*/
	epit1_init(0, 66000000/2);	/* Initialize EPIT1 timer, 1 crossover
								 * Count value is: 66000000/2, that is, the timing period is 500ms */
	while(1){	
		delay(500);
	}
	return 0;
}

4.Download Verification

  • Modify Makefile file file: Modify TARGET to epittimer, append "bsp/epittimer" folder
  • Download bin s to SD card using imxdownload software
  • After successful burning, insert SD card and reset LED 0 blinks continuously in 500ms cycle

Posted by dumdumsareyum on Sat, 11 Sep 2021 09:53:23 -0700