阅读:1486回复:0
关于FS44B0X的中断问题,请教各位大侠!
本人已经初步改写好了s3c44b0x的VXWORKS BSP代码,调试完成了串口poll模式输出功能,中断处理也已经能进入intEnter函数,并且自己用intConnnect连接的中断处理函数也能执行,但问题是:使用外部中断4567,只要按下一次中断按键,则中断一直不停止!(清除EXTINTPND,则系统复位,若使用定时器中断,则一次定时器中断进入中断服务程序四次,然后系统复位)
相关的代码如下:(调试了很长时间,代码已经被高度简化成最简单功能,一次只能开启一个中断) #include "vxWorks.h" #include "config.h" #include "intLib.h" #include "FS44B0X.h" /* Defines from FS44B0X100.h */ #if !defined (FS44B0X_INT_CON) || !defined (FS44B0X_INT_PEND) || \ !defined (FS44B0X_INT_MODE) || !defined (FS44B0X_INT_MASK) || \ !defined (FS44B0X_INT_NUM_LEVELS ) # error missing FS44B0X interrupt definitions #endif #ifndef FS44B0X_INT_REG_READ #define FS44B0X_INT_REG_READ(x,result) ((result) = *(volatile UINT32 *)(x)) #endif /*FS44B0X_INT_REG_READ*/ #ifndef FS44B0X_INT_REG_WRITE #define FS44B0X_INT_REG_WRITE(x,data) (*((volatile UINT32 *)(x)) = (data)) #endif /*FS44B0X_INT_REG_WRITE*/ /* * A mask word. Bits are set in this word when a specific level * is enabled. It is used to mask off individual levels that have * not been explicitly enabled. */ LOCAL UINT32 FS44B0XIntLvlEnabled; /* forward declarations */ STATUS FS44B0XIntLvlVecChk (int*, int*); STATUS FS44B0XIntLvlVecAck (int level,int vector); STATUS FS44B0XIntLvlEnable (int); STATUS FS44B0XIntLvlDisable (int); /******************************************************************************* * * FS44B0XIntDevInit - initialize the interrupt controller * * This routine will initialize the interrupt controller device, disabling all * interrupt sources. It will also connect the device driver specific routines * into the architecture level hooks. If the BSP needs to create a wrapper * routine around any of the arhitecture level routines, it should install the * pointer to the wrapper routine after calling this routine. * * RETURNS: N/A ***********************************************************************************/ void FS44B0XIntDevInit (void) { /* install the driver routines in the architecture hooks */ sysIntLvlVecChkRtn = FS44B0XIntLvlVecChk; sysIntLvlVecAckRtn = FS44B0XIntLvlVecAck; sysIntLvlEnableRtn = FS44B0XIntLvlEnable; sysIntLvlDisableRtn = FS44B0XIntLvlDisable; FS44B0XIntLvlEnabled = 0x0; /* all sources disabled */ FS44B0X_INT_REG_WRITE (FS44B0X_INT_CON,0x05); /* 设置为非向量中断模式,允许IRQ中断,禁止FIQ中断 */ FS44B0X_INT_REG_WRITE (FS44B0X_INT_MODE,0x0); /* 全部设置为IRQ方式 */ FS44B0X_INT_REG_WRITE (FS44B0X_INT_MASK,0x7ffffff); /*禁止全局中断以及所有中断*/ FS44B0X_INT_REG_WRITE (FS44B0X_I_ISPC,0x3ffffff); /* all IRQ pending bits clear */ FS44B0X_INT_REG_WRITE (FS44B0X_F_ISPC,0x3ffffff); /* all FIQ pending bits clear */ FS44B0X_INT_REG_WRITE(FS44B0X_EXTINTPND,0x0f); } /******************************************************************************* * * FS44B0XIntLvlVecChk - check for and return any pending interrupts * * This routine interrogates the hardware to determine the highest priority * interrupt pending. It returns the vector associated with that interrupt, and * also the interrupt priority level prior to the interrupt (not the * level of the interrupt). The current interrupt priority level is then * raised to the level of the current interrupt so that only higher priority * interrupts will be accepted until this interrupt is finished. * * The return value ERROR indicates that no pending interrupt was found and * that the level and vector values were not returned. * * RETURNS: OK or ERROR if no interrupt is pending. **********************************************************************************/ STATUS FS44B0XIntLvlVecChk(int* pLevel,int* pVector) { int newLevel; int intPendMask = 0x2000000; int count; UINT32 isr; /* FS44B0X_INT_REG_READ (FS44B0X_INT_PEND, newLevel); */ FS44B0X_INT_REG_READ (FS44B0X_I_ISPR, newLevel); newLevel &= FS44B0XIntLvlEnabled; for (count = 0, isr = 25; count < FS44B0X_INT_NUM_LEVELS; count++) { if (intPendMask & newLevel) break; isr--; intPendMask >>= 1; } *pVector = isr ; if(isr == 21) FS44B0X_INT_REG_WRITE_BYTE(FS44B0X_EXTINTPND,0x0f); FS44B0X_INT_REG_WRITE(FS44B0X_I_ISPC,(1<<isr)); return OK; } STATUS FS44B0XIntLvlVecAck (int level,int vector) { /* if(vector == 21) FS44B0X_INT_REG_WRITE_BYTE(FS44B0X_EXTINTPND,0x0f);*/ FS44B0X_INT_REG_WRITE(FS44B0X_I_ISPC,(1<<vector)); /*清除IRQ_MASK中的悬挂位*/ return OK; } /******************************************************************************* * * FS44B0XIntLvlEnable - enable a single interrupt level * * Enable a specific interrupt level. The enabled level will be allowed to * generate an interrupt, when the overall interrupt level is set below the * specified level. Without being enabled, the interrupt is blocked regardless * of the overall interrupt level setting. * * RETURNS: OK or ERROR if the specified level cannot be enabled. ********************************************************************************/ STATUS FS44B0XIntLvlEnable(int level) { UINT32 key; if (level < 0 ||level >= FS44B0X_INT_NUM_LEVELS) return ERROR; FS44B0XIntLvlEnabled |=(1<<level); /* FS44B0X_INT_REG_READ (FS44B0X_INT_MASK,key); key &= ~(0x1<<level); key &= ~(0x1<<SYS_GLOBAL_INT_LVL); FS44B0X_INT_REG_WRITE (FS44B0X_INT_MASK,key);*/ /*写0关闭中断屏蔽位 */ FS44B0X_INT_REG_WRITE (FS44B0X_INT_MASK,~((0x1<<level)|(0x1<<SYS_GLOBAL_INT_LVL))); return OK; } /******************************************************************************* * * FS44B0XIntLvlDisable - disable a single interrupt level * * Disable a specific interrupt level. The disabled level is prevented * from generating an interrupt even if the overall interrupt level is set * below the specified level. * * RETURNS: OK or ERROR, if the specified interrupt level cannot be disabled. *********************************************************************************/ STATUS FS44B0XIntLvlDisable(int level) { int key; if (level < 0 ||level >= FS44B0X_INT_NUM_LEVELS) return ERROR; /* FS44B0XIntLvlEnabled &=~(1<<level); FS44B0X_INT_REG_READ(FS44B0X_INT_MASK,key); key |=(1<<level); key &= ~(0x1<<SYS_GLOBAL_INT_LVL); FS44B0X_INT_REG_WRITE (FS44B0X_INT_MASK,key); */ FS44B0X_INT_REG_WRITE (FS44B0X_INT_MASK,(0x1<<level)); return OK; } |
|