/*---------------------------------------------------------------------------* Project: CtrBrom - libraries - OS File: os_interrupt.c Copyright 2008 Nintendo. All rights reserved. These coded instructions, statements, and computer programs contain proprietary information of Nintendo of America Inc. and/or Nintendo Company Ltd., and are protected by Federal copyright law. They may not be disclosed to third parties or copied or duplicated in any form, in whole or in part, without the prior written consent of Nintendo. $Date:: $ $Rev$ $Author$ *---------------------------------------------------------------------------*/ #include asm void i_osIrqVeneer( void ); /*---------------------------------------------------------------------------* Name: osInitInterrupt Description: Initialize Interrupts Arguments: None Returns: None *---------------------------------------------------------------------------*/ void osInitInterrupt( void ) { static BOOL isInit; if ( isInit == FALSE ) { isInit = TRUE; (void)osDisableIrqAndFiq(); i_osInitInterruptTable(); ((u32*)HW_INTR_VENEER_BUF)[0] = ((u32*)i_osIrqVeneer)[0]; ((u32*)HW_INTR_VENEER_BUF)[1] = ((u32*)i_osIrqVeneer)[1]; #ifdef SDK_ARM11 { u32 num = OS_INTR_ID_NUM; u32 conf = 0; int i; for ( i=0; i asm void i_osIrqVeneer( void ) { INASM_EXTERN( osIrqHandler ) ldr pc, =osIrqHandler LTORG } #include //================================================================================ // InterruptMask //================================================================================ /*---------------------------------------------------------------------------* Name: osEnableInterruptID Description: set Interrupt Set Enable Register Arguments: Interrupt Distributor ID Returns: TRUE if last state is enabled *---------------------------------------------------------------------------*/ BOOL osEnableInterruptID( OSIntrID id ) { BOOL retval; OSIntrMode enabled = osDisableInterrupts(); #ifdef SDK_ARM11 u32 ofs = id/32; u32 sft = id%32; retval = TRUE & (reg_OS_IDR_SET_IE[ofs] >> sft); reg_OS_IDR_SET_IE[ofs] = 1 << sft; #else // SDK_ARM9 OSIntrMask prep = reg_OS_IE; retval = TRUE & (BOOL)(prep >> id); reg_OS_IE = prep | (1 << id); #endif // SDK_ARM9 (void)osRestoreInterrupts( enabled ); return retval; } /*---------------------------------------------------------------------------* Name: osEnableInterruptMask Description: set specified interrupt factor Arguments: mask interrupt factor Returns: previous factors *---------------------------------------------------------------------------*/ OSIntrMask osEnableInterruptMask( OSIntrMask mask ) { OSIntrMode enabled = osDisableInterrupts(); #ifdef SDK_ARM11 OSIntrMask prep = reg_OS_IDR_SET_IE_ALL; reg_OS_IDR_SET_IE_ALL = mask; #else // SDK_ARM9 OSIntrMask prep = reg_OS_IE; reg_OS_IE = prep | mask; #endif // SDK_ARM9 (void)osRestoreInterrupts( enabled ); return prep; } /*---------------------------------------------------------------------------* Name: osDisableInterruptID Description: set Interrupt Clear Enable Register Arguments: Interrupt Distributor ID Returns: TRUE if last state is enabled *---------------------------------------------------------------------------*/ BOOL osDisableInterruptID( OSIntrID id ) { BOOL retval; OSIntrMode enabled = osDisableInterrupts(); #ifdef SDK_ARM11 u32 ofs = id/32; u32 sft = id%32; retval = TRUE & (reg_OS_IDR_SET_IE[ofs] >> sft); reg_OS_IDR_CLR_IE[ofs] = 1 << sft; #else // SDK_ARM9 OSIntrMask prep = reg_OS_IE; retval = TRUE & (BOOL)(prep >> id); reg_OS_IE = prep & ~(1 << id); #endif // SDK_ARM9 (void)osRestoreInterrupts( enabled ); return retval; } /*---------------------------------------------------------------------------* Name: osDisableInterruptMask Description: unset specified interrupt factor Arguments: mask interrupt factor Returns: previous factors *---------------------------------------------------------------------------*/ OSIntrMask osDisableInterruptMask( OSIntrMask mask ) { OSIntrMode enabled = osDisableInterrupts(); #ifdef SDK_ARM11 OSIntrMask prep = reg_OS_IDR_SET_IE_ALL; reg_OS_IDR_CLR_IE_ALL = mask; #else // SDK_ARM9 OSIntrMask prep = reg_OS_IE; reg_OS_IE = prep & ~mask; #endif // SDK_ARM9 (void)osRestoreInterrupts( enabled ); return prep; } /*---------------------------------------------------------------------------* Name: osRestoreInterruptID Description: set Interrupt Clear Enable Register Arguments: id : Interrupt Distributor ID state : state whether interrupt is enabled Returns: TRUE if last state is enabled *---------------------------------------------------------------------------*/ BOOL osRestoreInterruptID( OSIntrID id, BOOL state ) { BOOL retval; OSIntrMode enabled = osDisableInterrupts(); #ifdef SDK_ARM11 u32 ofs = id/32; u32 sft = id%32; retval = TRUE & (reg_OS_IDR_SET_IE[ofs] >> sft); if ( state == TRUE ) { reg_OS_IDR_SET_IE[ofs] = 1 << sft; } else { reg_OS_IDR_CLR_IE[ofs] = 1 << sft; } #else // SDK_ARM9 OSIntrMask prep = reg_OS_IE; retval = TRUE & (BOOL)(prep >> id); if ( state == TRUE ) { reg_OS_IE = prep | (state << id); } else { reg_OS_IE = prep & ~(state << id); } #endif // SDK_ARM9 (void)osRestoreInterrupts( enabled ); return retval; } /*---------------------------------------------------------------------------* Name: osSetInterruptMask Description: set interrupt factor Arguments: mask interrupt factor Returns: previous factors *---------------------------------------------------------------------------*/ OSIntrMask osSetInterruptMask( OSIntrMask mask ) { OSIntrMode enabled = osDisableInterrupts(); #ifdef SDK_ARM11 OSIntrMask prep = reg_OS_IDR_SET_IE_ALL; reg_OS_IDR_CLR_IE[0] = HW_IDR_WORD_MASK; reg_OS_IDR_CLR_IE[1] = HW_IDR_WORD_MASK; reg_OS_IDR_CLR_IE[2] = HW_IDR_WORD_MASK; reg_OS_IDR_CLR_IE[3] = HW_IDR_WORD_MASK; reg_OS_IDR_SET_IE_ALL = mask; #else // SDK_ARM9 OSIntrMask prep = reg_OS_IE; reg_OS_IE = mask; #endif // SDK_ARM9 (void)osRestoreInterrupts( enabled ); return prep; } //================================================================================ // INTERRUPT PENDING //================================================================================ /*---------------------------------------------------------------------------* Name: osClearInterruptPendingID Description: set Interrupt Clear Pending Register Arguments: Interrupt Distributor ID Returns: TRUE if last state is pending *---------------------------------------------------------------------------*/ BOOL osClearInterruptPendingID( OSIntrID id ) { OSIntrMode enabled = osDisableInterrupts(); BOOL retval; #ifdef SDK_ARM11 u32 ofs = id/32; u32 sft = id%32; retval = TRUE & (reg_OS_IDR_SET_PND[ofs] >> sft); reg_OS_IDR_CLR_PND[ofs] = 1 << sft; #else // SDK_ARM9 OSIntrMask prep = reg_OS_IF; retval = TRUE & (BOOL)(prep >> id); reg_OS_IF = (u32)(1 << id); #endif // SDK_ARM9 (void)osRestoreInterrupts( enabled ); return retval; } /*---------------------------------------------------------------------------* Name: osClearInterruptPendingMask Description: reset IF bit (setting bit causes to clear bit for interrupt) Arguments: mask interrupt factor Returns: previous factors *---------------------------------------------------------------------------*/ OSIntrMask osClearInterruptPendingMask( OSIntrMask mask ) { OSIntrMode enabled = osDisableInterrupts(); #ifdef SDK_ARM11 OSIntrMask prep = reg_OS_IDR_SET_PND_ALL; reg_OS_IDR_CLR_PND_ALL = mask; #else // SDK_ARM9 OSIntrMask prep = reg_OS_IF; reg_OS_IF = mask; #endif // SDK_ARM9 (void)osRestoreInterrupts( enabled ); return prep; } #ifdef SDK_ARM11 /*---------------------------------------------------------------------------* Name: osSetInterruptPendingID Description: set Interrupt Set Pending Register Arguments: Interrupt Distributor ID Returns: TRUE if last state is pending *---------------------------------------------------------------------------*/ BOOL osSetInterruptPendingID( OSIntrID id ) { u32 ofs = id/32; u32 sft = id%32; BOOL retval; retval = TRUE & (reg_OS_IDR_SET_PND[ofs] >> sft); reg_OS_IDR_SET_PND[ofs] = 1 << sft; return retval; } /*---------------------------------------------------------------------------* Name: osRestoreInterruptPendingID Description: restore Interrupt Pending Arguments: id : Interrupt Distributor ID state : state whether interrupt is enabled Returns: TRUE if last state is pending *---------------------------------------------------------------------------*/ BOOL osRestoreInterruptPendingID( OSIntrID id, BOOL state ) { u32 ofs = id/32; u32 sft = id%32; BOOL retval; retval = TRUE & (reg_OS_IDR_SET_PND[ofs] >> sft); if ( state == TRUE ) { reg_OS_IDR_SET_PND[ofs] = 1 << sft; } else { reg_OS_IDR_CLR_PND[ofs] = 1 << sft; } return retval; } /*---------------------------------------------------------------------------* Name: osSetEndOfInterruptRegister Description: set ID to End of Interrupt Register change state to Inactive. Arguments: Interrupt Distributor ID Returns: None *---------------------------------------------------------------------------*/ void osSetEndOfInterruptRegister( OSIntrID id ) { reg_OS_CPUI_EOI = id; } /*---------------------------------------------------------------------------* Name: i_osReadHighestPendingInterruptRegister Description: read ID from Highest Pending Interrupt Register Arguments: None Returns: Interrupt Distributor ID *---------------------------------------------------------------------------*/ OSIntrID i_osReadHighestPendingInterruptRegister( void ) { return (OSIntrID)(reg_OS_CPUI_HI_PND & REG_OS_CPUI_HI_PND_ID_MASK); } /*---------------------------------------------------------------------------* Name: i_osReadInterruptAcknowledgeRegister Description: read ID from Interrupt Acknowledge Register get interrupt ID and change state to NotPending and Active. Arguments: None Returns: Interrupt Distributor ID *---------------------------------------------------------------------------*/ OSIntrID i_osReadInterruptAcknowledgeRegister( void ) { return (OSIntrID)(reg_OS_CPUI_ACK & REG_OS_CPUI_ACK_ID_MASK); } #endif // SDK_ARM11 /*---------------------------------------------------------------------------* Name: osIsInterruptPendingID Description: set Interrupt Clear Pending Register Arguments: Interrupt Distributor ID Returns: TRUE if last state is pending *---------------------------------------------------------------------------*/ BOOL osIsInterruptPendingID( OSIntrID id ) { BOOL retval; #ifdef SDK_ARM11 u32 ofs = id/32; u32 sft = id%32; retval = TRUE & (reg_OS_IDR_SET_PND[ofs] >> sft); #else // SDK_ARM9 retval = TRUE & (BOOL)(reg_OS_IF >> id); #endif // SDK_ARM9 return retval; } //================================================================================ // IRQ CHEKE BUFFER //================================================================================ /*---------------------------------------------------------------------------* Name: osSetInterruptCheckID Description: set irq flag to check being called Arguments: irq factors to be set Returns: None *---------------------------------------------------------------------------*/ BOOL osSetInterruptCheckID( OSIntrID id ) { BOOL retval; OSIntrMode enabled = osDisableInterrupts(); #ifdef SDK_ARM11 u32 ofs = id/32; u32 sft = id%32; u32 *buf = &((OSIntrMask *)HW_INTR_CHECK0_BUF)->w[ofs]; #else // SDK_ARM9 u32 sft = id; u32 *buf = (OSIntrMask *)HW_INTR_CHECK_BUF; #endif // SDK_ARM9 retval = TRUE & (*buf >> sft); *buf |= 1 << sft; (void)osRestoreInterrupts( enabled ); return retval; } /*---------------------------------------------------------------------------* Name: osClearInterruptCheckID Description: clear irq flag stored in HW_INTR_CHECK_BUF Arguments: irq factors to be set Returns: None *---------------------------------------------------------------------------*/ BOOL osClearInterruptCheckID( OSIntrID id ) { BOOL retval; OSIntrMode enabled = osDisableInterrupts(); #ifdef SDK_ARM11 u32 ofs = id/32; u32 sft = id%32; u32 *buf = &((OSIntrMask *)HW_INTR_CHECK0_BUF)->w[ofs]; #else // SDK_ARM9 u32 sft = id; u32 *buf = (OSIntrMask *)HW_INTR_CHECK_BUF; #endif // SDK_ARM9 retval = TRUE & (*buf >> sft); *buf &= ~(1 << sft); (void)osRestoreInterrupts( enabled ); return retval; } /*---------------------------------------------------------------------------* Name: osIsInterruptCheckID Description: check irq flag stored in HW_INTR_CHECK_BUF Arguments: irq factors to be set Returns: None *---------------------------------------------------------------------------*/ BOOL osIsInterruptCheckID( OSIntrID id ) { BOOL retval; #ifdef SDK_ARM11 u32 ofs = id/32; u32 sft = id%32; u32 *buf = &((OSIntrMask *)HW_INTR_CHECK0_BUF)->w[ofs]; #else // SDK_ARM9 u32 sft = id; u32 *buf = (OSIntrMask *)HW_INTR_CHECK_BUF; #endif // SDK_ARM9 retval = TRUE & (*buf >> sft); return retval; } /*---------------------------------------------------------------------------* Name: osSetInterruptCheckMask Description: set irq flag to check being called Arguments: irq factors to be set Returns: None *---------------------------------------------------------------------------*/ void osSetInterruptCheckMask( OSIntrMask mask ) { OSIntrMode enabled = osDisableInterrupts(); #ifdef SDK_ARM11 ((OSIntrMask *)HW_INTR_CHECK0_BUF)->w[0] |= mask.w[0]; ((OSIntrMask *)HW_INTR_CHECK0_BUF)->w[1] |= mask.w[1]; ((OSIntrMask *)HW_INTR_CHECK0_BUF)->w[2] |= mask.w[2]; ((OSIntrMask *)HW_INTR_CHECK0_BUF)->w[3] |= mask.w[3]; #else // SDK_ARM9 *(OSIntrMask *)HW_INTR_CHECK_BUF |= mask; #endif // SDK_ARM9 (void)osRestoreInterrupts( enabled ); } /*---------------------------------------------------------------------------* Name: osClearInterruptCheckMask Description: clear irq flag stored in HW_INTR_CHECK_BUF Arguments: irq factors to be cleared Returns: None *---------------------------------------------------------------------------*/ void osClearInterruptCheckMask( OSIntrMask mask ) { OSIntrMode enabled = osDisableInterrupts(); #ifdef SDK_ARM11 ((OSIntrMask *)HW_INTR_CHECK0_BUF)->w[0] &= ~mask.w[0]; ((OSIntrMask *)HW_INTR_CHECK0_BUF)->w[1] &= ~mask.w[1]; ((OSIntrMask *)HW_INTR_CHECK0_BUF)->w[2] &= ~mask.w[2]; ((OSIntrMask *)HW_INTR_CHECK0_BUF)->w[3] &= ~mask.w[3]; #else // SDK_ARM9 *(OSIntrMask *)HW_INTR_CHECK_BUF &= ~mask; #endif // SDK_ARM9 (void)osRestoreInterrupts( enabled ); } /*---------------------------------------------------------------------------* Name: osIsInterruptCheckMask Description: check irq flag stored in HW_INTR_CHECK_BUF Arguments: irq factors to be cleared Returns: TRUE if irq flag exists *---------------------------------------------------------------------------*/ BOOL osIsInterruptCheckMask( OSIntrMask mask ) { u32 tmp; #ifdef SDK_ARM11 OSIntrMode enabled = osDisableInterrupts(); tmp = ((OSIntrMask *)HW_INTR_CHECK0_BUF)->w[0] & mask.w[0]; tmp |= ((OSIntrMask *)HW_INTR_CHECK0_BUF)->w[1] & mask.w[1]; tmp |= ((OSIntrMask *)HW_INTR_CHECK0_BUF)->w[2] & mask.w[2]; tmp |= ((OSIntrMask *)HW_INTR_CHECK0_BUF)->w[3] & mask.w[3]; (void)osRestoreInterrupts( enabled ); #else // SDK_ARM9 tmp = osGetInterruptCheckMask() & mask; #endif // SDK_ARM9 return tmp ? TRUE : FALSE; } //============================================================================ // WAIT //============================================================================ /*---------------------------------------------------------------------------* Name: osWaitInterruptID Description: wait specifiled interrupt. OS_WaitInterrupt doesn't switch thread. OS_WaitInterrupt wait by using OS_Halt(). Arguments: clear TRUE if want to clear interrupt flag before wait. FALSE if not. irqFlags bit of interrupts to wait for Returns: None *---------------------------------------------------------------------------*/ void osWaitInterruptID( BOOL clear, OSIntrID id ) { OSIntrMode cpsrIrq = osDisableInterrupts(); if (clear) { (void)osClearInterruptCheckID( id ); } while (! osIsInterruptCheckID(id) ) { osHalt(); (void)osEnableInterrupts(); (void)osDisableInterrupts(); } (void)osClearInterruptCheckID( id ); (void)osRestoreInterrupts( cpsrIrq ); } /*---------------------------------------------------------------------------* Name: osWaitInterruptMask Description: wait specifiled interrupt. OS_WaitInterrupt doesn't switch thread. OS_WaitInterrupt wait by using OS_Halt(). Arguments: clear TRUE if want to clear interrupt flag before wait. FALSE if not. irqFlags bit of interrupts to wait for Returns: None *---------------------------------------------------------------------------*/ void osWaitInterruptMask( BOOL clear, OSIntrMask irqFlags ) { OSIntrMode cpsrIrq = osDisableInterrupts(); if (clear) { (void)osClearInterruptCheckMask( irqFlags ); } while (! osIsInterruptCheckMask(irqFlags) ) { osHalt(); (void)osEnableInterrupts(); (void)osDisableInterrupts(); } (void)osClearInterruptCheckMask( irqFlags ); (void)osRestoreInterrupts( cpsrIrq ); }