1 /*---------------------------------------------------------------------------*
2   Project:  TwlSDK - OS
3   File:     os_timer.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-17#$
14   $Rev: 8556 $
15   $Author: okubata_ryoma $
16 
17  *---------------------------------------------------------------------------*/
18 #include <nitro/os.h>
19 
20 
21 //----------------------------------------------------------------------
22 #define OSi_TM_E_MASK      REG_OS_TM0CNT_H_E_MASK
23 #define OSi_TM_I_MASK      REG_OS_TM0CNT_H_I_MASK
24 #define OSi_TM_CH_MASK     REG_OS_TM1CNT_H_CH_MASK
25 
26 #define OSi_TIMER_MASK(preScale)   ((u16)(OSi_TM_E_MASK | OSi_TM_I_MASK | (preScale)))
27 #define OSi_CASCADE_MASK           ((u16)(OSi_TM_E_MASK | OSi_TM_I_MASK | OSi_TM_CH_MASK))
28 
29 //---- if OS reserved each timer, bit=1 (LSB is TIMER0)
30 static u16 OSi_TimerReserved = 0;
31 
32 u16     OSi_IsTimerReserved(int timerNum);
33 void    OSi_SetTimerReserved(int timerNum);
34 void    OSi_UnsetTimerReserved(int timerNum);
35 
36 static void OS_StopTimerAndUnsetHandler(OSTimer id);
37 static void OSi_TimerIntr0(void);
38 static void OSi_TimerIntr1(void);
39 static void OSi_TimerIntr2(void);
40 
41 static void (*OSi_IntrTable[])(void) = { OSi_TimerIntr0, OSi_TimerIntr1, OSi_TimerIntr2 };
42 static OSIrqMask OSi_MaskTable[] = { OS_IE_TIMER0, OS_IE_TIMER1, OS_IE_TIMER2 };
43 
44 //================================================================================
45 /*---------------------------------------------------------------------------*
46   Name:         OSi_IsTimerReserved
47 
48   Description:  check if specified timer is reserved for OS
49 
50   Arguments:    timerNum : timerNo (0-3)
51 
52   Returns:      non-0 if reserved
53  *---------------------------------------------------------------------------*/
OSi_IsTimerReserved(int timerNum)54 u16 OSi_IsTimerReserved(int timerNum)
55 {
56     return (u16)(OSi_TimerReserved & (1 << timerNum));
57 }
58 
59 /*---------------------------------------------------------------------------*
60   Name:         OSi_SetTimerReserved
61 
62   Description:  set specified timer to reserved for OS
63 
64   Arguments:    timerNum : timerNo (0-3)
65 
66   Returns:      None.
67  *---------------------------------------------------------------------------*/
OSi_SetTimerReserved(int timerNum)68 void OSi_SetTimerReserved(int timerNum)
69 {
70     OSi_TimerReserved |= (1 << timerNum);
71 }
72 
73 /*---------------------------------------------------------------------------*
74   Name:         OSi_UnsetTimerReserved
75 
76   Description:  unset specified timer to reserved for OS
77 
78   Arguments:    timerNum : timerNo (0-3)
79 
80   Returns:      None.
81  *---------------------------------------------------------------------------*/
OSi_UnsetTimerReserved(int timerNum)82 void OSi_UnsetTimerReserved(int timerNum)
83 {
84     OSi_TimerReserved &= ~(1 << timerNum);
85 }
86 
87 //================================================================================
88 /*---------------------------------------------------------------------------*
89   Name:         OS_StartTimer / OS_StartTimer32 / OS_StartTimer48 /OS_StartTimer64
90 
91   Description:  set timer(s) and start
92 
93   Arguments:    id         timerNo
94                 count      count value to be set to timer
95                 preScale   preScale
96 
97   Returns:      None
98  *---------------------------------------------------------------------------*/
99 //   use 1 timer, 16bit counter,  timer<id> interrupt occurs by overflow
100 //
OS_StartTimer(OSTimer id,u16 count,OSTimerPrescaler preScale)101 void OS_StartTimer(OSTimer id, u16 count, OSTimerPrescaler preScale)
102 {
103     SDK_ASSERT(OS_TIMER_0 <= id && id <= OS_TIMER_3);
104     SDK_ASSERT(OS_TIMER_PRESCALER_1 <= preScale && preScale <= OS_TIMER_PRESCALER_1024);
105     //---- check if system reserved
106     SDK_ASSERT(!OSi_IsTimerReserved(id));
107 
108 	//---- set a count register
109     OS_SetTimerCount(id, (u16)~count);
110 
111 	//---- set a control register
112     OS_SetTimerControl(id, OSi_TIMER_MASK(preScale));
113 }
114 //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
115 //   use 2 timers, 32bit counter, timer<id+1> interrupt occurs by overflow
116 //
OS_StartTimer32(OSTimer32 id,u32 count,OSTimerPrescaler preScale)117 void OS_StartTimer32(OSTimer32 id, u32 count, OSTimerPrescaler preScale)
118 {
119     SDK_ASSERT(OS_TIMER32_01 <= id && id <= OS_TIMER32_23);
120     SDK_ASSERT(OS_TIMER_PRESCALER_1 <= preScale && preScale <= OS_TIMER_PRESCALER_1024);
121     //---- check if system reserved
122     SDK_ASSERT(!OSi_IsTimerReserved(id));
123     SDK_ASSERT(!OSi_IsTimerReserved(id + 1));
124 
125 	//---- set count registers
126     OS_SetTimerCount((OSTimer)((int)id + 1), (u16)((~count >> 16) & 0xffff));
127     OS_SetTimerCount((OSTimer)id, (u16)(~count & 0xffff));
128 
129 	//---- set a timer interrupt handler
130     OS_SetIrqFunction(OSi_MaskTable[(int)id], OSi_IntrTable[(int)id]);
131 
132 	//---- set control registers
133     OS_SetTimerControl((OSTimer)((int)id + 1), OSi_CASCADE_MASK );
134     OS_SetTimerControl((OSTimer)id, OSi_TIMER_MASK(preScale));
135 }
136 //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
137 //   use 3 timers, 48bit counter, timer<id+2> interrupt occurs by overflow
138 //
OS_StartTimer48(OSTimer48 id,u64 count,OSTimerPrescaler preScale)139 void OS_StartTimer48(OSTimer48 id, u64 count, OSTimerPrescaler preScale)
140 {
141     SDK_ASSERT(OS_TIMER48_012 <= id && id <= OS_TIMER48_123);
142     SDK_ASSERT(OS_TIMER_PRESCALER_1 <= preScale && preScale <= OS_TIMER_PRESCALER_1024);
143     //---- check if system reserved
144     SDK_ASSERT(!OSi_IsTimerReserved(id));
145     SDK_ASSERT(!OSi_IsTimerReserved(id + 1));
146     SDK_ASSERT(!OSi_IsTimerReserved(id + 2));
147 
148 	//---- set count registers
149     OS_SetTimerCount((OSTimer)((int)id + 2), (u16)((~count >> 32) & 0xffff));
150     OS_SetTimerCount((OSTimer)((int)id + 1), (u16)((~count >> 16) & 0xffff));
151     OS_SetTimerCount((OSTimer)id, (u16)(~count & 0xffff));
152 
153 	//---- set timer interrupt handlers
154     OS_SetIrqFunction(OSi_MaskTable[(int)id+1], OSi_IntrTable[(int)id+1]);
155     OS_SetIrqFunction(OSi_MaskTable[(int)id], OSi_IntrTable[(int)id]);
156 
157 	//---- set control registers
158     OS_SetTimerControl((OSTimer)((int)id + 2), OSi_CASCADE_MASK );
159     OS_SetTimerControl((OSTimer)((int)id + 1), OSi_CASCADE_MASK );
160     OS_SetTimerControl((OSTimer)id, OSi_TIMER_MASK(preScale));
161 }
162 //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
163 //   use all 4 timers, 64bit counter, timer3 interrupt occurs by overflow
164 //
OS_StartTimer64(u64 count,OSTimerPrescaler preScale)165 void OS_StartTimer64(u64 count, OSTimerPrescaler preScale)
166 {
167     SDK_ASSERT(OS_TIMER_PRESCALER_1 <= preScale && preScale <= OS_TIMER_PRESCALER_1024);
168     //---- check if system reserved
169     SDK_ASSERT(!OSi_IsTimerReserved(OS_TIMER_0));
170     SDK_ASSERT(!OSi_IsTimerReserved(OS_TIMER_1));
171     SDK_ASSERT(!OSi_IsTimerReserved(OS_TIMER_2));
172     SDK_ASSERT(!OSi_IsTimerReserved(OS_TIMER_3));
173 
174 	//---- set count registers
175     OS_SetTimerCount(OS_TIMER_3, (u16)((~count >> 48) & 0xffff));
176     OS_SetTimerCount(OS_TIMER_2, (u16)((~count >> 32) & 0xffff));
177     OS_SetTimerCount(OS_TIMER_1, (u16)((~count >> 16) & 0xffff));
178     OS_SetTimerCount(OS_TIMER_0, (u16)(~count & 0xffff));
179 
180 	//---- set timer interrupt handlers
181     OS_SetIrqFunction(OS_IE_TIMER2, OSi_TimerIntr2);
182     OS_SetIrqFunction(OS_IE_TIMER1, OSi_TimerIntr1);
183 	OS_SetIrqFunction(OS_IE_TIMER0, OSi_TimerIntr0);
184 
185 	//---- set control registers
186     OS_SetTimerControl(OS_TIMER_3, OSi_CASCADE_MASK );
187     OS_SetTimerControl(OS_TIMER_2, OSi_CASCADE_MASK );
188     OS_SetTimerControl(OS_TIMER_1, OSi_CASCADE_MASK );
189     OS_SetTimerControl(OS_TIMER_0, OSi_TIMER_MASK(preScale));
190 }
191 
192 /*---------------------------------------------------------------------------*
193   Name:         OS_StopTimer / OS_StopTimer32 / OS_StopTimer48 / OS_StopTimer64
194 
195   Description:  stop timer(s)
196 
197   Arguments:    id         timerNo
198 
199   Returns:      None
200  *---------------------------------------------------------------------------*/
201 //  stop a timer
202 //
OS_StopTimer(OSTimer id)203 void OS_StopTimer(OSTimer id)
204 {
205     SDK_ASSERT(OS_TIMER_0 <= id && id <= OS_TIMER_3);
206     //---- check if system reserved
207     SDK_ASSERT(!OSi_IsTimerReserved(id));
208 
209     OS_SetTimerControl(id, 0);
210 }
211 
OS_StopTimerAndUnsetHandler(OSTimer id)212 static void OS_StopTimerAndUnsetHandler(OSTimer id)
213 {
214     OS_SetIrqFunction(OSi_MaskTable[(int)id], NULL);
215 	OS_StopTimer(id);
216 }
217 //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
218 //  stop 2 timers
219 //
OS_StopTimer32(OSTimer32 id)220 void OS_StopTimer32(OSTimer32 id)
221 {
222     SDK_ASSERT(OS_TIMER32_01 <= id && id <= OS_TIMER32_23);
223     //---- check if system reserved
224     SDK_ASSERT(!OSi_IsTimerReserved(id));
225     SDK_ASSERT(!OSi_IsTimerReserved(id + 1));
226 
227 	//---- clear timer setting
228     OS_StopTimerAndUnsetHandler((OSTimer)id);
229     OS_StopTimer((OSTimer)((int)id + 1));
230 }
231 //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
232 //  stop 3 timers
233 //
OS_StopTimer48(OSTimer48 id)234 void OS_StopTimer48(OSTimer48 id)
235 {
236     SDK_ASSERT(OS_TIMER48_012 <= id && id <= OS_TIMER48_123);
237     //---- check if system reserved
238     SDK_ASSERT(!OSi_IsTimerReserved(id));
239     SDK_ASSERT(!OSi_IsTimerReserved(id + 1));
240     SDK_ASSERT(!OSi_IsTimerReserved(id + 2));
241 
242 	//---- clear timer setting
243     OS_StopTimerAndUnsetHandler((OSTimer)id);
244     OS_StopTimerAndUnsetHandler((OSTimer)((int)id + 1));
245     OS_StopTimer((OSTimer)((int)id + 2));
246 }
247 //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
248 //  stop all 4 timers
249 //
OS_StopTimer64(void)250 void OS_StopTimer64(void)
251 {
252     //---- check if system reserved
253     SDK_ASSERT(!OSi_IsTimerReserved(OS_TIMER_0));
254     SDK_ASSERT(!OSi_IsTimerReserved(OS_TIMER_1));
255     SDK_ASSERT(!OSi_IsTimerReserved(OS_TIMER_2));
256     SDK_ASSERT(!OSi_IsTimerReserved(OS_TIMER_3));
257 
258 	//---- clear timer setting
259     OS_StopTimerAndUnsetHandler(OS_TIMER_0);
260     OS_StopTimerAndUnsetHandler(OS_TIMER_1);
261     OS_StopTimerAndUnsetHandler(OS_TIMER_2);
262     OS_StopTimer(OS_TIMER_3);
263 }
264 
265 /*---------------------------------------------------------------------------*
266   Name:         OSi_TimerIntr0 / OSi_TimerIntr1 / OSi_TimerIntr2
267 
268   Description:  timer 0/1/2 interrupt handler
269 
270   Arguments:    None
271 
272   Returns:      None
273  *---------------------------------------------------------------------------*/
OSi_TimerIntr0()274 static void OSi_TimerIntr0()
275 {
276     OS_SetTimerCount( OS_TIMER_0, 0 );
277 }
278 //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
OSi_TimerIntr1()279 static void OSi_TimerIntr1()
280 {
281     OS_SetTimerCount( OS_TIMER_1, 0 );
282 }
283 //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
OSi_TimerIntr2()284 static void OSi_TimerIntr2()
285 {
286     OS_SetTimerCount( OS_TIMER_2, 0 );
287 }
288