JZ2440 bare board development and abnormal interrupt practice # 7 (2)

Interrupt

Interrupt Controller

Benpian talk about interrupts, Part I have been told about exceptions and exception handling, the interrupt is an anomaly, so treatment is also similar, the main difference with other abnormalities, the presence of an interrupt controller that role.

Interrupt process is an interrupt source -> Interrupt Controller -> handler, there are many types interrupt source, an interrupt may be a serial port, a timer interrupt or an external interrupt. And the controller controls whether the interrupt is masked, and the interrupt priority level of the interrupt status. The handler and the exception handler is no different, as long as you can write according to their needs.

 The picture shows a block diagram of the interrupt controller, the interrupt source is the left most, divided into two sources, except that only how two sub source registers and SUBSRCPND SUBMASK control interrupt. What kind of interrupt sources have attributed the S3C2440 listed in the table:

 Here are the main source of discussion interrupt sources, you can see a description of a specific interrupt source has described, according to their own needs one to one, but the most important thing to understand in a grouping Arbiter, source interrupt source is divided into five groups , each no more than six interrupt sources, the final allocation result shown below, this assignment is mainly to realize the interrupt priority level, the presence of ARBITER each group two control signals: 1bitARB_mode, 2bitsARB_SEL, wherein for selecting ARB_SEL interrupt prioritized manner. Four kinds of priority order can be seen in the following figure, four combinations of two ARB_SEL represented REQ0 where the highest priority is fixed, the corresponding fixed REQ5 lowest priority, and with the REQ1-4 ARB_SEL Rotate left increases, we can directly set ARB_SEL to determine the priority order, the priority order ARB_mode be further affected when ARB_mode is 0, we are permanently fixed ARBS_SEL determined by the priority order, unless we could modify . When ARB_mode 1, each interrupt response time, and make ARB_SEL increased 1 that left one cycle, resulting in the highest priority interrupt becomes the lowest priority, thus ensuring lower-priority interrupts have the opportunity to get a response prevent hunger, which is also known as round-robin scheduling, scheduling similar with os, so here ARB_mode round-robin scheduling can also be said of the switch.

 Interrupt controller 5 has a control for the source register for the interrupt source: source Pending Register, MODE Register interrupt, mask
Register, priority Pending Register and Register interrupt
. Wen first one correspondence may block diagram on.

In which the source pending register and interrupt pending register similar, used to indicate which interrupt is triggered when the interrupt is triggered, the corresponding interrupt bit is set, the difference will be that all SRCPND triggered interrupt is asserted, but only for current needs INTPND the highest priority interrupt processing set, SRCPND screened into the highest priority interrupt to interrupt processing after the INTPND, INTPND received through the shield and the priority register mASK. It should be noted that these two registers need to be cleared after the process is completed, otherwise it would have been the response has been treated repeated interrupts. And the need to start from the source SRCPND-> INTPND, so it will not set again after clearing INTPND SRCPND. Mode setting is set to 1 in the corresponding bit.

 MASK register is used to mask interrupts, interrupt source when the corresponding bit is set, then the system interrupts are not acknowledged, and even come SRCPND interrupt bit is set, do not respond, but if the set INTPND directly, or require a response processing (INTPND after MASK, MASK not control).

 Mode register is used to control the interrupt or normal interrupt fast break, on the one already described FIQ because they have more of their own exclusive register, and therefore preserve the scene and recover the cost of the smaller field, the response speed is faster, so it is said for the fast break. Here default value is 0, that bit ordinary interrupt by default.

 Recall that in the priority register, and only needs to turn the rotary switch according to need, to set the interrupt priority order.

 

 In addition to the controller, if the system needs to respond to the interrupt, also need the I-bit CPSR-mentioned section F-bit or open, which is the system master switch interrupt process or to the I-bit F- bit cleared.

Add that, in order to facilitate S3C2440 resolution interrupt handler interrupt source register set INTOFFSET, different interrupt sources have different offset value, the register value can be directly compared with the standard.

 

External interruption

In addition to the interrupt controller needs to be configured, the interrupt source also needs to be configured. In an example where an external interrupt, an external interrupt switch is a button for the desired button is pressed, an interrupt is triggered, LED lights.

In https://blog.csdn.net/G_METHOD/article/details/104271762 also written a content key, that is polling way to carry out key state detection, more consumption of CPU resources, and the use of external interrupt event-free approach allows CPU to handle other things occurs, and when an event is triggered, and timely treatment. copy of the schematic and click the button corresponding to the key foot table.

