RTEMS 的 AT91SAM9260 移植(4): 中断驱动

中断驱动AT91rm9200和AT9260差别不大,主要要修改的地方是个别的中断向量号,另外就是最大中断向量号。

我所作的修改:

c/src/lib/libcpu/arm/at91sam9260/irq/irq.h

删除了相关的9200的定义,定义了AT9260中断的最大数量。

/* * Interrupt handler Header file * * Bacon Xu */ #ifndef __IRQ_H__ #define __IRQ_H__ #ifdef __cplusplus extern "C" { #endif #ifndef __asm__ /* * Include some preprocessor value also used by assember code */ #include <rtems.h> #include <at91sam9260.h> extern void default_int_handler(); /*********************************************************************** * Constants **********************************************************************/ /* possible interrupt sources on the AT9260*/ #define AT91SAM9260_MAX_INT 32 /* vector table used by shared/irq_init.c */ /* we can treat the AT91SAM9260 AIC_SVR_BASE as */ /* a vector table */ #define VECTOR_TABLE AT91C_AIC_SVR typedef unsigned char rtems_irq_level; typedef unsigned char rtems_irq_trigger; struct __rtems_irq_connect_data__; /* forward declaratiuon */ typedef unsigned int rtems_irq_number; typedef void (*rtems_irq_hdl) (uint32_t vector); typedef void (*rtems_irq_enable) (const struct __rtems_irq_connect_data__*); typedef void (*rtems_irq_disable) (const struct __rtems_irq_connect_data__*); typedef int (*rtems_irq_is_enabled)(const struct __rtems_irq_connect_data__*); typedef struct __rtems_irq_connect_data__ { /* IRQ line */ rtems_irq_number name; /* Handler */ rtems_irq_hdl hdl; /* function for enabling interrupts at device level. */ rtems_irq_enable on; /* function for disabling interrupts at device level. */ rtems_irq_disable off; /* Function to test if interrupt is enabled */ rtems_irq_is_enabled isOn; /* priority level of interrupt */ rtems_irq_level irqLevel; /* Trigger method (rising/falling edge or high/low level) */ rtems_irq_trigger irqTrigger; } rtems_irq_connect_data; /* * function to initialize the interrupt for a specific BSP */ void BSP_rtems_irq_mngt_init(); /* * function to connect a particular irq handler. */ int BSP_install_rtems_irq_handler (const rtems_irq_connect_data*); /* * function to get the current RTEMS irq handler for ptr->name. */ int BSP_get_current_rtems_irq_handler (rtems_irq_connect_data* ptr); /* * function to disconnect the RTEMS irq handler for ptr->name. */ int BSP_remove_rtems_irq_handler (const rtems_irq_connect_data*); #endif /* __asm__ */ #ifdef __cplusplus } #endif #endif /* __IRQ_H__ */

 

c/src/lib/libcpu/arm/at91sam9260/irq/irq.c中主要修改isValidInterrupt函数。

还有相关寄存器的引用。

/* * Atmel AT91SAM9260 Interrupt handler * * Bacon Xu */ #include <bsp.h> #include <irq.h> #include <rtems/score/thread.h> #include <rtems/score/apiext.h> #include <at91sam9260.h> /* * This function check that the value given for the irq line * is valid. */ static int isValidInterrupt(int irq) { if ( (irq < 0) || (irq >= AT91SAM9260_MAX_INT)) { return 0; } return 1; } /* * Installs the interrupt handler. */ int BSP_install_rtems_irq_handler (const rtems_irq_connect_data* irq) { rtems_interrupt_level level; if (!isValidInterrupt(irq->name)) { return 0; } /* * Check if default handler is actually connected. If not, issue * an error. Note: irq->name is a number corresponding to the * sources PID (see the at91sam9260_pid for this mapping). We * convert it to a long word offset to get source's vector register */ if (AT91C_BASE_AIC->AIC_SVR[irq->name] != (uint32_t) default_int_handler) { return 0; } rtems_interrupt_disable(level); /* * store the new handler */ //AIC_SVR_REG(irq->name * 4) = (uint32_t) irq->hdl; AT91C_BASE_AIC->AIC_SVR[irq->name] = (uint32_t) irq->hdl; /* * unmask interrupt */ //AIC_CTL_REG(AIC_IECR) = 1 << irq->name; AT91C_BASE_AIC->AIC_IECR = 1 << irq->name; /* * Enable interrupt on device */ if(irq->on) { irq->on(irq); } rtems_interrupt_enable(level); return 1; } /* * Remove and interrupt handler */ int BSP_remove_rtems_irq_handler (const rtems_irq_connect_data* irq) { rtems_interrupt_level level; if (!isValidInterrupt(irq->name)) { return 0; } /* * Check if the handler is actually connected. If not, issue an error. */ if (AT91C_BASE_AIC->AIC_SVR[irq->name] != (uint32_t) irq->hdl) { return 0; } rtems_interrupt_disable(level); /* * mask interrupt */ AT91C_BASE_AIC->AIC_IDCR = 1 << irq->name; /* * Disable interrupt on device */ if(irq->off) { irq->off(irq); } /* * restore the default irq value */ AT91C_BASE_AIC->AIC_SVR[irq->name] = (uint32_t) default_int_handler; rtems_interrupt_enable(level); return 1; } 

 

 

另外修改c/src/lib/libcpu/arm/at91sam9260/irq/bsp_irq_init.c

主要是修改一些寄存器的引用。

/* * Atmel AT91SAM9260 Interrupt handler * * Bacon Xu */ #include <irq.h> #include <bsp.h> #include <at91sam9260.h> extern void default_int_handler(void); /* * Interrupt system initialization. Disable interrupts, clear * any that are pending. */ void BSP_rtems_irq_mngt_init(void) { long *vectorTable; int i; /* disable all interrupts */ AT91C_BASE_AIC->AIC_IDCR = 0xFFFFFFFF; AT91C_BASE_AIC->AIC_EOICR = 0x00000000; vectorTable = (long *) VECTOR_TABLE; /* Initialize the vector table contents with default handler */ for (i = 0; i < BSP_MAX_INT; i++) { *(vectorTable + i) = (long)(default_int_handler); } AT91C_BASE_AIC->AIC_SPU = (unsigned int)0; }

 

至此,中断的驱动也完成了。

这里要特别的注意一下:RTEMS要求所有的中断处理程序都是有参数的,参数为中断的向量号。由于这个BSP是我学习之初做的,也并没有顾及这个问题。具体代码在 c/src/lib/libcpu/arm/at91sam9260/irq/bsp_irq_asm.S中。只要中断处理程序中不使用这个参数,还是没有多大问题的。本身AT9260的中断就是设备分开的,也不是太需要,但是需要的朋友还是要做一些修改。

 

 

你可能感兴趣的:(function,struct,vector,table,preprocessor,Constants)