xref: /nrf52832-nimble/rt-thread/libcpu/sim/win32/cpu_port.c (revision 104654410c56c573564690304ae786df310c91fc)
1*10465441SEvalZero /*
2*10465441SEvalZero ************************************************************************************************************************
3*10465441SEvalZero * File    : cpu_port.c
4*10465441SEvalZero * By      : xyou
5*10465441SEvalZero * Version : V1.00.00
6*10465441SEvalZero *
7*10465441SEvalZero * By      : prife
8*10465441SEvalZero * Version : V1.00.01
9*10465441SEvalZero ************************************************************************************************************************
10*10465441SEvalZero */
11*10465441SEvalZero 
12*10465441SEvalZero /*
13*10465441SEvalZero *********************************************************************************************************
14*10465441SEvalZero *                                             INCLUDE FILES
15*10465441SEvalZero *********************************************************************************************************
16*10465441SEvalZero */
17*10465441SEvalZero #include  <rtthread.h>
18*10465441SEvalZero #include  <windows.h>
19*10465441SEvalZero #include  <mmsystem.h>
20*10465441SEvalZero #include  <stdio.h>
21*10465441SEvalZero #include  "cpu_port.h"
22*10465441SEvalZero 
23*10465441SEvalZero /*
24*10465441SEvalZero *********************************************************************************************************
25*10465441SEvalZero *                                             WinThread STRUCTURE
26*10465441SEvalZero *  Windows runs each task in a thread.
27*10465441SEvalZero *  The context switch is managed by the threads.So the task stack does not have to be managed directly,
28*10465441SEvalZero *  although the stack stack is still used to hold an WinThreadState structure this is the only thing it
29*10465441SEvalZero *  will be ever hold.
30*10465441SEvalZero *  the structure indirectly maps the task handle to a thread handle
31*10465441SEvalZero *********************************************************************************************************
32*10465441SEvalZero */
33*10465441SEvalZero typedef struct
34*10465441SEvalZero {
35*10465441SEvalZero     void            *Param;                     //Thread param
36*10465441SEvalZero     void            (*Entry)(void *);           //Thread entry
37*10465441SEvalZero     void            (*Exit)(void);                      //Thread exit
38*10465441SEvalZero     HANDLE          ThreadHandle;
39*10465441SEvalZero     DWORD           ThreadID;
40*10465441SEvalZero }win_thread_t;
41*10465441SEvalZero 
42*10465441SEvalZero const DWORD MS_VC_EXCEPTION=0x406D1388;
43*10465441SEvalZero 
44*10465441SEvalZero #pragma pack(push,8)
45*10465441SEvalZero typedef struct tagTHREADNAME_INFO
46*10465441SEvalZero {
47*10465441SEvalZero 	DWORD dwType; // Must be 0x1000.
48*10465441SEvalZero 	LPCSTR szName; // Pointer to name (in user addr space).
49*10465441SEvalZero 	DWORD dwThreadID; // Thread ID (-1=caller thread).
50*10465441SEvalZero 	DWORD dwFlags; // Reserved for future use, must be zero.
51*10465441SEvalZero } THREADNAME_INFO;
52*10465441SEvalZero #pragma pack(pop)
53*10465441SEvalZero 
54*10465441SEvalZero /*
55*10465441SEvalZero *********************************************************************************************************
56*10465441SEvalZero *                                             LOCAL DEFINES
57*10465441SEvalZero *********************************************************************************************************
58*10465441SEvalZero */
59*10465441SEvalZero #define MAX_INTERRUPT_NUM       ((rt_uint32_t)sizeof(rt_uint32_t) * 8)
60*10465441SEvalZero 
61*10465441SEvalZero /*
62*10465441SEvalZero  * Simulated interrupt waiting to be processed.this is a bit mask where each bit represent one interrupt
63*10465441SEvalZero  * so a maximum of 32 interrupts can be simulated
64*10465441SEvalZero  */
65*10465441SEvalZero static volatile rt_uint32_t  CpuPendingInterrupts = 0;
66*10465441SEvalZero 
67*10465441SEvalZero /*
68*10465441SEvalZero  * An event used to inform the simulated interrupt processing thread (a high priority thread
69*10465441SEvalZero  *      that simulated interrupt processing) that an interrupt is pending
70*10465441SEvalZero  */
71*10465441SEvalZero static HANDLE   hInterruptEventHandle = NULL;
72*10465441SEvalZero 
73*10465441SEvalZero /*
74*10465441SEvalZero  * Mutex used to protect all the simulated interrupt variables that are accessed by multiple threads
75*10465441SEvalZero  */
76*10465441SEvalZero static HANDLE   hInterruptEventMutex = NULL;
77*10465441SEvalZero 
78*10465441SEvalZero /*
79*10465441SEvalZero  * Handler for all the simulate software interrupts.
80*10465441SEvalZero  * The first two positions are used the Yield and Tick interrupt so are handled slightly differently
81*10465441SEvalZero  * all the other interrupts can be user defined
82*10465441SEvalZero */
83*10465441SEvalZero static rt_uint32_t (*CpuIsrHandler[MAX_INTERRUPT_NUM])(void) = {0};
84*10465441SEvalZero 
85*10465441SEvalZero /*
86*10465441SEvalZero  * Handler for OSTick Thread
87*10465441SEvalZero  */
88*10465441SEvalZero static HANDLE       OSTick_Thread;
89*10465441SEvalZero static DWORD        OSTick_ThreadID;
90*10465441SEvalZero static HANDLE       OSTick_SignalPtr;
91*10465441SEvalZero static TIMECAPS     OSTick_TimerCap;
92*10465441SEvalZero static MMRESULT     OSTick_TimerID;
93*10465441SEvalZero 
94*10465441SEvalZero /*
95*10465441SEvalZero  * flag in interrupt handling
96*10465441SEvalZero  */
97*10465441SEvalZero rt_uint32_t rt_interrupt_from_thread, rt_interrupt_to_thread;
98*10465441SEvalZero rt_uint32_t rt_thread_switch_interrupt_flag;
99*10465441SEvalZero 
100*10465441SEvalZero /*
101*10465441SEvalZero *********************************************************************************************************
102*10465441SEvalZero *                                             PRIVATE FUNCTION PROTOTYPES
103*10465441SEvalZero *********************************************************************************************************
104*10465441SEvalZero */
105*10465441SEvalZero //static void WinThreadScheduler(void);
106*10465441SEvalZero void WinThreadScheduler(void);
107*10465441SEvalZero rt_uint32_t YieldInterruptHandle(void);
108*10465441SEvalZero rt_uint32_t SysTickInterruptHandle(void);
109*10465441SEvalZero static DWORD WINAPI ThreadforSysTickTimer(LPVOID lpParam);
110*10465441SEvalZero static DWORD WINAPI ThreadforKeyGet(LPVOID lpParam);
111*10465441SEvalZero 
SetThreadName(DWORD dwThreadID,char * threadName)112*10465441SEvalZero static void SetThreadName(DWORD dwThreadID, char* threadName)
113*10465441SEvalZero {
114*10465441SEvalZero #if defined(_MSC_VER)
115*10465441SEvalZero 	THREADNAME_INFO info;
116*10465441SEvalZero 	info.dwType = 0x1000;
117*10465441SEvalZero 	info.szName = threadName;
118*10465441SEvalZero 	info.dwThreadID = dwThreadID;
119*10465441SEvalZero 	info.dwFlags = 0;
120*10465441SEvalZero 
121*10465441SEvalZero 	__try
122*10465441SEvalZero 	{
123*10465441SEvalZero 		RaiseException( MS_VC_EXCEPTION, 0, sizeof(info)/sizeof(ULONG_PTR), (ULONG_PTR*)&info );
124*10465441SEvalZero 	}
125*10465441SEvalZero 	__except(EXCEPTION_EXECUTE_HANDLER)
126*10465441SEvalZero 	{
127*10465441SEvalZero 	}
128*10465441SEvalZero #endif
129*10465441SEvalZero }
130*10465441SEvalZero 
131*10465441SEvalZero /*
132*10465441SEvalZero *********************************************************************************************************
133*10465441SEvalZero *                                            rt_hw_stack_init()
134*10465441SEvalZero * Description : Initialize stack of thread
135*10465441SEvalZero * Argument(s) : void *pvEntry,void *pvParam,rt_uint8_t *pStackAddr,void *pvExit
136*10465441SEvalZero * Return(s)   : rt_uint8_t*
137*10465441SEvalZero * Caller(s)   : rt_thread_init or rt_thread_create
138*10465441SEvalZero * Note(s)     : none
139*10465441SEvalZero *********************************************************************************************************
140*10465441SEvalZero */
141*10465441SEvalZero 
thread_run(LPVOID lpThreadParameter)142*10465441SEvalZero static DWORD WINAPI thread_run( LPVOID lpThreadParameter )
143*10465441SEvalZero {
144*10465441SEvalZero 	rt_thread_t tid = rt_thread_self();
145*10465441SEvalZero 	win_thread_t  *pWinThread = (win_thread_t *)lpThreadParameter;
146*10465441SEvalZero 
147*10465441SEvalZero 	SetThreadName(GetCurrentThreadId(), tid->name);
148*10465441SEvalZero 
149*10465441SEvalZero 	pWinThread->Entry(pWinThread->Param);
150*10465441SEvalZero 
151*10465441SEvalZero 	pWinThread->Exit();
152*10465441SEvalZero 	return 0;
153*10465441SEvalZero }
154*10465441SEvalZero 
rt_hw_stack_init(void * pEntry,void * pParam,rt_uint8_t * pStackAddr,void * pExit)155*10465441SEvalZero rt_uint8_t* rt_hw_stack_init(void *pEntry,void *pParam,rt_uint8_t *pStackAddr,void *pExit)
156*10465441SEvalZero {
157*10465441SEvalZero     win_thread_t    *pWinThread = NULL;
158*10465441SEvalZero 
159*10465441SEvalZero     /*
160*10465441SEvalZero      * In this simulated case a stack is not initialized
161*10465441SEvalZero      * The thread handles the context switching itself. The WinThreadState object is placed onto the stack
162*10465441SEvalZero      * that was created for the task
163*10465441SEvalZero      * so the stack buffer is still used,just not in the conventional way.
164*10465441SEvalZero      */
165*10465441SEvalZero     pWinThread = (win_thread_t *)(pStackAddr - sizeof(win_thread_t));
166*10465441SEvalZero 
167*10465441SEvalZero     pWinThread->Entry = pEntry;
168*10465441SEvalZero     pWinThread->Param = pParam;
169*10465441SEvalZero     pWinThread->Exit = pExit;
170*10465441SEvalZero 
171*10465441SEvalZero     pWinThread->ThreadHandle = NULL;
172*10465441SEvalZero     pWinThread->ThreadID = 0;
173*10465441SEvalZero 
174*10465441SEvalZero     /* Create the winthread */
175*10465441SEvalZero     pWinThread->ThreadHandle = CreateThread(NULL,
176*10465441SEvalZero                                             0,
177*10465441SEvalZero                                             (LPTHREAD_START_ROUTINE) thread_run,
178*10465441SEvalZero                                             pWinThread,
179*10465441SEvalZero                                             CREATE_SUSPENDED,
180*10465441SEvalZero                                             &(pWinThread->ThreadID));
181*10465441SEvalZero     SetThreadAffinityMask(pWinThread->ThreadHandle,
182*10465441SEvalZero                           0x01);
183*10465441SEvalZero     SetThreadPriorityBoost(pWinThread->ThreadHandle,
184*10465441SEvalZero                            TRUE);
185*10465441SEvalZero     SetThreadPriority(pWinThread->ThreadHandle,
186*10465441SEvalZero                       THREAD_PRIORITY_IDLE);
187*10465441SEvalZero 
188*10465441SEvalZero     return (rt_uint8_t*)pWinThread;
189*10465441SEvalZero } /*** rt_hw_stack_init ***/
190*10465441SEvalZero 
191*10465441SEvalZero /*
192*10465441SEvalZero *********************************************************************************************************
193*10465441SEvalZero *                                            rt_hw_interrupt_disable()
194*10465441SEvalZero * Description : disable cpu interrupts
195*10465441SEvalZero * Argument(s) : void
196*10465441SEvalZero * Return(s)   : rt_base_t
197*10465441SEvalZero * Caller(s)   : Applicatios or os_kernel
198*10465441SEvalZero * Note(s)     : none
199*10465441SEvalZero *********************************************************************************************************
200*10465441SEvalZero */
rt_hw_interrupt_disable(void)201*10465441SEvalZero rt_base_t rt_hw_interrupt_disable(void)
202*10465441SEvalZero {
203*10465441SEvalZero     if(hInterruptEventMutex != NULL)
204*10465441SEvalZero     {
205*10465441SEvalZero         WaitForSingleObject(hInterruptEventMutex,INFINITE);
206*10465441SEvalZero     }
207*10465441SEvalZero 
208*10465441SEvalZero     return 0;
209*10465441SEvalZero } /*** rt_hw_interrupt_disable ***/
210*10465441SEvalZero 
211*10465441SEvalZero 
212*10465441SEvalZero /*
213*10465441SEvalZero *********************************************************************************************************
214*10465441SEvalZero *                                            rt_hw_interrupt_enable()
215*10465441SEvalZero * Description : enable cpu interrupts
216*10465441SEvalZero * Argument(s) : rt_base_t level
217*10465441SEvalZero * Return(s)   : void
218*10465441SEvalZero * Caller(s)   : Applications or os_kernel
219*10465441SEvalZero * Note(s)     : none
220*10465441SEvalZero *********************************************************************************************************
221*10465441SEvalZero */
rt_hw_interrupt_enable(rt_base_t level)222*10465441SEvalZero void rt_hw_interrupt_enable(rt_base_t level)
223*10465441SEvalZero {
224*10465441SEvalZero     level = level;
225*10465441SEvalZero 
226*10465441SEvalZero     if (hInterruptEventMutex != NULL)
227*10465441SEvalZero     {
228*10465441SEvalZero         ReleaseMutex(hInterruptEventMutex);
229*10465441SEvalZero     }
230*10465441SEvalZero 
231*10465441SEvalZero } /*** rt_hw_interrupt_enable ***/
232*10465441SEvalZero 
233*10465441SEvalZero /*
234*10465441SEvalZero *********************************************************************************************************
235*10465441SEvalZero *                                            rt_hw_context_switch_interrupt()
236*10465441SEvalZero * Description : switch thread's contex
237*10465441SEvalZero * Argument(s) : void
238*10465441SEvalZero * Return(s)   : void
239*10465441SEvalZero * Caller(s)   : os kernel
240*10465441SEvalZero * Note(s)     : none
241*10465441SEvalZero *********************************************************************************************************
242*10465441SEvalZero */
rt_hw_context_switch_interrupt(rt_uint32_t from,rt_uint32_t to)243*10465441SEvalZero void rt_hw_context_switch_interrupt(rt_uint32_t from,
244*10465441SEvalZero                                     rt_uint32_t to)
245*10465441SEvalZero {
246*10465441SEvalZero     if(rt_thread_switch_interrupt_flag != 1)
247*10465441SEvalZero     {
248*10465441SEvalZero         rt_thread_switch_interrupt_flag = 1;
249*10465441SEvalZero 
250*10465441SEvalZero         // set rt_interrupt_from_thread
251*10465441SEvalZero         rt_interrupt_from_thread = *((rt_uint32_t *)(from));
252*10465441SEvalZero     }
253*10465441SEvalZero 
254*10465441SEvalZero     rt_interrupt_to_thread = *((rt_uint32_t *)(to));
255*10465441SEvalZero 
256*10465441SEvalZero 	//trigger YIELD exception(cause context switch)
257*10465441SEvalZero     TriggerSimulateInterrupt(CPU_INTERRUPT_YIELD);
258*10465441SEvalZero } /*** rt_hw_context_switch_interrupt ***/
259*10465441SEvalZero 
260*10465441SEvalZero 
261*10465441SEvalZero 
rt_hw_context_switch(rt_uint32_t from,rt_uint32_t to)262*10465441SEvalZero void rt_hw_context_switch(rt_uint32_t from,
263*10465441SEvalZero                           rt_uint32_t to)
264*10465441SEvalZero {
265*10465441SEvalZero     if(rt_thread_switch_interrupt_flag != 1)
266*10465441SEvalZero     {
267*10465441SEvalZero         rt_thread_switch_interrupt_flag  = 1;
268*10465441SEvalZero 
269*10465441SEvalZero         // set rt_interrupt_from_thread
270*10465441SEvalZero         rt_interrupt_from_thread = *((rt_uint32_t *)(from));
271*10465441SEvalZero 
272*10465441SEvalZero     }
273*10465441SEvalZero 
274*10465441SEvalZero     // set rt_interrupt_to_thread
275*10465441SEvalZero     rt_interrupt_to_thread = *((rt_uint32_t *)(to));
276*10465441SEvalZero 
277*10465441SEvalZero     //trigger YIELD exception(cause contex switch)
278*10465441SEvalZero     TriggerSimulateInterrupt(CPU_INTERRUPT_YIELD);
279*10465441SEvalZero 
280*10465441SEvalZero } /*** rt_hw_context_switch ***/
281*10465441SEvalZero 
282*10465441SEvalZero /*
283*10465441SEvalZero *********************************************************************************************************
284*10465441SEvalZero *                                            rt_hw_context_switch_to()
285*10465441SEvalZero * Description : switch to new thread
286*10465441SEvalZero * Argument(s) : rt_uint32_t to              //the stack address of the thread which will switch to
287*10465441SEvalZero * Return(s)   : void
288*10465441SEvalZero * Caller(s)   : rt_thread schecale
289*10465441SEvalZero * Note(s)     : this function is used to perform the first thread switch
290*10465441SEvalZero *********************************************************************************************************
291*10465441SEvalZero */
rt_hw_context_switch_to(rt_uint32_t to)292*10465441SEvalZero void rt_hw_context_switch_to(rt_uint32_t to)
293*10465441SEvalZero {
294*10465441SEvalZero 	//set to thread
295*10465441SEvalZero     rt_interrupt_to_thread = *((rt_uint32_t *)(to));
296*10465441SEvalZero 
297*10465441SEvalZero     //clear from thread
298*10465441SEvalZero     rt_interrupt_from_thread = 0;
299*10465441SEvalZero 
300*10465441SEvalZero     //set interrupt to 1
301*10465441SEvalZero     rt_thread_switch_interrupt_flag = 1;
302*10465441SEvalZero 
303*10465441SEvalZero     //start WinThreadScheduler
304*10465441SEvalZero     WinThreadScheduler();
305*10465441SEvalZero 
306*10465441SEvalZero     //never reach here!
307*10465441SEvalZero     return;
308*10465441SEvalZero 
309*10465441SEvalZero } /*** rt_hw_context_switch_to ***/
310*10465441SEvalZero 
311*10465441SEvalZero 
312*10465441SEvalZero 
313*10465441SEvalZero /*
314*10465441SEvalZero *********************************************************************************************************
315*10465441SEvalZero *                                            TriggerSimulateInterrupt()
316*10465441SEvalZero * Description : Trigger a simulated interrupts handle
317*10465441SEvalZero * Argument(s) : t_uint32_t IntIndex
318*10465441SEvalZero * Return(s)   : void
319*10465441SEvalZero * Caller(s)   : Applications
320*10465441SEvalZero * Note(s)     : none
321*10465441SEvalZero *********************************************************************************************************
322*10465441SEvalZero */
TriggerSimulateInterrupt(rt_uint32_t IntIndex)323*10465441SEvalZero void TriggerSimulateInterrupt(rt_uint32_t IntIndex)
324*10465441SEvalZero {
325*10465441SEvalZero     if((IntIndex < MAX_INTERRUPT_NUM) && (hInterruptEventMutex != NULL))
326*10465441SEvalZero     {
327*10465441SEvalZero         /* Yield interrupts are processed even when critical nesting is non-zero  */
328*10465441SEvalZero         WaitForSingleObject(hInterruptEventMutex,
329*10465441SEvalZero                             INFINITE);
330*10465441SEvalZero 
331*10465441SEvalZero         CpuPendingInterrupts |= (1 << IntIndex);
332*10465441SEvalZero 
333*10465441SEvalZero         SetEvent(hInterruptEventHandle);
334*10465441SEvalZero 
335*10465441SEvalZero         ReleaseMutex(hInterruptEventMutex);
336*10465441SEvalZero     }
337*10465441SEvalZero } /*** TriggerSimulateInterrupt ***/
338*10465441SEvalZero 
339*10465441SEvalZero /*
340*10465441SEvalZero *********************************************************************************************************
341*10465441SEvalZero *                                            RegisterSimulateInterrupt()
342*10465441SEvalZero * Description : Register a interrupt handle to simulate paltform
343*10465441SEvalZero * Argument(s) : rt_uint32_t IntIndex,rt_uint32_t (*IntHandler)(void)
344*10465441SEvalZero * Return(s)   : void
345*10465441SEvalZero * Caller(s)   : Applications
346*10465441SEvalZero * Note(s)     : none
347*10465441SEvalZero *********************************************************************************************************
348*10465441SEvalZero */
RegisterSimulateInterrupt(rt_uint32_t IntIndex,rt_uint32_t (* IntHandler)(void))349*10465441SEvalZero void RegisterSimulateInterrupt(rt_uint32_t IntIndex,rt_uint32_t (*IntHandler)(void))
350*10465441SEvalZero {
351*10465441SEvalZero     if(IntIndex < MAX_INTERRUPT_NUM)
352*10465441SEvalZero     {
353*10465441SEvalZero         if (hInterruptEventMutex != NULL)
354*10465441SEvalZero         {
355*10465441SEvalZero             WaitForSingleObject(hInterruptEventMutex,
356*10465441SEvalZero                                 INFINITE);
357*10465441SEvalZero 
358*10465441SEvalZero             CpuIsrHandler[IntIndex] = IntHandler;
359*10465441SEvalZero 
360*10465441SEvalZero             ReleaseMutex(hInterruptEventMutex);
361*10465441SEvalZero         }
362*10465441SEvalZero         else
363*10465441SEvalZero         {
364*10465441SEvalZero             CpuIsrHandler[IntIndex] = IntHandler;
365*10465441SEvalZero         }
366*10465441SEvalZero     }
367*10465441SEvalZero 
368*10465441SEvalZero } /*** RegisterSimulateInterrupt ***/
369*10465441SEvalZero 
370*10465441SEvalZero 
371*10465441SEvalZero 
372*10465441SEvalZero /*
373*10465441SEvalZero *********************************************************************************************************
374*10465441SEvalZero *                                             PRIVATE FUNCTION
375*10465441SEvalZero *********************************************************************************************************
376*10465441SEvalZero */
377*10465441SEvalZero 
378*10465441SEvalZero /*
379*10465441SEvalZero *********************************************************************************************************
380*10465441SEvalZero *                                            WinThreadScheduler()
381*10465441SEvalZero * Description : Handle all simulate interrupts
382*10465441SEvalZero * Argument(s) : void
383*10465441SEvalZero * Return(s)   : static void
384*10465441SEvalZero * Caller(s)   : os scachle
385*10465441SEvalZero * Note(s)     : none
386*10465441SEvalZero *********************************************************************************************************
387*10465441SEvalZero */
388*10465441SEvalZero #define WIN_WM_MIN_RES      (1)
WinThreadScheduler(void)389*10465441SEvalZero  void WinThreadScheduler(void)
390*10465441SEvalZero {
391*10465441SEvalZero     HANDLE          hInterruptObjectList[2];
392*10465441SEvalZero     HANDLE          hThreadHandle;
393*10465441SEvalZero     rt_uint32_t     SwitchRequiredMask;
394*10465441SEvalZero     rt_uint32_t     i;
395*10465441SEvalZero 
396*10465441SEvalZero     win_thread_t    *WinThreadFrom;
397*10465441SEvalZero     win_thread_t    *WinThreadTo;
398*10465441SEvalZero 
399*10465441SEvalZero     /*
400*10465441SEvalZero      * Install the interrupt handlers used bye scheduler itself
401*10465441SEvalZero      */
402*10465441SEvalZero     RegisterSimulateInterrupt(CPU_INTERRUPT_YIELD,
403*10465441SEvalZero                               YieldInterruptHandle);
404*10465441SEvalZero     RegisterSimulateInterrupt(CPU_INTERRUPT_TICK,
405*10465441SEvalZero                               SysTickInterruptHandle);
406*10465441SEvalZero 
407*10465441SEvalZero     /*
408*10465441SEvalZero      * Create the events and mutex that are used to synchronise all the WinThreads
409*10465441SEvalZero      */
410*10465441SEvalZero     hInterruptEventMutex = CreateMutex(NULL,
411*10465441SEvalZero                                        FALSE,
412*10465441SEvalZero                                        NULL);
413*10465441SEvalZero     hInterruptEventHandle = CreateEvent(NULL,
414*10465441SEvalZero                                         FALSE,
415*10465441SEvalZero                                         FALSE,
416*10465441SEvalZero                                         NULL);
417*10465441SEvalZero 
418*10465441SEvalZero     if((hInterruptEventMutex == NULL) || (hInterruptEventHandle == NULL))
419*10465441SEvalZero     {
420*10465441SEvalZero         return;
421*10465441SEvalZero     }
422*10465441SEvalZero 
423*10465441SEvalZero     /*
424*10465441SEvalZero      * Set the priority of this WinThread such that it is above the priority of the WinThreads
425*10465441SEvalZero      * that run rt-threads.
426*10465441SEvalZero      * This is higher priority is required to ensure simulate interrupts take priority over rt-threads
427*10465441SEvalZero      */
428*10465441SEvalZero     hThreadHandle = GetCurrentThread();
429*10465441SEvalZero     if(hThreadHandle == NULL)
430*10465441SEvalZero     {
431*10465441SEvalZero         return;
432*10465441SEvalZero     }
433*10465441SEvalZero 
434*10465441SEvalZero     if (SetThreadPriority(hThreadHandle,
435*10465441SEvalZero                           THREAD_PRIORITY_HIGHEST) == 0)
436*10465441SEvalZero     {
437*10465441SEvalZero         return;
438*10465441SEvalZero     }
439*10465441SEvalZero     SetThreadPriorityBoost(hThreadHandle,
440*10465441SEvalZero                            TRUE);
441*10465441SEvalZero     SetThreadAffinityMask(hThreadHandle,
442*10465441SEvalZero                           0x01);
443*10465441SEvalZero 
444*10465441SEvalZero     /*
445*10465441SEvalZero      * Start the thread that simulates the timer peripheral to generate tick interrupts.
446*10465441SEvalZero      */
447*10465441SEvalZero     OSTick_Thread = CreateThread(NULL,
448*10465441SEvalZero                                  0,
449*10465441SEvalZero                                  ThreadforSysTickTimer,
450*10465441SEvalZero                                  0,
451*10465441SEvalZero                                  CREATE_SUSPENDED,
452*10465441SEvalZero                                  &OSTick_ThreadID);
453*10465441SEvalZero     if(OSTick_Thread == NULL)
454*10465441SEvalZero     {
455*10465441SEvalZero         //Display Error Message
456*10465441SEvalZero 
457*10465441SEvalZero 
458*10465441SEvalZero         return;
459*10465441SEvalZero     }
460*10465441SEvalZero     SetThreadPriority(OSTick_Thread,
461*10465441SEvalZero                       THREAD_PRIORITY_NORMAL);
462*10465441SEvalZero     SetThreadPriorityBoost(OSTick_Thread,
463*10465441SEvalZero                            TRUE);
464*10465441SEvalZero     SetThreadAffinityMask(OSTick_Thread,
465*10465441SEvalZero                           0x01);
466*10465441SEvalZero 
467*10465441SEvalZero     /*
468*10465441SEvalZero      * Set timer Caps
469*10465441SEvalZero      */
470*10465441SEvalZero     if (timeGetDevCaps(&OSTick_TimerCap,
471*10465441SEvalZero                        sizeof(OSTick_TimerCap)) != TIMERR_NOERROR)
472*10465441SEvalZero     {
473*10465441SEvalZero 
474*10465441SEvalZero         CloseHandle(OSTick_Thread);
475*10465441SEvalZero 
476*10465441SEvalZero         return;
477*10465441SEvalZero     }
478*10465441SEvalZero     if (OSTick_TimerCap.wPeriodMin < WIN_WM_MIN_RES)
479*10465441SEvalZero     {
480*10465441SEvalZero         OSTick_TimerCap.wPeriodMin = WIN_WM_MIN_RES;
481*10465441SEvalZero     }
482*10465441SEvalZero 
483*10465441SEvalZero     if(timeBeginPeriod(OSTick_TimerCap.wPeriodMin) != TIMERR_NOERROR)
484*10465441SEvalZero     {
485*10465441SEvalZero         CloseHandle(OSTick_Thread);
486*10465441SEvalZero 
487*10465441SEvalZero         return;
488*10465441SEvalZero     }
489*10465441SEvalZero 
490*10465441SEvalZero     OSTick_SignalPtr = CreateEvent(NULL,TRUE,FALSE,NULL);
491*10465441SEvalZero     if(OSTick_SignalPtr == NULL)
492*10465441SEvalZero     {
493*10465441SEvalZero         // disp error message
494*10465441SEvalZero 
495*10465441SEvalZero         timeEndPeriod(OSTick_TimerCap.wPeriodMin);
496*10465441SEvalZero         CloseHandle(OSTick_Thread);
497*10465441SEvalZero 
498*10465441SEvalZero         return;
499*10465441SEvalZero     }
500*10465441SEvalZero 
501*10465441SEvalZero     OSTick_TimerID = timeSetEvent((UINT             )   (1000 / RT_TICK_PER_SECOND) ,
502*10465441SEvalZero                                   (UINT             )   OSTick_TimerCap.wPeriodMin,
503*10465441SEvalZero                                   (LPTIMECALLBACK   )   OSTick_SignalPtr,
504*10465441SEvalZero                                   (DWORD_PTR        )   NULL,
505*10465441SEvalZero                                   (UINT             )   (TIME_PERIODIC | TIME_CALLBACK_EVENT_SET));
506*10465441SEvalZero 
507*10465441SEvalZero     if(OSTick_TimerID == 0)
508*10465441SEvalZero     {
509*10465441SEvalZero         //disp
510*10465441SEvalZero 
511*10465441SEvalZero         CloseHandle(OSTick_SignalPtr);
512*10465441SEvalZero         timeEndPeriod(OSTick_TimerCap.wPeriodMin);
513*10465441SEvalZero         CloseHandle(OSTick_Thread);
514*10465441SEvalZero 
515*10465441SEvalZero         return;
516*10465441SEvalZero     }
517*10465441SEvalZero 
518*10465441SEvalZero     /*
519*10465441SEvalZero      * Start OS Tick Thread an release Interrupt Mutex
520*10465441SEvalZero      */
521*10465441SEvalZero     ResumeThread(OSTick_Thread);
522*10465441SEvalZero     ReleaseMutex( hInterruptEventMutex );
523*10465441SEvalZero 
524*10465441SEvalZero     //trigger YEILD INTERRUPT
525*10465441SEvalZero     TriggerSimulateInterrupt(CPU_INTERRUPT_YIELD);
526*10465441SEvalZero 
527*10465441SEvalZero     /*
528*10465441SEvalZero      * block on the mutex that ensure exclusive access to the simulated interrupt objects
529*10465441SEvalZero      *  and the events that signals that a simulated interrupt should be processed.
530*10465441SEvalZero      */
531*10465441SEvalZero 
532*10465441SEvalZero     hInterruptObjectList[0] = hInterruptEventHandle;
533*10465441SEvalZero     hInterruptObjectList[1] = hInterruptEventMutex;
534*10465441SEvalZero 
535*10465441SEvalZero 
536*10465441SEvalZero     while (1)
537*10465441SEvalZero     {
538*10465441SEvalZero         WaitForMultipleObjects(sizeof(hInterruptObjectList) / sizeof(HANDLE),
539*10465441SEvalZero                                hInterruptObjectList,
540*10465441SEvalZero                                TRUE,
541*10465441SEvalZero                                INFINITE);
542*10465441SEvalZero 
543*10465441SEvalZero         /*
544*10465441SEvalZero          * Used to indicate whether the simulate interrupt processing has necessitated a contex
545*10465441SEvalZero          * switch to another thread
546*10465441SEvalZero          */
547*10465441SEvalZero         SwitchRequiredMask = 0;
548*10465441SEvalZero 
549*10465441SEvalZero         /*
550*10465441SEvalZero          * For each interrupt we are interested in processing ,each of which is represented
551*10465441SEvalZero          * by a bit in the 32bit CpuPendingInterrupts variable.
552*10465441SEvalZero          */
553*10465441SEvalZero         for (i = 0; i < MAX_INTERRUPT_NUM; ++i)
554*10465441SEvalZero         {
555*10465441SEvalZero             /* is the simulated interrupt pending ? */
556*10465441SEvalZero             if (CpuPendingInterrupts & (1UL << i))
557*10465441SEvalZero             {
558*10465441SEvalZero                 /* Is a handler installed ?*/
559*10465441SEvalZero                 if (CpuIsrHandler[i] != NULL)
560*10465441SEvalZero                 {
561*10465441SEvalZero                     /* Run the actual handler */
562*10465441SEvalZero                     if (CpuIsrHandler[i]() != 0)
563*10465441SEvalZero                     {
564*10465441SEvalZero                         SwitchRequiredMask |= (1UL << i);
565*10465441SEvalZero                     }
566*10465441SEvalZero                 }
567*10465441SEvalZero 
568*10465441SEvalZero                 /* Clear the interrupt pending bit */
569*10465441SEvalZero                 CpuPendingInterrupts &= ~(1UL << i);
570*10465441SEvalZero             }
571*10465441SEvalZero         }
572*10465441SEvalZero 
573*10465441SEvalZero         if(SwitchRequiredMask != 0)
574*10465441SEvalZero         {
575*10465441SEvalZero             WinThreadFrom = (win_thread_t *)rt_interrupt_from_thread;
576*10465441SEvalZero             WinThreadTo = (win_thread_t *)rt_interrupt_to_thread;
577*10465441SEvalZero 
578*10465441SEvalZero             if ((WinThreadFrom != NULL) && (WinThreadFrom->ThreadHandle != NULL))
579*10465441SEvalZero             {
580*10465441SEvalZero                 SuspendThread(WinThreadFrom->ThreadHandle);
581*10465441SEvalZero             }
582*10465441SEvalZero 
583*10465441SEvalZero             ResumeThread(WinThreadTo->ThreadHandle);
584*10465441SEvalZero 
585*10465441SEvalZero         }
586*10465441SEvalZero 
587*10465441SEvalZero         ReleaseMutex(hInterruptEventMutex);
588*10465441SEvalZero     }
589*10465441SEvalZero } /*** WinThreadScheduler ***/
590*10465441SEvalZero 
591*10465441SEvalZero 
592*10465441SEvalZero 
593*10465441SEvalZero /*
594*10465441SEvalZero *********************************************************************************************************
595*10465441SEvalZero *                                            ThreadforSysTickTimer()
596*10465441SEvalZero * Description : win thread to simulate a systick timer
597*10465441SEvalZero * Argument(s) : LPVOID lpParam
598*10465441SEvalZero * Return(s)   : static DWORD WINAPI
599*10465441SEvalZero * Caller(s)   : none
600*10465441SEvalZero * Note(s)     : This is not a real time way of generating tick events as the next wake time should be relative
601*10465441SEvalZero *               to the previous wake time,not the time Sleep() is called.
602*10465441SEvalZero *               It is done this way to prevent overruns in this very non real time simulated/emulated environment
603*10465441SEvalZero *********************************************************************************************************
604*10465441SEvalZero */
ThreadforSysTickTimer(LPVOID lpParam)605*10465441SEvalZero static DWORD WINAPI ThreadforSysTickTimer(LPVOID lpParam)
606*10465441SEvalZero {
607*10465441SEvalZero 
608*10465441SEvalZero     (void)lpParam;              //prevent compiler warnings
609*10465441SEvalZero 
610*10465441SEvalZero     for(;;)
611*10465441SEvalZero     {
612*10465441SEvalZero         /*
613*10465441SEvalZero          * Wait until the timer expires and we can access the simulated interrupt variables.
614*10465441SEvalZero          */
615*10465441SEvalZero         WaitForSingleObject(OSTick_SignalPtr,INFINITE);
616*10465441SEvalZero 
617*10465441SEvalZero         ResetEvent(OSTick_SignalPtr);
618*10465441SEvalZero 
619*10465441SEvalZero         /*
620*10465441SEvalZero          * Trigger a systick interrupt
621*10465441SEvalZero          */
622*10465441SEvalZero         TriggerSimulateInterrupt(CPU_INTERRUPT_TICK);
623*10465441SEvalZero 
624*10465441SEvalZero     }
625*10465441SEvalZero 
626*10465441SEvalZero     return 0;
627*10465441SEvalZero 
628*10465441SEvalZero } /*** prvThreadforSysTickTimer ***/
629*10465441SEvalZero 
630*10465441SEvalZero /*
631*10465441SEvalZero *********************************************************************************************************
632*10465441SEvalZero *                                            SysTickInterruptHandle()
633*10465441SEvalZero * Description : Interrupt handle for systick
634*10465441SEvalZero * Argument(s) : void
635*10465441SEvalZero * Return(s)   : rt_uint32_t
636*10465441SEvalZero * Caller(s)   : none
637*10465441SEvalZero * Note(s)     : none
638*10465441SEvalZero *********************************************************************************************************
639*10465441SEvalZero */
SysTickInterruptHandle(void)640*10465441SEvalZero rt_uint32_t SysTickInterruptHandle(void)
641*10465441SEvalZero {
642*10465441SEvalZero 
643*10465441SEvalZero     /* enter interrupt */
644*10465441SEvalZero     rt_interrupt_enter();
645*10465441SEvalZero 
646*10465441SEvalZero     rt_tick_increase();
647*10465441SEvalZero 
648*10465441SEvalZero     /* leave interrupt */
649*10465441SEvalZero     rt_interrupt_leave();
650*10465441SEvalZero 
651*10465441SEvalZero     return 0;
652*10465441SEvalZero } /*** SysTickInterruptHandle ***/
653*10465441SEvalZero 
654*10465441SEvalZero /*
655*10465441SEvalZero *********************************************************************************************************
656*10465441SEvalZero *                                            YieldInterruptHandle()
657*10465441SEvalZero * Description : Interrupt handle for Yield
658*10465441SEvalZero * Argument(s) : void
659*10465441SEvalZero * Return(s)   : rt_uint32_t
660*10465441SEvalZero * Caller(s)   : none
661*10465441SEvalZero * Note(s)     : none
662*10465441SEvalZero *********************************************************************************************************
663*10465441SEvalZero */
YieldInterruptHandle(void)664*10465441SEvalZero rt_uint32_t YieldInterruptHandle(void)
665*10465441SEvalZero {
666*10465441SEvalZero 
667*10465441SEvalZero     /*
668*10465441SEvalZero      * if rt_thread_switch_interrupt_flag = 1 yield already handled
669*10465441SEvalZero      */
670*10465441SEvalZero     if(rt_thread_switch_interrupt_flag != 0)
671*10465441SEvalZero     {
672*10465441SEvalZero         rt_thread_switch_interrupt_flag = 0;
673*10465441SEvalZero 
674*10465441SEvalZero         /* return thread switch request = 1 */
675*10465441SEvalZero         return 1;
676*10465441SEvalZero     }
677*10465441SEvalZero 
678*10465441SEvalZero     return 0;
679*10465441SEvalZero } /*** YieldInterruptHandle ***/
680