1 /*---------------------------------------------------------------------------*
2   Project:  TwlSDK - OS - demos - mutex-2
3   File:     main.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-04-01#$
14   $Rev: 5205 $
15   $Author: yada $
16  *---------------------------------------------------------------------------*/
17 #include <nitro.h>
18 
19 
20 void    VBlankIntr(void);
21 void    proc1(void *p1);
22 void    proc2(void *p1);
23 void    common(u32 val);
24 
25 //---- thread
26 #define    STACK_SIZE     1024
27 #define    THREAD1_PRIO   10
28 #define    THREAD2_PRIO   11
29 OSThread thread1;
30 OSThread thread2;
31 u64     stack1[STACK_SIZE / sizeof(u64)];
32 u64     stack2[STACK_SIZE / sizeof(u64)];
33 
34 BOOL    th1_sw = FALSE;
35 
36 OSMutex mutex;
37 
38 //---- pad
39 u16     preKeyData;
40 u16     keyData;
41 u16     keyTrigger;
42 
43 //================================================================================
44 /*---------------------------------------------------------------------------*
45   Name:         NitroMain
46 
47   Description:  main
48 
49   Arguments:    None
50 
51   Returns:      None
52  *---------------------------------------------------------------------------*/
NitroMain(void)53 void NitroMain(void)
54 {
55     //================ initialize
56     OS_Init();
57     GX_Init();
58     OS_InitThread();
59 
60     //---- start thread-2
61     OS_InitMutex(&mutex);
62     OS_CreateThread(&thread2, proc2, NULL, stack2 + STACK_SIZE / sizeof(u64), STACK_SIZE,
63                     THREAD2_PRIO);
64     OS_WakeupThreadDirect(&thread2);
65 
66     //----  VBlank setting
67     (void)OS_SetIrqFunction(OS_IE_V_BLANK, VBlankIntr);
68     (void)OS_EnableIrqMask(OS_IE_V_BLANK);
69     (void)OS_EnableIrq();
70     (void)GX_VBlankIntr(TRUE);
71 
72     //---- Dummy READ workaround for pushing 'A' at IPL
73     preKeyData = PAD_Read();
74 
75     //================ main loop
76     while (1)
77     {
78         //---- wait VBlank
79         OS_WaitVBlankIntr();
80 
81         //---- read pad
82         keyData = PAD_Read();
83         keyTrigger = (u16)((preKeyData ^ keyData) & keyData);
84         preKeyData = keyData;
85 
86         //---- press A button to start thread-1
87         if (keyTrigger & PAD_BUTTON_A && !th1_sw)
88         {
89             th1_sw = TRUE;
90             OS_CreateThread(&thread1, proc1, NULL, stack1 + STACK_SIZE / sizeof(u64), STACK_SIZE,
91                             THREAD1_PRIO);
92             OS_WakeupThreadDirect(&thread1);
93         }
94 
95         OS_WakeupThreadDirect(&thread2);
96     }
97 }
98 
99 
100 //--------------------------------------------------------------------------------
101 //    VBlank interrupt handler
102 //
VBlankIntr(void)103 void VBlankIntr(void)
104 {
105     OS_SetIrqCheckFlag(OS_IE_V_BLANK);
106 }
107 
108 //--------------------------------------------------------------------------------
109 //    thread 1
110 //
proc1(void * p1)111 void proc1(void *p1)
112 {
113 #pragma unused(p1)
114     int     cnt = 0;
115 
116     OS_LockMutex(&mutex);
117     while (1)
118     {
119         common(1);
120 
121         //---- exit thread after count 10
122         if (++cnt > 10)
123         {
124             th1_sw = FALSE;
125             OS_ExitThread();           // exit thread with locking mutex
126 
127             // even if exit thread-1 with locking mutex,
128             // release the mutex automatically in OS_ExitThread()
129         }
130     }
131 }
132 
133 //--------------------------------------------------------------------------------
134 //    thread 2
135 //
proc2(void * p1)136 void proc2(void *p1)
137 {
138 #pragma unused(p1)
139     while (1)
140     {
141         OS_LockMutex(&mutex);
142         common(2);
143         OS_UnlockMutex(&mutex);
144 
145         OS_SleepThread(NULL);
146     }
147 }
148 
149 //--------------------------------------------------------------------------------
150 //    common routine ( as critical routine here )
151 //
common(u32 val)152 void common(u32 val)
153 {
154 #ifdef SDK_FINALROM
155 #pragma unused( val )
156 #endif
157 
158     OS_Printf("critical routine called from thread=%d\n", val);
159 }
160 
161 /*====== End of main.c ======*/
162