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:: 2008-09-18#$
14   $Rev: 8573 $
15   $Author: okubata_ryoma $
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 /*---------------------------------------------------------------------------*
125   Name:         OS_GetTick
126 
127   Description:  get tick value
128 
129   Arguments:    None
130 
131   Returns:      tick value
132  *---------------------------------------------------------------------------*/
OS_GetTick(void)133 OSTick OS_GetTick(void)
134 {
135     vu16    countL;
136     vu64    countH;
137 
138     OSIntrMode prev = OS_DisableInterrupts();
139     SDK_ASSERT(OSi_UseTick);
140 
141     countL = *(REGType16 *)((u32)REG_TM0CNT_L_ADDR + OSi_TICK_TIMER * 4);
142     countH = OSi_TickCounter & 0xffffffffffffULL;
143 
144     //---- check if timer interrupt bit is on
145     if (reg_OS_IF & OSi_TICK_IE_TIMER && !(countL & 0x8000))
146     {
147         countH++;
148     }
149 
150     (void)OS_RestoreInterrupts(prev);
151 
152     return (countH << 16) | countL;
153 }
154 
155 //---- for profiler
156 #pragma profile off
OSi_GetTick_noProfile(void)157 u32 OSi_GetTick_noProfile(void)
158 {
159     vu16    countL;
160     vu16    countH;
161 
162     OSIntrMode prev = OS_DisableInterrupts();
163     SDK_ASSERT(OSi_UseTick);
164 
165     countL = *(REGType16 *)((u32)REG_TM0CNT_L_ADDR + OSi_TICK_TIMER * 4);
166     countH = (u16)OSi_TickCounter;
167 
168     //---- check if timer interrupt bit is on
169     if (reg_OS_IF & OSi_TICK_IE_TIMER && !(countL & 0x8000))
170     {
171         countH++;
172     }
173 
174     (void)OS_RestoreInterrupts(prev);
175 
176     return (u32)(countH << 16) | countL;
177 }
178 
179 #pragma profile reset
180 
181 /*---------------------------------------------------------------------------*
182   Name:         OS_GetTickLo
183 
184   Description:  get tick value (only u16 part)
185 
186   Arguments:    None
187 
188   Returns:      tick value (only u16 part)
189  *---------------------------------------------------------------------------*/
OS_GetTickLo(void)190 u16 OS_GetTickLo(void)
191 {
192     SDK_ASSERT(OSi_UseTick);
193     return *(REGType16 *)((u32)REG_TM0CNT_L_ADDR + OSi_TICK_TIMER * 4);
194 }
195 
196 /*---------------------------------------------------------------------------*
197   Name:         OS_SetTick
198 
199   Description:  set tick value
200 
201   Arguments:    count     value of tick to be set
202 
203   Returns:      None
204  *---------------------------------------------------------------------------*/
OS_SetTick(OSTick count)205 void OS_SetTick(OSTick count)
206 {
207     OSIntrMode prev;
208 
209     SDK_ASSERT(OSi_UseTick);
210     prev = OS_DisableInterrupts();
211 
212     reg_OS_IF = OSi_TICK_IE_TIMER;
213 
214     OSi_NeedResetTimer = TRUE;
215 
216     OSi_TickCounter = (u64)(count >> 16);
217 
218     OS_SetTimerControl(OSi_TICK_TIMER, 0);
219     OS_SetTimerCount((OSTimer)OSi_TICK_TIMER, (u16)(count & 0xffff));
220     OS_SetTimerControl(OSi_TICK_TIMER, (u16)OSi_TICK_TIMERCONTROL);
221 
222     (void)OS_RestoreInterrupts(prev);
223 }
224