/*---------------------------------------------------------------------------* Project: TwlSDK - OS File: os_tick.c Copyright 2003-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:: 2009-06-15#$ $Rev: 10752 $ $Author: terui $ *---------------------------------------------------------------------------*/ #include //---------------------------------------------------------------------- //---- timer control setting for tick #define OSi_TICK_TIMERCONTROL ( REG_OS_TM0CNT_H_E_MASK | REG_OS_TM0CNT_H_I_MASK | OS_TIMER_PRESCALER_64 ) //---- timer number tick uses #define OSi_TICK_TIMER OS_TIMER_0 //---- timer interrupt mask (must be same number with OSi_TICK_TIMER) #define OSi_TICK_IE_TIMER OS_IE_TIMER0 //---- flag for initialization tick static u16 OSi_UseTick = FALSE; //---- tick counter vu64 OSi_TickCounter; //---- flag for need to re-set timer BOOL OSi_NeedResetTimer = FALSE; extern u16 OSi_IsTimerReserved(int timerNum); extern void OSi_SetTimerReserved(int timerNum); static void OSi_CountUpTick(void); u32 OSi_GetTick_noProfile(void); /*---------------------------------------------------------------------------* Name: OS_InitTick Description: initialize 'tick system' Arguments: None Returns: None *---------------------------------------------------------------------------*/ void OS_InitTick(void) { if (!OSi_UseTick) { OSi_UseTick = TRUE; //---- OS reserves OSi_TICK_TIMER timer SDK_ASSERT(!OSi_IsTimerReserved(OSi_TICK_TIMER)); OSi_SetTimerReserved(OSi_TICK_TIMER); //---- setting timer OSi_TickCounter = 0; OS_SetTimerControl(OSi_TICK_TIMER, 0); OS_SetTimerCount((OSTimer)OSi_TICK_TIMER, (u16)0); OS_SetTimerControl(OSi_TICK_TIMER, (u16)OSi_TICK_TIMERCONTROL); //---- set interrupt callback OS_SetIrqFunction(OSi_TICK_IE_TIMER, OSi_CountUpTick); //---- enable timer interrupt (void)OS_EnableIrqMask(OSi_TICK_IE_TIMER); //---- need to reset OSi_NeedResetTimer = FALSE; } } /*---------------------------------------------------------------------------* Name: OS_IsTickAvailable Description: check tick system is available Arguments: None Returns: if available, TRUE. *---------------------------------------------------------------------------*/ BOOL OS_IsTickAvailable(void) { return OSi_UseTick; } /*---------------------------------------------------------------------------* Name: OSi_CountUpTick Description: timer interrupt handle. Arguments: None Returns: None *---------------------------------------------------------------------------*/ static void OSi_CountUpTick(void) { OSi_TickCounter++; //---- setting for timer if (OSi_NeedResetTimer) { OS_SetTimerControl(OSi_TICK_TIMER, 0); OS_SetTimerCount((OSTimer)OSi_TICK_TIMER, (u16)0); OS_SetTimerControl(OSi_TICK_TIMER, (u16)OSi_TICK_TIMERCONTROL); OSi_NeedResetTimer = FALSE; } //---- reset callback OSi_EnterTimerCallback(OSi_TICK_TIMER, (void (*)(void *))OSi_CountUpTick, 0); } #ifdef SDK_ARM7 #ifdef SDK_TWL extern u32 MIC_GetDelayIF(void); #endif #endif /*---------------------------------------------------------------------------* Name: OS_GetTick Description: get tick value Arguments: None Returns: tick value *---------------------------------------------------------------------------*/ OSTick OS_GetTick(void) { vu16 countL; vu64 countH; OSIntrMode prev = OS_DisableInterrupts(); SDK_ASSERT(OSi_UseTick); countL = *(REGType16 *)((u32)REG_TM0CNT_L_ADDR + OSi_TICK_TIMER * 4); countH = OSi_TickCounter & 0xffffffffffffULL; //---- check if timer interrupt bit is on #ifdef SDK_ARM7 #ifdef SDK_TWL if (((reg_OS_IF | MIC_GetDelayIF()) & OSi_TICK_IE_TIMER) && !(countL & 0x8000)) #else if (reg_OS_IF & OSi_TICK_IE_TIMER && !(countL & 0x8000)) #endif #else if (reg_OS_IF & OSi_TICK_IE_TIMER && !(countL & 0x8000)) #endif { countH++; } (void)OS_RestoreInterrupts(prev); return (countH << 16) | countL; } //---- for profiler #pragma profile off u32 OSi_GetTick_noProfile(void) { vu16 countL; vu16 countH; OSIntrMode prev = OS_DisableInterrupts(); SDK_ASSERT(OSi_UseTick); countL = *(REGType16 *)((u32)REG_TM0CNT_L_ADDR + OSi_TICK_TIMER * 4); countH = (u16)OSi_TickCounter; //---- check if timer interrupt bit is on if (reg_OS_IF & OSi_TICK_IE_TIMER && !(countL & 0x8000)) { countH++; } (void)OS_RestoreInterrupts(prev); return (u32)(countH << 16) | countL; } #pragma profile reset /*---------------------------------------------------------------------------* Name: OS_GetTickLo Description: get tick value (only u16 part) Arguments: None Returns: tick value (only u16 part) *---------------------------------------------------------------------------*/ u16 OS_GetTickLo(void) { SDK_ASSERT(OSi_UseTick); return *(REGType16 *)((u32)REG_TM0CNT_L_ADDR + OSi_TICK_TIMER * 4); } /*---------------------------------------------------------------------------* Name: OS_SetTick Description: set tick value Arguments: count value of tick to be set Returns: None *---------------------------------------------------------------------------*/ void OS_SetTick(OSTick count) { OSIntrMode prev; SDK_ASSERT(OSi_UseTick); prev = OS_DisableInterrupts(); reg_OS_IF = OSi_TICK_IE_TIMER; OSi_NeedResetTimer = TRUE; OSi_TickCounter = (u64)(count >> 16); OS_SetTimerControl(OSi_TICK_TIMER, 0); OS_SetTimerCount((OSTimer)OSi_TICK_TIMER, (u16)(count & 0xffff)); OS_SetTimerControl(OSi_TICK_TIMER, (u16)OSi_TICK_TIMERCONTROL); (void)OS_RestoreInterrupts(prev); }