1 /*---------------------------------------------------------------------------*
2 Project: TwlSDK - ThreadSafeTest - CP
3 File: main.c
4
5 Copyright 2007 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-02-06#$
14 $Rev: 9986 $
15 $Author: yosizaki $
16 *---------------------------------------------------------------------------*/
17
18 //---------------------------------------------------------------------------
19 // Thread-safe test for divider and square root arithmetic unit
20 // HOWTO:
21 // 1. The state of the divider and square root unit are switched when a thread is switched, so it is thread-safe without any special processing.
22 //
23 //
24 // 2. By calling the CP_SaveContext and CP_RestoreContext functions in an interrupt before and after (respectively) using the divider and square root unit, you can restore the state of these two units and use them safely.
25 //
26 //
27 //---------------------------------------------------------------------------
28
29 #include <nitro.h>
30
31
32 /*---------------------------------------------------------------------------*
33 Prototype Declarations
34 *---------------------------------------------------------------------------*/
35 static void VBlankIntr(void);
36 void proc1(void *arg);
37 void proc2(void *arg);
38
39
40 /*---------------------------------------------------------------------------*
41 Constant Definitions
42 *---------------------------------------------------------------------------*/
43 #define A1 0x40F337
44 #define B1 0x197
45 #define A2 0x7843276F4561
46 #define B2 0x3208F1
47
48
49 #define THREAD1_PRIO 10
50 #define THREAD2_PRIO 11
51
52 #define STACK_SIZE 1024
53
54
55 /*---------------------------------------------------------------------------*
56 Internal Variable Definitions
57 *---------------------------------------------------------------------------*/
58 u64 stack1[STACK_SIZE / sizeof(u64)];
59 u64 stack2[STACK_SIZE / sizeof(u64)];
60
61 OSThread thread1;
62 OSThread thread2;
63
64
65 //---------------------------------------------------------------------------
66 // Main Loop
67 //---------------------------------------------------------------------------
NitroMain(void)68 void NitroMain(void)
69 {
70 u64 a;
71 u32 b;
72 u64 c;
73
74 //---------------------------------------------------------------------------
75 // Initialization
76 //---------------------------------------------------------------------------
77 OS_Init();
78 OS_InitThread();
79 FX_Init();
80
81 GX_Init();
82 GX_SetPower(GX_POWER_ALL);
83
84 GX_DispOn();
85
86 OS_SetIrqFunction(OS_IE_V_BLANK, VBlankIntr);
87 (void)OS_EnableIrqMask(OS_IE_V_BLANK);
88 (void)OS_EnableIrq();
89
90 reg_GX_DISPSTAT = 8;
91
92
93 OS_Printf("Correct Answer: %x / %x = %x\n", A1, B1, A1 / B1);
94 OS_Printf("Correct Answer: %llx / %x = %llx\n\n", A2, B2, A2 / B2);
95
96 a = A2;
97 b = B2;
98
99
100 // Wait for V-Blank in the middle of calculation
101 CP_SetDiv64_32(a, b);
102 OS_Printf("Main: Start %llx / %x ...\n", a, b);
103
104 CP_WaitDiv();
105 OS_WaitVBlankIntr(); // Waiting for the end of the V-Blank interrupt
106
107 c = (u64)CP_GetDivResult64();
108
109 OS_Printf("Main: Get %llx / %x = %llx\n", a, b, c);
110
111
112 // Start thread
113 OS_Printf("----------------------------\n");
114 OS_Printf("Create Thread\n");
115
116 OS_CreateThread(&thread1, proc1, (void *)0x111, stack1 + STACK_SIZE / sizeof(u64), STACK_SIZE,
117 THREAD1_PRIO);
118 OS_CreateThread(&thread2, proc2, (void *)0x222, stack2 + STACK_SIZE / sizeof(u64), STACK_SIZE,
119 THREAD2_PRIO);
120
121 OS_WakeupThreadDirect(&thread1);
122 OS_WakeupThreadDirect(&thread2);
123
124 OS_Printf("Idle\n");
125 OS_WakeupThreadDirect(&thread2);
126
127
128 // Quit
129 OS_Printf("==== Finish sample.\n");
130 OS_Terminate();
131
132 while (1)
133 {
134
135 OS_WaitVBlankIntr(); // Waiting for the end of the V-Blank interrupt
136
137 }
138 }
139
140
141 //---------------------------------------------------------------------------
142 // V-Blank interrupt function:
143 //---------------------------------------------------------------------------
VBlankIntr(void)144 static void VBlankIntr(void)
145 {
146 u32 a, b, c;
147 CPContext context;
148
149 // Save context of arithmetic unit
150 CP_SaveContext(&context);
151
152 a = A1;
153 b = B1;
154
155 CP_SetDiv32_32(a, b);
156 OS_Printf("VBlank: Start %x / %x ...\n", a, b);
157 CP_WaitDiv();
158 c = (u32)CP_GetDivResult32();
159
160 OS_Printf("VBlank: Get %x / %x = %x\n", a, b, c);
161
162 // Restore context of arithmetic unit
163 CP_RestoreContext(&context);
164
165 OS_SetIrqCheckFlag(OS_IE_V_BLANK); // Checking V-Blank interrupt
166
167
168 }
169
170
171 //--------------------------------------------------------------------------------
172 // proc1
173 //
proc1(void * arg)174 void proc1(void *arg)
175 {
176 #pragma unused(arg)
177 u64 a;
178 u32 b;
179 u64 c;
180
181 while (1)
182 {
183 OS_Printf("Sleep Thread1\n");
184 OS_SleepThread(NULL);
185 OS_Printf("Wake Thread1 (Priority %d)\n", THREAD1_PRIO);
186
187 a = A2;
188 b = B2;
189
190 CP_SetDiv64_32(a, b);
191 OS_Printf("Thread1: Start %llx / %x ...\n", a, b);
192 CP_WaitDiv();
193 c = (u64)CP_GetDivResult64();
194
195 OS_Printf("Thread1: Get %llx / %x = %x\n", a, b, c);
196 }
197 }
198
199 //--------------------------------------------------------------------------------
200 // proc2
201 //
proc2(void * arg)202 void proc2(void *arg)
203 {
204 #pragma unused(arg)
205 u32 a, b, c;
206
207 while (1)
208 {
209 OS_Printf("Sleep Thread2\n");
210 OS_SleepThread(NULL);
211 OS_Printf("WakeThread2: (Priority %d)\n", THREAD2_PRIO);
212
213 a = A1;
214 b = B1;
215
216 CP_SetDiv32_32(a, b);
217 OS_Printf("Thread2: Start %x / %x ...\n", a, b);
218 CP_WaitDiv();
219
220 // Call thread 1 in the middle of calculation
221 OS_WakeupThreadDirect(&thread1);
222 c = (u32)CP_GetDivResult32();
223 OS_Printf("Thread2: Get %x / %x = %x\n", a, b, c);
224 }
225 }
226