1 /*---------------------------------------------------------------------------*
2   Project:  TwlSDK - OS
3   File:     os_tick.c
4 
5   Copyright 2003-2008 Nintendo.  All rights reserved.
6 
7   These coded instructions, statements, and computer programs contain
8   proprietary information of Nintendo of America Inc. and/or Nintendo
9   Company Ltd., and are protected by Federal copyright law.  They may
10   not be disclosed to third parties or copied or duplicated in any form,
11   in whole or in part, without the prior written consent of Nintendo.
12 
13   $Date:: 2009-06-15#$
14   $Rev: 10752 $
15   $Author: terui $
16  *---------------------------------------------------------------------------*/
17 #include <nitro/os.h>
18 
19 //----------------------------------------------------------------------
20 //---- timer control setting for tick
21 #define OSi_TICK_TIMERCONTROL  ( REG_OS_TM0CNT_H_E_MASK | REG_OS_TM0CNT_H_I_MASK | OS_TIMER_PRESCALER_64 )
22 
23 //---- timer number tick uses
24 #define OSi_TICK_TIMER         OS_TIMER_0
25 
26 //---- timer interrupt mask (must be same number with OSi_TICK_TIMER)
27 #define OSi_TICK_IE_TIMER      OS_IE_TIMER0
28 
29 //---- flag for initialization tick
30 static u16 OSi_UseTick = FALSE;
31 
32 //---- tick counter
33 vu64    OSi_TickCounter;
34 
35 //---- flag for need to re-set timer
36 BOOL    OSi_NeedResetTimer = FALSE;
37 
38 
39 extern u16 OSi_IsTimerReserved(int timerNum);
40 extern void OSi_SetTimerReserved(int timerNum);
41 
42 static void OSi_CountUpTick(void);
43 u32     OSi_GetTick_noProfile(void);
44 
45 
46 /*---------------------------------------------------------------------------*
47   Name:         OS_InitTick
48 
49   Description:  initialize 'tick system'
50 
51   Arguments:    None
52 
53   Returns:      None
54  *---------------------------------------------------------------------------*/
OS_InitTick(void)55 void OS_InitTick(void)
56 {
57     if (!OSi_UseTick)
58     {
59         OSi_UseTick = TRUE;
60 
61         //---- OS reserves OSi_TICK_TIMER timer
62         SDK_ASSERT(!OSi_IsTimerReserved(OSi_TICK_TIMER));
63         OSi_SetTimerReserved(OSi_TICK_TIMER);
64 
65         //---- setting timer
66         OSi_TickCounter = 0;
67         OS_SetTimerControl(OSi_TICK_TIMER, 0);
68         OS_SetTimerCount((OSTimer)OSi_TICK_TIMER, (u16)0);
69         OS_SetTimerControl(OSi_TICK_TIMER, (u16)OSi_TICK_TIMERCONTROL);
70 
71         //---- set interrupt callback
72         OS_SetIrqFunction(OSi_TICK_IE_TIMER, OSi_CountUpTick);
73 
74         //---- enable timer interrupt
75         (void)OS_EnableIrqMask(OSi_TICK_IE_TIMER);
76 
77         //---- need to reset
78         OSi_NeedResetTimer = FALSE;
79     }
80 }
81 
82 /*---------------------------------------------------------------------------*
83   Name:         OS_IsTickAvailable
84 
85   Description:  check tick system is available
86 
87   Arguments:    None
88 
89   Returns:      if available, TRUE.
90  *---------------------------------------------------------------------------*/
OS_IsTickAvailable(void)91 BOOL OS_IsTickAvailable(void)
92 {
93     return OSi_UseTick;
94 }
95 
96 
97 /*---------------------------------------------------------------------------*
98   Name:         OSi_CountUpTick
99 
100   Description:  timer interrupt handle.
101 
102   Arguments:    None
103 
104   Returns:      None
105  *---------------------------------------------------------------------------*/
OSi_CountUpTick(void)106 static void OSi_CountUpTick(void)
107 {
108     OSi_TickCounter++;
109 
110     //---- setting for timer
111     if (OSi_NeedResetTimer)
112     {
113         OS_SetTimerControl(OSi_TICK_TIMER, 0);
114         OS_SetTimerCount((OSTimer)OSi_TICK_TIMER, (u16)0);
115         OS_SetTimerControl(OSi_TICK_TIMER, (u16)OSi_TICK_TIMERCONTROL);
116 
117         OSi_NeedResetTimer = FALSE;
118     }
119 
120     //---- reset callback
121     OSi_EnterTimerCallback(OSi_TICK_TIMER, (void (*)(void *))OSi_CountUpTick, 0);
122 }
123 
124 #ifdef SDK_ARM7
125 #ifdef SDK_TWL
126 extern u32 MIC_GetDelayIF(void);
127 #endif
128 #endif
129 /*---------------------------------------------------------------------------*
130   Name:         OS_GetTick
131 
132   Description:  get tick value
133 
134   Arguments:    None
135 
136   Returns:      tick value
137  *---------------------------------------------------------------------------*/
OS_GetTick(void)138 OSTick OS_GetTick(void)
139 {
140     vu16    countL;
141     vu64    countH;
142 
143     OSIntrMode prev = OS_DisableInterrupts();
144     SDK_ASSERT(OSi_UseTick);
145 
146     countL = *(REGType16 *)((u32)REG_TM0CNT_L_ADDR + OSi_TICK_TIMER * 4);
147     countH = OSi_TickCounter & 0xffffffffffffULL;
148 
149     //---- check if timer interrupt bit is on
150 #ifdef SDK_ARM7
151 #ifdef SDK_TWL
152     if (((reg_OS_IF | MIC_GetDelayIF()) & OSi_TICK_IE_TIMER) && !(countL & 0x8000))
153 #else
154     if (reg_OS_IF & OSi_TICK_IE_TIMER && !(countL & 0x8000))
155 #endif
156 #else
157     if (reg_OS_IF & OSi_TICK_IE_TIMER && !(countL & 0x8000))
158 #endif
159     {
160         countH++;
161     }
162 
163     (void)OS_RestoreInterrupts(prev);
164 
165     return (countH << 16) | countL;
166 }
167 
168 //---- for profiler
169 #pragma profile off
OSi_GetTick_noProfile(void)170 u32 OSi_GetTick_noProfile(void)
171 {
172     vu16    countL;
173     vu16    countH;
174 
175     OSIntrMode prev = OS_DisableInterrupts();
176     SDK_ASSERT(OSi_UseTick);
177 
178     countL = *(REGType16 *)((u32)REG_TM0CNT_L_ADDR + OSi_TICK_TIMER * 4);
179     countH = (u16)OSi_TickCounter;
180 
181     //---- check if timer interrupt bit is on
182     if (reg_OS_IF & OSi_TICK_IE_TIMER && !(countL & 0x8000))
183     {
184         countH++;
185     }
186 
187     (void)OS_RestoreInterrupts(prev);
188 
189     return (u32)(countH << 16) | countL;
190 }
191 
192 #pragma profile reset
193 
194 /*---------------------------------------------------------------------------*
195   Name:         OS_GetTickLo
196 
197   Description:  get tick value (only u16 part)
198 
199   Arguments:    None
200 
201   Returns:      tick value (only u16 part)
202  *---------------------------------------------------------------------------*/
OS_GetTickLo(void)203 u16 OS_GetTickLo(void)
204 {
205     SDK_ASSERT(OSi_UseTick);
206     return *(REGType16 *)((u32)REG_TM0CNT_L_ADDR + OSi_TICK_TIMER * 4);
207 }
208 
209 /*---------------------------------------------------------------------------*
210   Name:         OS_SetTick
211 
212   Description:  set tick value
213 
214   Arguments:    count     value of tick to be set
215 
216   Returns:      None
217  *---------------------------------------------------------------------------*/
OS_SetTick(OSTick count)218 void OS_SetTick(OSTick count)
219 {
220     OSIntrMode prev;
221 
222     SDK_ASSERT(OSi_UseTick);
223     prev = OS_DisableInterrupts();
224 
225     reg_OS_IF = OSi_TICK_IE_TIMER;
226 
227     OSi_NeedResetTimer = TRUE;
228 
229     OSi_TickCounter = (u64)(count >> 16);
230 
231     OS_SetTimerControl(OSi_TICK_TIMER, 0);
232     OS_SetTimerCount((OSTimer)OSi_TICK_TIMER, (u16)(count & 0xffff));
233     OS_SetTimerControl(OSi_TICK_TIMER, (u16)OSi_TICK_TIMERCONTROL);
234 
235     (void)OS_RestoreInterrupts(prev);
236 }
237