EINT0 EINT2 EINT11 EINT19
GPF0 GPF2 GPG3 GPG11

 The last time we set it to the input pins can be read pin for the key state, the need to use an external interrupt, you need to set it to the corresponding external interrupt mode. Seen from the FIG., As long as the corresponding GPxCON pin is set to an external interrupt pin.

 In addition to the GPIO register needs to be set, but also need to set up an external interrupt. As follows, provided EXTINT trigger can specify the external interrupt is low, high, rising, falling, or double edge triggered. Here we chose to use double edge triggered, according to their needs or preferences may be selected.

 It should be noted that some external interrupt pin exists filtering played external interrupts 32 or 51 can be known, the level key is pressed there will be jitter, if not the dither processing, the interrupt trigger button press operation may be trigger multiple interrupt events, such as buttons for lighting, but shake triggered more than once, so every time you press the button once the lights are blinking. Anti-shake mode can be filtered, filtering crude way, this is a period of delay waiting for stable level, where chip help us to do the filtering, of course, you can write to turn off filtering function register, there are clock time and other registers to configure filtering .

 

 Interrupt controller compares Similarly, the external interrupt mask register and the register is also present PEND registers, similarly, the interrupt mask to mask, the PEND indicates that one external interrupt trigger. Similarly, after processing the interrupt to clear the corresponding bit PEND.

 Control of the above-described interrupt register in the interrupt source, but the interrupt handler in the interrupt source is determined, if the PND using the interrupt controller can not determine the specific source of the interrupt (e.g., there are several external interrupts share EINT a flag) In this case it is necessary by external interrupt register to a PND which distinguish a particular source of the interrupt.

According to the above output code as follows:

.text
.global _start

_start:
	B RESET	
	LDR pc,UNDEFIE
	LDR pc,SW_INTERRUPT
	B ABORT_PREFETCH
	B ABORT_DATA
	B halt				//reserve
	LDR pc,INTERRUPT
	B FIQ_HANDLE

UNDEFIE:
	.word DO_UND	
	
SW_INTERRUPT:
	.word DO_SWI

INTERRUPT:
	.word DO_INTERRUPT
	

ABORT_PREFETCH:
ABORT_DATA:	
IRQ_HANDLE:
FIQ_HANDLE:
	B halt

DO_UND:
	//1.设置栈
	LDR SP,=0x34000000
	//2.保存现场
	STMDB SP!,{R0-R12,LR}

	//处理函数
	MRS R0,CPSR
	LDR R1,=UND_TEST_STRING
    BL ExecptionHandle
	
	//3.恢复现场,跳转回原来的位置
	LDMIA SP!,{R0-R12,PC}^  //^ 表示将SPSR恢复到CPSR中
	
DO_SWI:
	//1.设置栈
	LDR SP,=0x33e00000
	//2.保存现场
	STMDB SP!,{R0-R12,LR}
	
	//处理函数
	MRS R0,CPSR
	LDR R1,=SWI_TEST_STRING
	SUB R2,LR,#4
    BL SWIHandler
	
	//3.恢复现场,跳转回原来的位置
	LDMIA SP!,{R0-R12,PC}^  //^ 表示将SPSR恢复到CPSR中

DO_INTERRUPT:
	//1.设置栈
	LDR SP,=0x33d00000
	//2.保存现场
	SUBS LR, LR, #4
	STMDB SP!,{R0-R12,LR}
	
	//处理函数
    BL InterruptHandler
    bl testPrint1
	
	//3.恢复现场,跳转回原来的位置
	LDMIA SP!,{R0-R12,PC}^  //^ 表示将SPSR恢复到CPSR中

UND_TEST_STRING:
	.string "enter undefin mode!\n"
	
SWI_TEST_STRING:
	.string "enter swi mode!\n"

.align 4
RESET:
	MOV R0,#0
	LDR R1,[R0]
	
	STR R0,[R0]
	LDR R2,[R0]
	
	CMP R2,R0
	LDR SP,=0x40000000+4096
	MOVEQ SP,#4096
	STREQ R1,[R0]
	
	BL HardwareInitAll
	BL UartInit
	
TEST_UND:
	bl testPrint
	.word 0xdeadc0de
	//bl testPrint
TEST_SWI:
	MRS R0,CPSR
	BIC R0,R0,#0x0F
	MSR CPSR,R0
	SWI 0x123
	
	LDR pc,=main
halt:
    B halt
interrupt.h
----------------------
#ifndef __INTERRUPT_H
#define __INTERRUPT_H


void AllInterruptInit(void);
void InterruptHandler(void);


#endif


 

interrupt.c
-------------------------------

#include "interrupt.h"
#include <stdint.h>

#include "led.h"
#include "s3c2440.h"


static void InterruptControllerInit(void)
{
	//开启全局中断开关
	asm(
		"MRS R0,CPSR \n\t"
		"BIC R0,R0,#0x80 \n\t"
		"MSR CPSR,R0 \n\t"
	);

	//关闭相关中断的屏蔽
	INTMSK &= ~((1<<0) | (1<<2) | (1<<5)); 

}

