1 /*---------------------------------------------------------------------------*
2 Project: TwlSDK - OS
3 File: os_system.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 #include <nitro/code32.h>
20 #ifdef SDK_TWL
21 #include <twl/scfg/common/scfg.h>
22 #endif
23
24 //============================================================================
25 // CONTROL INTERRUPT
26 //============================================================================
27 #if defined(SDK_TCM_APPLY) && defined(SDK_ARM9)
28 #include <nitro/itcm_begin.h>
29 #endif
30 /*---------------------------------------------------------------------------*
31 Name: OS_EnableInterrupts
32
33 Description: Set CPSR to enable irq interrupts
34
35 Arguments: None.
36
37 Returns: last state of HW_PSR_IRQ_DISABLE
38 *---------------------------------------------------------------------------*/
OS_EnableInterrupts(void)39 asm OSIntrMode OS_EnableInterrupts( void )
40 {
41 mrs r0, cpsr
42 bic r1, r0, #HW_PSR_IRQ_DISABLE
43 msr cpsr_c, r1
44 and r0, r0, #HW_PSR_IRQ_DISABLE
45
46 bx lr
47 }
48
49
50 /*---------------------------------------------------------------------------*
51 Name: OS_DisableInterrupts
52
53 Description: Set CPSR to disable irq interrupts
54
55 Arguments: None.
56
57 Returns: last state of HW_PSR_IRQ_DISABLE
58 *---------------------------------------------------------------------------*/
OS_DisableInterrupts(void)59 asm OSIntrMode OS_DisableInterrupts( void )
60 {
61 mrs r0, cpsr
62 orr r1, r0, #HW_PSR_IRQ_DISABLE
63 msr cpsr_c, r1
64 and r0, r0, #HW_PSR_IRQ_DISABLE
65
66 bx lr
67 }
68
69
70 /*---------------------------------------------------------------------------*
71 Name: OS_RestoreInterrupts
72
73 Description: Restore CPSR irq interrupt
74
75 Arguments: state of irq interrupt bit
76
77 Returns: last state of HW_PSR_IRQ_DISABLE
78 *---------------------------------------------------------------------------*/
OS_RestoreInterrupts(register OSIntrMode state)79 asm OSIntrMode OS_RestoreInterrupts( register OSIntrMode state )
80 {
81 mrs r1, cpsr
82 bic r2, r1, #HW_PSR_IRQ_DISABLE
83 orr r2, r2, r0
84 msr cpsr_c, r2
85 and r0, r1, #HW_PSR_IRQ_DISABLE
86
87 bx lr
88 }
89 #if defined(SDK_TCM_APPLY) && defined(SDK_ARM9)
90 #include <nitro/itcm_end.h>
91 #endif
92
93
94 /*---------------------------------------------------------------------------*
95 Name: OS_EnableInterrupts_IrqAndFiq
96
97 Description: Set CPSR to enable irq and fiq interrupts
98
99 Arguments: None.
100
101 Returns: last state of HW_PSR_IRQ_DISABLE & HW_PSR_FIQ_DISABLE
102 *---------------------------------------------------------------------------*/
OS_EnableInterrupts_IrqAndFiq(void)103 asm OSIntrMode OS_EnableInterrupts_IrqAndFiq( void )
104 {
105 mrs r0, cpsr
106 bic r1, r0, #HW_PSR_IRQ_FIQ_DISABLE
107 msr cpsr_c, r1
108 and r0, r0, #HW_PSR_IRQ_FIQ_DISABLE
109
110 bx lr
111 }
112
113
114 /*---------------------------------------------------------------------------*
115 Name: OS_DisableInterrupts_IrqAndFiq
116
117 Description: Set CPSR to disable irq and fiq interrupts
118
119 Arguments: None.
120
121 Returns: last state of HW_PSR_IRQ_DISABLE & HW_PSR_FIQ_DISABLE
122 *---------------------------------------------------------------------------*/
OS_DisableInterrupts_IrqAndFiq(void)123 asm OSIntrMode OS_DisableInterrupts_IrqAndFiq( void )
124 {
125 mrs r0, cpsr
126 orr r1, r0, #HW_PSR_IRQ_FIQ_DISABLE
127 msr cpsr_c, r1
128 and r0, r0, #HW_PSR_IRQ_FIQ_DISABLE
129
130 bx lr
131 }
132
133
134 /*---------------------------------------------------------------------------*
135 Name: OS_RestoreInterrupts_IrqAndFiq
136
137 Description: Restore CPSR irq and fiq interrupt
138
139 Arguments: state of irq and fiq interrupt bit
140
141 Returns: last state of HW_PSR_IRQ_DISABLE & HW_PSR_FIQ_DISABLE
142 *---------------------------------------------------------------------------*/
OS_RestoreInterrupts_IrqAndFiq(register OSIntrMode state)143 asm OSIntrMode OS_RestoreInterrupts_IrqAndFiq( register OSIntrMode state )
144 {
145 mrs r1, cpsr
146 bic r2, r1, #HW_PSR_IRQ_FIQ_DISABLE
147 orr r2, r2, r0
148 msr cpsr_c, r2
149 and r0, r1, #HW_PSR_IRQ_FIQ_DISABLE
150
151 bx lr
152 }
153
154
155 /*---------------------------------------------------------------------------*
156 Name: OS_GetCpsrIrq
157
158 Description: Get current state of CPSR irq interrupt
159
160 Arguments: None
161
162 Returns: last state of HW_PSR_IRQ_DISABLE
163 *---------------------------------------------------------------------------*/
OS_GetCpsrIrq(void)164 asm OSIntrMode_Irq OS_GetCpsrIrq( void )
165 {
166 mrs r0, cpsr
167 and r0, r0, #HW_PSR_IRQ_DISABLE
168
169 bx lr
170 }
171
172
173 //============================================================================
174 // PROCESSER MODE
175 //============================================================================
176 #if defined(SDK_TCM_APPLY) && defined(SDK_ARM9)
177 #include <nitro/itcm_begin.h>
178 #endif
179 /*---------------------------------------------------------------------------*
180 Name: OS_GetProcMode
181
182 Description: Get processor mode from CPSR
183
184 Arguments: None.
185
186 Returns: CPU processor mode (field 0x10-0x1f)
187 *---------------------------------------------------------------------------*/
OS_GetProcMode(void)188 asm OSProcMode OS_GetProcMode( void )
189 {
190 mrs r0, cpsr
191 and r0, r0, #HW_PSR_CPU_MODE_MASK
192
193 bx lr
194 }
195 #if defined(SDK_TCM_APPLY) && defined(SDK_ARM9)
196 #include <nitro/itcm_end.h>
197 #endif
198
199 #include <nitro/codereset.h>
200
201
202 //============================================================================
203 // WAIT
204 //============================================================================
205 /*---------------------------------------------------------------------------*
206 Name: OS_SpinWaitCpuCycles
207
208 Description: Spin and Wait for specified CPU cycles at least
209
210 Arguments: cycles waiting CPU cycle
211
212 Returns: None
213 *---------------------------------------------------------------------------*/
214 #ifdef SDK_ARM9
215 #include <nitro/code32.h>
OS_SpinWaitCpuCycles(u32 cycle)216 asm void OS_SpinWaitCpuCycles( u32 cycle )
217 {
218 _1: subs r0, r0, #4 // 3 cycle
219 bcs _1 // 1 cycle
220 bx lr
221 }
222 #include <nitro/codereset.h>
223 #else
OS_SpinWaitCpuCycles(u32 cycle)224 void OS_SpinWaitCpuCycles(u32 cycle)
225 {
226 SVC_WaitByLoop((s32)cycle / 4);
227 }
228 #endif
229
230 /*---------------------------------------------------------------------------*
231 Name: OS_SpinWaitSysCycles
232
233 Description: Spin and Wait for specified SYSTEM cycles at least
234
235 Arguments: cycles waiting SYSTEM cycle
236
237 Returns: None
238 *---------------------------------------------------------------------------*/
239 #ifdef SDK_ARM9
OS_SpinWaitSysCycles(u32 cycle)240 void OS_SpinWaitSysCycles( u32 cycle )
241 {
242 #ifdef SDK_TWL
243 cycle <<= (SCFG_GetCpuSpeed()==SCFG_CPU_SPEED_2X)? 2: 1;
244 #else
245 cycle <<= 1;
246 #endif
247
248 if (cycle > 16)
249 {
250 OS_SpinWaitCpuCycles(cycle - 16);
251 }
252 }
253 #else
OS_SpinWaitSysCycles(u32 cycle)254 void OS_SpinWaitSysCycles(u32 cycle)
255 {
256 SVC_WaitByLoop((s32)cycle / 4);
257 }
258 #endif
259
260
261 /*---------------------------------------------------------------------------*
262 Name: OS_WaitInterrupt
263
264 Description: wait specifiled interrupt.
265 the difference between OS_WaitIrq and OS_WaitInterrupt is:
266 in waiting interrupt
267 OS_WaitIrq does switch thread,
268 OS_WaitInterrupt doesn't switch thread.
269 OS_WaitIrq wait by using OS_SleepThread() with threadQueue,
270 OS_WaitInterrupt wait by using OS_Halt().
271 if SDK_NO_THREAD defined, 2 functions become same.
272
273 Arguments: clear TRUE if want to clear interrupt flag before wait.
274 FALSE if not.
275 irqFlags bit of interrupts to wait for
276
277 Returns: None
278 *---------------------------------------------------------------------------*/
OS_WaitInterrupt(BOOL clear,OSIrqMask irqFlags)279 void OS_WaitInterrupt(BOOL clear, OSIrqMask irqFlags)
280 {
281 OSIntrMode cpsrIrq = OS_DisableInterrupts();
282 BOOL ime = OS_EnableIrq();
283
284 if (clear)
285 {
286 (void)OS_ClearIrqCheckFlag(irqFlags);
287 }
288
289 while (!(OS_GetIrqCheckFlag() & irqFlags))
290 {
291 OS_Halt();
292 (void)OS_EnableInterrupts();
293 (void)OS_DisableInterrupts();
294 }
295
296 (void)OS_ClearIrqCheckFlag(irqFlags);
297 (void)OS_RestoreIrq(ime);
298 (void)OS_RestoreInterrupts(cpsrIrq);
299 }
300
301 /*---------------------------------------------------------------------------*
302 Name: OS_WaitVBlankIntr
303
304 Description: wait till vblank interrupt occurred.
305 the difference between SVC_WaitVBlankIntr and OS_WaitVBlankIntr is:
306 OS_WaitVBlankIntr does switch thread,
307 SVC_WaitVBlankIntr doesn't switch thread.
308
309 Arguments: None
310
311 Returns: None
312 *---------------------------------------------------------------------------*/
OS_WaitVBlankIntr(void)313 void OS_WaitVBlankIntr(void)
314 {
315 SVC_WaitByLoop(1);
316 #if defined(SDK_ENABLE_ARM7_PRINT) && defined(SDK_ARM9)
317 // PrintServer for ARM7 (if specified)
318 OS_PrintServer();
319 #endif
320 OS_WaitIrq(TRUE, OS_IE_V_BLANK);
321 }
322
323