S3C2440 key interrupt program

The key interrupt is an external interrupt, that is, it belongs to an abnormal state and can generate an interrupt. So how do we analyze and write a key interrupt code based on S3C2440?
1. The first parameter that we want to initialize the response to is divided into three steps:
1. We must set an interrupt source so that it can send an interrupt signal. It must be ensured that the 2440 can feel the external interrupt, this time it must be achieved by setting the interrupt source.
2. We also need to set up an interrupt controller so that it can send an interrupt signal to the CPU
. 3. We also need to set up the CPU. There is a CPSR in it, which is the main switch of the interrupt.
2. The processing process
must identify the source of the interrupt. Different interrupts execute different interrupt functions.
3. Clear the interrupt after processing

After clarifying the idea of ​​interruption, we started to write code.
Let's look at the data sheet first.
Insert picture description hereFrom the data sheet, we can see that Bit7 is the main interrupt switch. We need to clear Bit7. When Bit7 is set to 1, the CPU cannot interrupt.

Then we start to write the code. Our general purpose of setting is to turn on or off the LED light in the button interrupt. We first define two functions, one is to initialize the interrupt controller, and the other is to initialize the button and set it to The function of the interrupt source. The specific function name is shown in the figure: The Insert picture description here
first function to initialize the interrupt controller is divided into three parts:

  1. Initialization of the interrupt source: Set the button as an interrupt pin so that it can trigger an interrupt when it is pressed or released.
  2. Interrupt the initialization of the controller,
  3. Set the CPSR register of the CPU to enable interrupts

From the data manual and schematic diagram, we can know that the
button pins are: Button 1: GPF0 Button 2: GPG15 Button 3: GPG3 Button 4: GPG11
Insert picture description here
Insert picture description here
Then start writing this part of the code:
1. We first determine the button pin And set him as an interrupt pin. The
specific code is as follows

   /*配置GPIO为中断引脚*/
   GPFCON &= ~((3<<0) | (3<<4));
   GPFCON |=  ((2<<0) | (2<<4));  /*s2,s3被配置为中断引脚*/

   GPGCON &= ~((3<<6) | (3<<11));
   GPGCON |=  ((2<<0) | (2<<11)); /*s4,s5被配置为中断引脚*/
   
   /*设置中断触发方式,按下松开都触发中断,双边沿触发*/

   EXTINT0 |= (7<<0) | (7<<8);    /*s2,s3*/
   EXTINT1 |= (7<<12);            /* s4  */
   EXTINT2 |= (7<<12);            /* s5  */   

Then we look at the interrupt switch control register and look up the data sheet to get: Insert picture description hereWe need to set the position of each interrupt line controller to 0 to enable the interrupt control line.

Then we look at the EINTMASK register Insert picture description here
INTMAKs to mask interrupt generation

Let's look at the INTPBND register Insert picture description hereINTPND to display the interrupt line of the interrupt that is currently taking place with the highest priority. We can take his value to know what interrupt is currently in progress.

Let's first look up the interrupt vector table,
Insert picture description here
and the address of the interrupt vector table can get the address corresponding to each interrupt mode:
/ 0x0c :Abort (prefetch)/
/ 0x10 :Abort (data)/
/ 0x14 :Reserved/
/ 0x18 :IRQ/
/ 0x1c :FIQ/

After knowing the address of the interrupt, we know whether the interrupt is judged by the value of the CPSR register. Let's check the data sheet:
Insert picture description here
check the data sheet to get it. When an external interrupt occurs, the value of the external interrupt CPSR is 10010, return The address is the address of CPSR minus 4.
SRCPND is used to display which interrupt is generated, and the corresponding bit needs to be cleared.
Insert picture description here
Available from the data sheet:

  • bit0-at0
  • bit2-eint2
  • bit5-eint8_23
    Now we can start to write the code:
    first enable the interrupt controller: (enable the interrupt by manipulating INTMSK) After
    Insert picture description here
    enabling the interrupt, you can receive the interrupt from the button. There are multiple interrupt sources. So how should we distinguish each interrupt? From the above, we can see that the INTOFFSET register can determine which interrupt line is currently interrupted. We can analyze the value of the INTOFFSET register to determine which interrupt to handle the interrupt. The code is as follows:
if (bit == 0 || bit == 2 || bit == 5)  /* eint0,2,eint8_23 */
	{
		key_eint_irq(bit); /* 处理中断, 清中断源EINTPEND */
	}

After entering the interrupt and completing the tasks that need to be completed in the interrupt, we need to clear the interrupt flag bit so that we can enter the interrupt next time. When clearing the interrupt, we only need to set the corresponding bit of the SRCPND and INTPND register to 1 to clear the corresponding interrupt. The
code is as follows:

/* 清中断 : 从源头开始清 */
	SRCPND = (1<<bit);
	INTPND = (1<<bit);	

After clearing the interrupt, we then write the interrupt handling function:
The initialization code of the LED and the button is omitted: the
code is as follows:

void key_eint_irq(int irq)
{
	unsigned int val = EINTPEND;
	unsigned int val1 = GPFDAT;
	unsigned int val2 = GPGDAT;
	
	if (irq == 0) /* eint0 : s2 控制 D12 */
	{
		if (val1 & (1<<0)) /* s2 --> gpf6 */
		{
			/* 松开 */
			GPFDAT |= (1<<6);
		}
		else
		{
			/* 按下 */
			GPFDAT &= ~(1<<6);
		}
		
	}
	else if (irq == 2) /* eint2 : s3 控制 D11 */
	{
		if (val1 & (1<<2)) /* s3 --> gpf5 */
		{
			/* 松开 */
			GPFDAT |= (1<<5);
		}
		else
		{
			/* 按下 */
			GPFDAT &= ~(1<<5);
		}
		
	}
	else if (irq == 5) /* eint8_23, eint11--s4 控制 D10, eint19---s5 控制所有LED */
	{
		if (val & (1<<11)) /* eint11 */
		{
			if (val2 & (1<<3)) /* s4 --> gpf4 */
			{
				/* 松开 */
				GPFDAT |= (1<<4);
			}
			else
			{
				/* 按下 */
				GPFDAT &= ~(1<<4);
			}
		}
		else if (val & (1<<19)) /* eint19 */
		{
			if (val2 & (1<<11))
			{
				/* 松开 */
				/* 熄灭所有LED */
				GPFDAT |= ((1<<4) | (1<<5) | (1<<6));
			}
			else
			{
				/* 按下: 点亮所有LED */
				GPFDAT &= ~((1<<4) | (1<<5) | (1<<6));
			}
		}
	}

	EINTPEND = val;
}

Guess you like

Origin blog.csdn.net/weixin_41407439/article/details/89409282