📄 irq.c
字号:
/*
* irq.c - demo of irq handler api
*
* Author: li ming <admin@lumit.org>
* Date: 2005-6-12
* Copyleft: http://www.lumit.org
*/
#define SYSCFG 0x03FF0000
#define INTPND (*((volatile unsigned *)(SYSCFG+0x4004)))
#define INTMSK (*((volatile unsigned *)(SYSCFG+0x4008)))
#define INT0_MASK (1 << 0)
#define TIMER_MASK (1 << 10)
#define TDATA0 (*((volatile unsigned *)(SYSCFG+0x6004)))
void int0_hooker(void);
void timer_hooker(void);
#define IRQ_SOURCE_NUM 21
static void (*device_irq_handler[IRQ_SOURCE_NUM])(void);
int request_irq( unsigned int irq, void (*handler)(void) )
{
if( device_irq_handler[irq] )
return -1; // fail to request, free this irq first
// fill the device_irq_handler vector
device_irq_handler[irq] = handler;
return 0;
}
int free_irq( unsigned int irq, void (*handler)(void) )
{
if( !device_irq_handler[irq] )
return -1; // fail to request, free this irq first
// free the device_irq_handler vector
device_irq_handler[irq] = 0;
return 0;
}
/* Clear all existing pending bit */
void clear_irq_pending(void)
{
INTPND |= INTPND;
}
void unmask_irq(int irq_num)
{
INTMSK &= ~((1<<21) | (1 <<irq_num));
}
void do_irq( void )
{
void (* current_pc)();
int irq_source;
int i;
// get irq number from INTPND
irq_source = INTPND;
// get current device irq handler to current_pc
for( i = 0; i < IRQ_SOURCE_NUM; i++ )
{
if( irq_source & ( 1 << i ) )
{
/* clear the pending bit */
INTPND = 1 << i;
// here is an interrup at source i
if( device_irq_handler[i] )
{
current_pc = device_irq_handler[i];
// call registered device irq handler to do_irq
((void (*)(void))(current_pc))(); /* thanks, STheobald */
}
}
}
return;
}
void install_irq_handler( void (*isr)(void) )
{
/* ARM irq exception vector addr is 0x00000018 */
unsigned int * irq_vec_addr = ( unsigned int * ) 0x18;
/* this is isr entry address, could be another address like 0x3c, 0x58... */
unsigned int * isr_entry_addr = ( unsigned int * ) 0x38;
unsigned int instruction;
/* set the ISR entry at 0x38 */
*isr_entry_addr = (unsigned int)isr;
/* make an instruction: it is machine-code for "ldr pc, [pc, #(38-18-8)]" */
instruction = ((unsigned int) isr_entry_addr - (unsigned int)irq_vec_addr - 0x08) | 0xe59ff000;
/* set this instruction at 0x18 */
*irq_vec_addr = instruction;
return;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -