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