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