static void ExternInterruptInit(void)
{
	//设置为外部中断引脚
	GPFCON &= ~((3<<0)|(3<<4));
	GPFCON |= (2<<0)|(2<<4);
	
	GPGCON &= ~((3<<6)|(3<<22));
	GPGCON |= (2<<6)|(2<<22);

	EXTINT0 |= (7<<0) | (7<<8);     /* S2,S3 */
	EXTINT1 |= (7<<12);             /* S4 */
	EXTINT2 |= (7<<12);
	
	/* 设置EINTMASK使能eint11,19 */
	EINTMASK &= ~((1<<11) | (1<<19));
}


void AllInterruptInit(void)
{
	InterruptControllerInit();
	ExternInterruptInit();
}

void ExtInterruptHandler(uint32_t irq)
{
	uint32_t ext_interrupt_bit = EINTPEND;
	
	switch(irq)
	{
		case 0:
		{
			ToggleLed(kLed1);
			break;
		}

		case 2:
		{		
			ToggleLed(kLed2);
			break;
		}
		
		case 5:
		{
			if(ext_interrupt_bit &( 1 << 9 ))
			{		
				ToggleLed(kLed3);
			}
			else if(ext_interrupt_bit &( 1 << 11 ))
			{			
				ToggleLed(kLed1);
				ToggleLed(kLed2);
				ToggleLed(kLed3);
			}
			
			break;
		}
		default:
			break;
	}
	
	EINTPEND = ext_interrupt_bit;
}

void InterruptHandler(void)
{
	uint32_t interrupt_bit = INTOFFSET;

	if(interrupt_bit>=0 && interrupt_bit <=5)
	{
		ExtInterruptHandler(interrupt_bit);
	}

	SRCPND = 1<< interrupt_bit;
	INTPND = 1<< interrupt_bit;
}


This code is not actually write workload, some register directly using the default value without modification, but still card me a long time, mainly after pressing the button to execute the interrupt function will always somehow runaway or inexplicable restart, last look dis is found on one of the mentioned abnormal return different values ​​require different treatment of this point, the need to interrupt the return value of minus 4 to return to the normal flow of the program.

 

Timer

Timers can tell from the name is used to timing, put it here because of his presence interrupted interrupt function, not only the timer interrupt function. After setting the timer interrupt is generated by a predetermined time may be used to perform tasks periodically or temporally, on the other hand, by comparing the timer enable register PWM output timer pin, the power supply control unit or other energy required peripherals, breathing light can be achieved by this function, it can be also output as the clock source peripherals.

S3C2440 has five 16-bit clock, the clock estimates different reasons of cost or because of difficult to achieve, the presence of functional castration or shared resources. TIMER0 is the most complete of a timer.

 From left to right, you can see the clock timer uses PCLK to drive before the content has been PCLK to 50MHz. An 8-bit prescaler exists after the PCLK, may require the use of division, i.e. reduce the clock frequency used thereafter can also reduce the frequency divider in time, where the frequency division selection by setting a frequency division number register MUX . Timer exists TCMPB, TCNTB register, wherein TCMPB compare register, for comparing the current count value to output a PWM wave, TCNTB compared with the initial value set by the timer, when the timer value is 0, we set up automatic and loads, this TCNTB is automatically assigned to the count register. It is also noted that the two registers can be modified at any time, but will not take effect any time when needed in the next timing cycle begins to take effect, so to ensure ongoing count to normal operation. Followed by a digital circuit is negated, followed selector is trapezoidal, invert bit by one to control the output of the waveform is inverted. Dead Zone Generator dead band generator for a safeguard high-power motor with a PWM time, in the application of classical H-bridge circuit to control the motor. Substantially diagram below (AD do not have to use a simple drawing Videos about ···), an intermediate for the motor M, as a triode amplification circuit device, when the ON voltage to the A, B to a zero potential, and the circuit A is turned on the second case, assuming that the motor is transferred corresponding to FIG. When the voltage is turned to B and A to the time 0, B-side circuit is turned on, the motor reverse case, corresponding to the third case of FIG. When the motor required to reverse or vice-versa around from the positive, bound through a voltage switching time A and B, with a true analog voltages it is not possible mutations. At this time, if there is no dead time period, while it may be A and B are in the ON voltage range, in case a short circuit directly to the power supply and the ground, in particular the risk of causing a fourth FIG. The dead can help us solve this problem, concrete is no longer expand.

S3C2440 counter is relatively simple, but also set the counter 32 prior to use to increase or decrease, can only be reduced here, also considered worry, when the counter is reduced to 0, that is, the timing of the timer interrupt is triggered. Want to use a timer interrupt, timer controller in addition to the section settings, also need to set the timer and starts. Relevant registers as follows:

