📄 sysintrctl.c
字号:
/* sysIntrCtl.c - pxa270 for interrupt controller driver *//* Copyright 2002, Wind River Systems, Inc. *//*TODO - Remove the pxa270 modification history and begin a new history starting with version 01a and growing the history upward with each revision.modification history--------------------01a,21may02,scm written.*//* TODO - Fill in this file with I/O addresses and related constants for the pxa270 BSP. Anything with "pxa270" as a prefix needs to examined and re-named to id the BSP (i.e. iq80321, iq80310, etc.) *//*This module implements the pxa270 interrupt controller driver.The pxa270 does not have a true interrupt controller, so the interruptprocessing must be in non-preemptive mode. Effectively there is only oneinterrupt level, but there are 32 interrupt vectors. These are managedby the intArchLib.The number of interrupts supported by the software is pxa270_INT_NUM_LEVELS.The actual registers referenced are: pxa270_INTCTL_REG pxa270_IINTSRC_REGWe assume that config.h or pxa270.h has defined the above addresses.This driver assumes that the chip is memory-mapped and does directmemory accesses to the registers which are assumed to be 32 bits wide.If a different access method is needed, the BSP can redefine the macros.The BSP will initialize this driver in sysHwInit2(), after initializingthe main interrupt library, usually intLibInit(). The initializationroutine, pxa270IntDevInit() will setup the interrupt service.All of the functions in this library are global. This allows them tobe used by the BSP if it is necessary to create wrapper routines or toincorporate several drivers together as one.*/#include "vxWorks.h"#include "config.h"#include "intLib.h"#include "pxa270.h"/* hardware access methods *//* Convert level number to vector number */#ifndef pxa270_INT_LVL_VEC_MAP#define pxa270_INT_LVL_VEC_MAP(level, vector) \ ((vector) = ((level) + pxa270_INT_VEC_BASE))#endif /* pxa270_INT_LVL_VEC_MAP *//* Convert pending register value, to a level number */#ifndef pxa270_INT_PEND_LVL_MAP#define pxa270_INT_PEND_LVL_MAP(pendReg, level) \ ((level) = (pendReg))#endif /* pxa270_INT_PEND_LVL_MAP *//* Local data *//* Current interrupt level setting (pxa270IntLvlChg). */LOCAL UINT32 pxa270IntLvlCurrent = 0; /* effectively have one level *//* forward declarations */STATUS pxa270IntLvlVecChk (int*, int*);STATUS pxa270IntLvlVecAck (int, int);int pxa270IntLvlChg (int);STATUS pxa270IntLvlEnable (int);STATUS pxa270IntLvlDisable (int);extern void sysIntrEnable();/********************************************************************************* pxa270IntDevInit - 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: OK or ERROR if pxa270IntLvlPriMap invalid.*/int pxa270IntDevInit (void) { int key; /* install the driver routines in the architecture hooks */ sysIntLvlVecChkRtn = pxa270IntLvlVecChk;/*获取最高优先权设备ID*/ sysIntLvlVecAckRtn = pxa270IntLvlVecAck;/*空*/ sysIntLvlChgRtn = pxa270IntLvlChg; sysIntLvlEnableRtn = pxa270IntLvlEnable; sysIntLvlDisableRtn = pxa270IntLvlDisable; /* Mask all the interrupts */ key = intLock (); *((volatile UINT32 *)(PXA270_ICMR)) = 0;/*屏蔽所有中断*/ *((volatile UINT32 *)(PXA270_ICMR2)) = 0;/*屏蔽所有中断*/ *((volatile UINT32 *)(PXA270_ICLR)) = 0;/*设置所有的中断为IRQ中断*/ *((volatile UINT32 *)(PXA270_ICLR2)) = 0;/*设置所有的中断为IRQ中断*/ *((UINT32 *)PXA270_ICCR) = 0x1;/*中断引起处理器跳出空闲模式*/ sysIntrEnable(); *((UINT32*)0x40e0003c) = 0x1;/*当检测到GPIO管脚的下降沿时设置GEDR状态位*/ *((UINT32*)0x40e00048) = 0x1;/*Clear edge detect status field.*/ intUnlock (key); return OK; }/********************************************************************************* pxa270IntLvlVecChk - 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 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 pxa270IntLvlVecChk ( int* pLevel, /* ptr to receive old interrupt level */ int* pVector /* ptr to receive current interrupt vector */ ) { int newLevel; int key; /* Read pending interrupt register and mask undefined bits */ key = intLock (); newLevel = *((UINT32 *)PXA270_ICHP);/*找到最高优先权设备ID*/ if((newLevel & 0x80000000) == 0) return ERROR; /*因为是IRQ,所以右移16位,取出后5位的设备ID位*/ newLevel = (newLevel >> 16)&0x1f; if(newLevel == 8) { newLevel = IRQ_DM9k; } *pLevel = newLevel; *pVector = INUM_TO_IVEC(newLevel);/*将newLevel 转换成中断向量 */ newLevel = *((UINT32 *)PXA270_ICIP) ;/*获取引起IRQ中断的中断源*/ intUnlock (key); return OK; }/********************************************************************************* pxa270IntLvlVecAck - acknowledge the current interrupt** This is a no-op** Since pxa270IntLvlVecChk doesn't change the state of the system,* there is nothing here that needs to be undone.** It is assumed that the interrupt service routine has cleared the* interrupt source itself.** RETURNS: OK or ERROR if a hardware fault is detected.* ARGSUSED*/STATUS pxa270IntLvlVecAck ( int level, /* old interrupt level to be restored */ int vector /* current interrupt vector, if needed */ ) { return OK; }/********************************************************************************* pxa270IntLvlChg - change the interrupt level value** This is a no-op since we effectively have one level.** RETURNS: Previous interrupt level.*/int pxa270IntLvlChg ( int level /* new interrupt level */ ) { return pxa270IntLvlCurrent; }/********************************************************************************* pxa270IntLvlEnable - 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 to* enable interrupts of this priority (as configured by pxa270IntLvlPriMap,* if appropriate). 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 pxa270IntLvlEnable ( int level /* level to be enabled */ ) { int key; if (level < 0 || level >= pxa270_INT_NUM_LEVELS) return ERROR; key = intLock (); if(level >PXA_INTERNAL_IRQS) level = IRQ_GPIO0; *((volatile UINT32 *)(PXA270_ICMR)) |= (1 << level);/*打开屏蔽位*/ *((volatile UINT32 *)(PXA270_IPR0+4*level)) =( level | 0x80000000);/*写设备ID,并使之有效*/ intUnlock (key); return OK; }/********************************************************************************* pxa270IntLvlDisable - 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 to enable interrupts of this priority (as configured by* pxa270IntLvlPriMap, if appropriate).** RETURNS: OK or ERROR, if the specified interrupt level cannot be disabled.*/STATUS pxa270IntLvlDisable ( int level /* level to be disabled */ ) { int key; if (level < 0 || level >= pxa270_INT_NUM_LEVELS) return ERROR; if(level >PXA_INTERNAL_IRQS) level = IRQ_GPIO0; key = intLock (); *((volatile UINT32 *)(PXA270_ICMR)) &= ~(1 << level);/*屏蔽中断*/ *((volatile UINT32 *)(PXA270_IPR0+4*level)) =0;/*使设备ID无效*/ intUnlock (key); return OK; }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -