/*---------------------------------------------------------------------------* Project: CtrBrom - libraries - OS File: os_timer.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 //---------------------------------------------------------------------- #ifdef SDK_ARM9 #define REG_OS_TMCNT_H_E_MASK REG_OS_TM0CNT_H_E_MASK #define REG_OS_TMCNT_H_I_MASK REG_OS_TM0CNT_H_I_MASK #define REG_OS_TMCNT_H_CH_MASK REG_OS_TM1CNT_H_CH_MASK #endif // SDK_ARM9 //---- if OS reserved each timer, bit=1 static u8 i_osTimerReserved[OS_TIMER_NUM]; #ifdef SDK_ARM11 static u8 i_osTimerControl[OS_TIMER_NUM]; #endif // SDK_ARM11 u8 i_osIsTimerReserved(int timerNum); void i_osSetTimerReserved(int timerNum); void i_osUnsetTimerReserved(int timerNum); /*---------------------------------------------------------------------------* Name: osInitTimer Description: Initialize Timers Arguments: None Returns: None *---------------------------------------------------------------------------*/ void osInitTimer( void ) { static BOOL isInit; if ( isInit == FALSE ) { OSIntrMode intr = osDisableInterrupts(); isInit = TRUE; #ifdef SDK_ARM11 osStopTimer(OS_TIMER_0); osStopTimer(OS_TIMER_1); osResetWatchdog(); osDisableWatchdog(); i_osTimerControl[OS_TIMER_0] = 0; i_osTimerControl[OS_TIMER_1] = 0; #else // SDK_ARM9 osStopTimer64(); #endif // SDK_ARM9 osRestoreInterrupts( intr ); } } //================================================================================ /*---------------------------------------------------------------------------* Name: i_osIsTimerReserved Description: check if specified timer is reserved for OS Arguments: timerNum : timerNo (0-3) Returns: non-0 if reserved *---------------------------------------------------------------------------*/ u8 i_osIsTimerReserved( int timer_id ) { return i_osTimerReserved[timer_id]; } /*---------------------------------------------------------------------------* Name: i_osSetTimerReserved Description: set specified timer to reserved for OS Arguments: timerNum : timerNo (0-3) Returns: None. *---------------------------------------------------------------------------*/ void i_osSetTimerReserved( int timer_id ) { i_osTimerReserved[timer_id] = TRUE; } /*---------------------------------------------------------------------------* Name: i_osUnsetTimerReserved Description: unset specified timer to reserved for OS Arguments: timerNum : timerNo (0-3) Returns: None. *---------------------------------------------------------------------------*/ void i_osUnsetTimerReserved( int timer_id ) { i_osTimerReserved[timer_id] = FALSE; } //================================================================================ /*---------------------------------------------------------------------------* Name: osStartTimer Description: set timer(s) and start Arguments: id timerNo count count value to be set to timer preScale preScale Returns: None *---------------------------------------------------------------------------*/ #ifdef SDK_ARM11 // // use 1 timer, 16bit counter, timer interrupt occurs by overflow // void osStartTimer( OSTimer id, OSTimerCount count, OSTimerPrescaler preScale ) { SDK_ASSERT(OS_TIMER_0 <= id && id < OS_TIMER_NUM); SDK_ASSERT(2 <= preScale && preScale <= (256*2)); //---- check if system reserved SDK_ASSERT(!i_osIsTimerReserved(id)); preScale /= 2; if ( preScale ) { preScale--; } osSetTimerCount(id, count); osSetTimerControl(id, REG_OS_TM_CNT_E_MASK | REG_OS_TM_CNT_IT_MASK | i_osTimerControl[id] | (preScale << REG_OS_TM_CNT_PS_SHIFT)); } #else // SDK_ARM9 // // use 1 timer, 16bit counter, timer interrupt occurs by overflow // void osStartTimer( OSTimer id, u16 count, OSTimerPrescaler preScale ) { SDK_ASSERT(OS_TIMER_0 <= id && id < OS_TIMER_NUM); SDK_ASSERT(OS_TIMER_PRESCALER_1 <= preScale && preScale <= OS_TIMER_PRESCALER_1024); //---- check if system reserved SDK_ASSERT(!i_osIsTimerReserved(id)); osSetTimerCount(id, (u16)~count); osSetTimerControl(id, (u16)(REG_OS_TMCNT_H_E_MASK | REG_OS_TMCNT_H_I_MASK | preScale)); } // // use 2 timers, 32bit counter, timer interrupt occurs by overflow // void osStartTimer32( OSTimer32 id, u32 count, OSTimerPrescaler preScale ) { SDK_ASSERT(OS_TIMER32_01 <= id && id <= OS_TIMER32_23); SDK_ASSERT(OS_TIMER_PRESCALER_1 <= preScale && preScale <= OS_TIMER_PRESCALER_1024); //---- check if system reserved SDK_ASSERT(!i_osIsTimerReserved(id)); SDK_ASSERT(!i_osIsTimerReserved(id + 1)); osSetTimerCount((OSTimer)((int)id + 1), (u16)((~count >> 16) & 0xffff)); osSetTimerCount((OSTimer)id, (u16)(~count & 0xffff)); osSetTimerControl((OSTimer)((int)id + 1), REG_OS_TMCNT_H_E_MASK | REG_OS_TMCNT_H_I_MASK | REG_OS_TMCNT_H_CH_MASK); osSetTimerControl((OSTimer)id, (u16)(REG_OS_TMCNT_H_E_MASK | preScale)); } // // use 3 timers, 48bit counter, timer interrupt occurs by overflow // void osStartTimer48( OSTimer48 id, u64 count, OSTimerPrescaler preScale ) { SDK_ASSERT(OS_TIMER48_012 <= id && id <= OS_TIMER48_123); SDK_ASSERT(OS_TIMER_PRESCALER_1 <= preScale && preScale <= OS_TIMER_PRESCALER_1024); //---- check if system reserved SDK_ASSERT(!i_osIsTimerReserved(id)); SDK_ASSERT(!i_osIsTimerReserved(id + 1)); SDK_ASSERT(!i_osIsTimerReserved(id + 2)); osSetTimerCount((OSTimer)((int)id + 2), (u16)((~count >> 32) & 0xffff)); osSetTimerCount((OSTimer)((int)id + 1), (u16)((~count >> 16) & 0xffff)); osSetTimerCount((OSTimer)id, (u16)(~count & 0xffff)); osSetTimerControl((OSTimer)((int)id + 2), REG_OS_TMCNT_H_E_MASK | REG_OS_TMCNT_H_I_MASK | REG_OS_TMCNT_H_CH_MASK); osSetTimerControl((OSTimer)((int)id + 1), REG_OS_TMCNT_H_E_MASK | REG_OS_TMCNT_H_CH_MASK); osSetTimerControl((OSTimer)id, (u16)(REG_OS_TMCNT_H_E_MASK | preScale)); } // // use all 4 timers, 64bit counter, timer3 interrupt occurs by overflow // void osStartTimer64( u64 count, OSTimerPrescaler preScale ) { SDK_ASSERT(OS_TIMER_PRESCALER_1 <= preScale && preScale <= OS_TIMER_PRESCALER_1024); //---- check if system reserved SDK_ASSERT(!i_osIsTimerReserved(OS_TIMER_0)); SDK_ASSERT(!i_osIsTimerReserved(OS_TIMER_1)); SDK_ASSERT(!i_osIsTimerReserved(OS_TIMER_2)); SDK_ASSERT(!i_osIsTimerReserved(OS_TIMER_3)); osSetTimerCount(OS_TIMER_3, (u16)((~count >> 48) & 0xffff)); osSetTimerCount(OS_TIMER_2, (u16)((~count >> 32) & 0xffff)); osSetTimerCount(OS_TIMER_1, (u16)((~count >> 16) & 0xffff)); osSetTimerCount(OS_TIMER_0, (u16)(~count & 0xffff)); osSetTimerControl(OS_TIMER_3, REG_OS_TMCNT_H_E_MASK | REG_OS_TMCNT_H_I_MASK | REG_OS_TMCNT_H_CH_MASK); osSetTimerControl(OS_TIMER_2, REG_OS_TMCNT_H_E_MASK | REG_OS_TMCNT_H_CH_MASK); osSetTimerControl(OS_TIMER_1, REG_OS_TMCNT_H_E_MASK | REG_OS_TMCNT_H_CH_MASK); osSetTimerControl(OS_TIMER_0, (u16)(REG_OS_TMCNT_H_E_MASK | preScale)); } #endif // SDK_ARM9 /*---------------------------------------------------------------------------* Name: i_osStopTimer Description: stop timer(s) Arguments: id timerNo Returns: None *---------------------------------------------------------------------------*/ // // stop a timer // void osStopTimer( OSTimer id ) { SDK_ASSERT(OS_TIMER_0 <= id && id < OS_TIMER_NUM); //---- check if system reserved SDK_ASSERT(!i_osIsTimerReserved(id)); osSetTimerControl(id, 0); #ifdef SDK_ARM11 osClearTimerEventFlag(id); #endif // SDK_ARM11 } #ifdef SDK_ARM9 // // stop 2 timers // void osStopTimer32( OSTimer32 id ) { SDK_ASSERT(OS_TIMER32_01 <= id && id <= OS_TIMER32_23); //---- check if system reserved SDK_ASSERT(!i_osIsTimerReserved(id)); SDK_ASSERT(!i_osIsTimerReserved(id + 1)); osStopTimer((OSTimer)((int)id + 1)); osStopTimer((OSTimer)id); } // // stop 3 timers // void i_osStopTimer48( OSTimer48 id ) { SDK_ASSERT(OS_TIMER48_012 <= id && id <= OS_TIMER48_123); //---- check if system reserved SDK_ASSERT(!i_osIsTimerReserved(id)); SDK_ASSERT(!i_osIsTimerReserved(id + 1)); SDK_ASSERT(!i_osIsTimerReserved(id + 2)); osStopTimer((OSTimer)((int)id + 2)); osStopTimer((OSTimer)((int)id + 1)); osStopTimer((OSTimer)id); } // // stop all 4 timers // void osStopTimer64( void ) { //---- check if system reserved SDK_ASSERT(!i_osIsTimerReserved(OS_TIMER_0)); SDK_ASSERT(!i_osIsTimerReserved(OS_TIMER_1)); SDK_ASSERT(!i_osIsTimerReserved(OS_TIMER_2)); SDK_ASSERT(!i_osIsTimerReserved(OS_TIMER_3)); osStopTimer(OS_TIMER_3); osStopTimer(OS_TIMER_2); osStopTimer(OS_TIMER_1); osStopTimer(OS_TIMER_0); } #endif // SDK_ARM9 #ifdef SDK_ARM11 #include /*---------------------------------------------------------------------------* Name: osGetPerfMonitor Description: Get Performance Monitor Arguments: monitorNum : monitorNo (0-2) Returns: count *---------------------------------------------------------------------------*/ asm u32 osGetPerfMonitor( OSMoniter mon ) { cmp r0, #__cpp(OS_MONITOR_1) beq FSYM(1) cmp r0, #__cpp(OS_MONITOR_2) beq FSYM(2) mrc p15, 0, r0, c15, c12, 1 b FSYM(3) LSYM(1) mrc p15, 0, r0, c15, c12, 2 b FSYM(3) LSYM(2) mrc p15, 0, r0, c15, c12, 3 LSYM(3) bx lr } /*---------------------------------------------------------------------------* Name: osSetPerfMonitor Description: Set Performance Monitor Arguments: monitorNum : monitorNo (0-2) count Returns: previous count *---------------------------------------------------------------------------*/ asm u32 osSetPerfMonitor( OSMoniter mon, u32 count ) { cmp r0, #__cpp(OS_MONITOR_1) beq FSYM(1) cmp r0, #__cpp(OS_MONITOR_2) beq FSYM(2) mrc p15, 0, r0, c15, c12, 1 mcr p15, 0, r1, c15, c12, 1 b FSYM(3) LSYM(1) mrc p15, 0, r0, c15, c12, 1 mcr p15, 0, r1, c15, c12, 1 b FSYM(3) LSYM(2) mrc p15, 0, r0, c15, c12, 1 mcr p15, 0, r1, c15, c12, 1 LSYM(3) bx lr } #include /*---------------------------------------------------------------------------* Name: osIsEnableTimerReload Description: check if specified timer is enabling reload Arguments: timerNum : timerNo (0-1) Returns: non-0 if repeated *---------------------------------------------------------------------------*/ u8 osIsEnableTimerReload( OSTimer timer_id ) { SDK_ASSERT(OS_TIMER_0 <= id && id < OS_TIMER_NUM); return i_osTimerControl[timer_id] & REG_OS_WD_CNT_RLD_MASK ? TRUE : FALSE; } /*---------------------------------------------------------------------------* Name: osEnableTimerReload Description: enable specified timer to reload Arguments: timerNum : timerNo (0-1) Returns: None. *---------------------------------------------------------------------------*/ void osEnableTimerReload( OSTimer timer_id ) { SDK_ASSERT(OS_TIMER_0 <= id && id < OS_TIMER_NUM); OSIntrMode intr = osDisableInterrupts(); i_osTimerControl[timer_id] |= REG_OS_WD_CNT_RLD_MASK; osRestoreInterrupts( intr ); } /*---------------------------------------------------------------------------* Name: osDisableTimerReload Description: disable specified timer to reload Arguments: timerNum : timerNo (0-1) Returns: None. *---------------------------------------------------------------------------*/ void osDisableTimerReload( OSTimer timer_id ) { SDK_ASSERT(OS_TIMER_0 <= id && id < OS_TIMER_NUM); OSIntrMode intr = osDisableInterrupts(); i_osTimerControl[timer_id] &= ~REG_OS_WD_CNT_RLD_MASK; osRestoreInterrupts( intr ); } /*---------------------------------------------------------------------------* Name: osResetWatchdog Description: Reset Watchdog Arguments: None Returns: None *---------------------------------------------------------------------------*/ void osResetWatchdog( void ) { reg_OS_WD_RST = TRUE; } /*---------------------------------------------------------------------------* Name: osDisableWatchdog Description: Disable Watchdog Arguments: None Returns: None *---------------------------------------------------------------------------*/ void osDisableWatchdog( void ) { OSIntrMode intr = osDisableInterrupts(); reg_OS_WD_DIS = OSi_WATCHDOG_DISABLE_CODE_0; reg_OS_WD_DIS = OSi_WATCHDOG_DISABLE_CODE_1; osRestoreInterrupts( intr ); } #endif // SDK_ARM11