The first is a frequency count 8 prescaler, we used the timer 1 is used only for the interrupt, and therefore only the prescaler to 0. There is also need complex division factor used by these two numbers to make the clock down to an appropriate value, where the value in fact enough on the line, such as herein provided directly to prescaler 99, and 16 using frequency division, according to the final formula clock is 50MHz / ((99 + 1) * 16) = 31250Hz.

 After determining the clock, the count value is determined to obtain the timer period, here it is not necessary since no PWM output compare register is provided, only need to set the initial value to the count TCMPB0. Suppose we expect 0.5s interrupted once, according to the clock obtained above, you can know that we need to set the initial value of 15625, you can get 0.5s interrupted once the desired effect.

 The last is a need to set the clock control register, the same attention only to the relevant timer 0, timer set to automatically reload the initial value of 0, since it is unnecessary to output clock pin, where the tube can not invert, the default values according to the chip manual mentioned for the first time need to manually start the manual update manually set, but need to clear this bit before writing next time. Finally, start the timer.

 Other similar content on external interrupt, external interrupt only on the basis of the program, plus timer is initialized, the timer interrupt handler, while closing the associated timer interrupt mask to thereby output the code as follows:

interrupt.c
------------------------------------

#include "interrupt.h"
#include <stdint.h>

#include "led.h"
#include "s3c2440.h"

typedef void (*irq_func)(int);
irq_func irq_array[32];

static void register_irq(int irq, irq_func fp)
{
	irq_array[irq] = fp;
	INTMSK &= ~(1<<irq);
}

void Timer0InterruptHandler(int irq)
{
	ToggleLed(kLed1);
}

void ExtInterruptHandler(int irq)
{
	uint32_t ext_interrupt_bit = EINTPEND;
	
	switch(irq)
	{
		case 0:
		{
			ToggleLed(kLed1);
			break;
		}

		case 2:
		{		
			ToggleLed(kLed2);
			break;
		}
		
		case 5:
		{
			if(ext_interrupt_bit &( 1 << 9 ))
			{		
				ToggleLed(kLed3);
			}
			else if(ext_interrupt_bit &( 1 << 11 ))
			{			
				ToggleLed(kLed1);
				ToggleLed(kLed2);
				ToggleLed(kLed3);
			}
			
			break;
		}
		default:
			break;
	}
	
	EINTPEND = ext_interrupt_bit;
}


static void InterruptControllerInit(void)
{
	//开启全局中断开关
	asm(
		"MRS R0,CPSR \n\t"
		"BIC R0,R0,#0x80 \n\t"
		"MSR CPSR,R0 \n\t"
	);
}

static void ExternInterruptInit(void)
{
	//设置为外部中断引脚
	GPFCON &= ~((3<<0)|(3<<4));
	GPFCON |= (2<<0)|(2<<4);
	
	GPGCON &= ~((3<<6)|(3<<22));
	GPGCON |= (2<<6)|(2<<22);

	EXTINT0 |= (7<<0) | (7<<8);     /* S2,S3 */
	EXTINT1 |= (7<<12);             /* S4 */
	EXTINT2 |= (7<<12);
	
	/* 设置EINTMASK使能eint11,19 */
	EINTMASK &= ~((1<<11) | (1<<19));
	
	register_irq(0,ExtInterruptHandler);
	register_irq(2,ExtInterruptHandler);
	register_irq(5,ExtInterruptHandler);
}

static void Timer0InterruptInit(void)
{
	TCFG0 = 99;  
	TCFG1 &= ~0xf;
	TCFG1 |= 3;

	TCNTB0 = 15625;

	TCON |= (1<<1);

	TCON &= ~(1<<1);
	TCON |= (1<<0) | (1<<3);

	/* 设置中断 */
	register_irq(10, Timer0InterruptHandler);
}


void AllInterruptInit(void)
{
	InterruptControllerInit();
	ExternInterruptInit();
	Timer0InterruptInit();
}

void InterruptHandler(void)
{
	uint32_t interrupt_bit = INTOFFSET;

	irq_array[interrupt_bit](interrupt_bit);

	SRCPND = 1<< interrupt_bit;
	INTPND = 1<< interrupt_bit;
}


 With the preliminary work, the timer interrupt here to do very little, here to remove the normal function using the array of function pointers optimized code structure, when the interrupt initialization, requiring registration interrupt number and interrupt handlers, so that the total interruption handlers need not be modified during subsequent increased functionality, coupling to reduce the code. Code effect led light off, ha ha visually 0.5s.

 

Published 19 original articles · won praise 7 · views 6918

Guess you like

Origin blog.csdn.net/G_METHOD/article/details/104620994