diff options
Diffstat (limited to 'libcpu/sim')
| -rw-r--r-- | libcpu/sim/win32/cpu_port.c | 1354 | ||||
| -rw-r--r-- | libcpu/sim/win32/cpu_port.h | 66 |
2 files changed, 710 insertions, 710 deletions
diff --git a/libcpu/sim/win32/cpu_port.c b/libcpu/sim/win32/cpu_port.c index 5969d2e8d1..38c387b196 100644 --- a/libcpu/sim/win32/cpu_port.c +++ b/libcpu/sim/win32/cpu_port.c @@ -1,677 +1,677 @@ -/*
-************************************************************************************************************************
-* File : cpu_port.c
-* By : xyou
-* Version : V1.00.00
-*
-* By : prife
-* Version : V1.00.01
-************************************************************************************************************************
-*/
-
-/*
-*********************************************************************************************************
-* INCLUDE FILES
-*********************************************************************************************************
-*/
-#include <rtthread.h>
-#include <windows.h>
-#include <mmsystem.h>
-#include <stdio.h>
-#include "cpu_port.h"
-
-/*
-*********************************************************************************************************
-* WinThread STRUCTURE
-* Windows runs each task in a thread.
-* The context switch is managed by the threads.So the task stack does not have to be managed directly,
-* although the stack stack is still used to hold an WinThreadState structure this is the only thing it
-* will be ever hold.
-* the structure indirectly maps the task handle to a thread handle
-*********************************************************************************************************
-*/
-typedef struct
-{
- void *Param; //Thread param
- void (*Entry)(void *); //Thread entry
- void (*Exit)(void); //Thread exit
- HANDLE ThreadHandle;
- DWORD ThreadID;
-}win_thread_t;
-
-const DWORD MS_VC_EXCEPTION=0x406D1388;
-
-#pragma pack(push,8)
-typedef struct tagTHREADNAME_INFO
-{
- DWORD dwType; // Must be 0x1000.
- LPCSTR szName; // Pointer to name (in user addr space).
- DWORD dwThreadID; // Thread ID (-1=caller thread).
- DWORD dwFlags; // Reserved for future use, must be zero.
-} THREADNAME_INFO;
-#pragma pack(pop)
-
-/*
-*********************************************************************************************************
-* LOCAL DEFINES
-*********************************************************************************************************
-*/
-#define MAX_INTERRUPT_NUM ((rt_uint32_t)sizeof(rt_uint32_t) * 8)
-
-/*
- * Simulated interrupt waiting to be processed.this is a bit mask where each bit represent one interrupt
- * so a maximum of 32 interrupts can be simulated
- */
-static volatile rt_uint32_t CpuPendingInterrupts = 0;
-
-/*
- * An event used to inform the simulated interrupt processing thread (a high priority thread
- * that simulated interrupt processing) that an interrupt is pending
- */
-static HANDLE hInterruptEventHandle = NULL;
-
-/*
- * Mutex used to protect all the simulated interrupt variables that are accessed by multiple threads
- */
-static HANDLE hInterruptEventMutex = NULL;
-
-/*
- * Handler for all the simulate software interrupts.
- * The first two positions are used the Yield and Tick interrupt so are handled slightly differently
- * all the other interrupts can be user defined
-*/
-static rt_uint32_t (*CpuIsrHandler[MAX_INTERRUPT_NUM])(void) = {0};
-
-/*
- * Handler for OSTick Thread
- */
-static HANDLE OSTick_Thread;
-static DWORD OSTick_ThreadID;
-static HANDLE OSTick_SignalPtr;
-static TIMECAPS OSTick_TimerCap;
-static MMRESULT OSTick_TimerID;
-
-/*
- * flag in interrupt handling
- */
-rt_uint32_t rt_interrupt_from_thread, rt_interrupt_to_thread;
-rt_uint32_t rt_thread_switch_interrupt_flag;
-
-/*
-*********************************************************************************************************
-* PRIVATE FUNCTION PROTOTYPES
-*********************************************************************************************************
-*/
-//static void WinThreadScheduler(void);
-void WinThreadScheduler(void);
-rt_uint32_t YieldInterruptHandle(void);
-rt_uint32_t SysTickInterruptHandle(void);
-static DWORD WINAPI ThreadforSysTickTimer(LPVOID lpParam);
-static DWORD WINAPI ThreadforKeyGet(LPVOID lpParam);
-
-static void SetThreadName(DWORD dwThreadID, char* threadName)
-{
- THREADNAME_INFO info;
- info.dwType = 0x1000;
- info.szName = threadName;
- info.dwThreadID = dwThreadID;
- info.dwFlags = 0;
-
- __try
- {
- RaiseException( MS_VC_EXCEPTION, 0, sizeof(info)/sizeof(ULONG_PTR), (ULONG_PTR*)&info );
- }
- __except(EXCEPTION_EXECUTE_HANDLER)
- {
- }
-}
-
-/*
-*********************************************************************************************************
-* rt_hw_stack_init()
-* Description : Initialize stack of thread
-* Argument(s) : void *pvEntry,void *pvParam,rt_uint8_t *pStackAddr,void *pvExit
-* Return(s) : rt_uint8_t*
-* Caller(s) : rt_thread_init or rt_thread_create
-* Note(s) : none
-*********************************************************************************************************
-*/
-
-static DWORD WINAPI thread_run( LPVOID lpThreadParameter )
-{
- rt_thread_t tid = rt_thread_self();
- win_thread_t *pWinThread = (win_thread_t *)lpThreadParameter;
-
- SetThreadName(GetCurrentThreadId(), tid->name);
-
- pWinThread->Entry(pWinThread->Param);
-
- pWinThread->Exit();
- return 0;
-}
-
-rt_uint8_t* rt_hw_stack_init(void *pEntry,void *pParam,rt_uint8_t *pStackAddr,void *pExit)
-{
- win_thread_t *pWinThread = NULL;
-
- /*
- * In this simulated case a stack is not initialized
- * The thread handles the context switching itself. The WinThreadState object is placed onto the stack
- * that was created for the task
- * so the stack buffer is still used,just not in the conventional way.
- */
- pWinThread = (win_thread_t *)(pStackAddr - sizeof(win_thread_t));
-
- pWinThread->Entry = pEntry;
- pWinThread->Param = pParam;
- pWinThread->Exit = pExit;
-
- pWinThread->ThreadHandle = NULL;
- pWinThread->ThreadID = 0;
-
- /* Create the winthread */
- pWinThread->ThreadHandle = CreateThread(NULL,
- 0,
- (LPTHREAD_START_ROUTINE) thread_run,
- pWinThread,
- CREATE_SUSPENDED,
- &(pWinThread->ThreadID));
- SetThreadAffinityMask(pWinThread->ThreadHandle,
- 0x01);
- SetThreadPriorityBoost(pWinThread->ThreadHandle,
- TRUE);
- SetThreadPriority(pWinThread->ThreadHandle,
- THREAD_PRIORITY_IDLE);
-
- return (rt_uint8_t*)pWinThread;
-} /*** rt_hw_stack_init ***/
-
-/*
-*********************************************************************************************************
-* rt_hw_interrupt_disable()
-* Description : disable cpu interrupts
-* Argument(s) : void
-* Return(s) : rt_base_t
-* Caller(s) : Applicatios or os_kernel
-* Note(s) : none
-*********************************************************************************************************
-*/
-rt_base_t rt_hw_interrupt_disable(void)
-{
- if(hInterruptEventMutex != NULL)
- {
- WaitForSingleObject(hInterruptEventMutex,INFINITE);
- }
-
- return 0;
-} /*** rt_hw_interrupt_disable ***/
-
-
-/*
-*********************************************************************************************************
-* rt_hw_interrupt_enable()
-* Description : enable cpu interrupts
-* Argument(s) : rt_base_t level
-* Return(s) : void
-* Caller(s) : Applications or os_kernel
-* Note(s) : none
-*********************************************************************************************************
-*/
-void rt_hw_interrupt_enable(rt_base_t level)
-{
- level = level;
-
- if (hInterruptEventMutex != NULL)
- {
- ReleaseMutex(hInterruptEventMutex);
- }
-
-} /*** rt_hw_interrupt_enable ***/
-
-/*
-*********************************************************************************************************
-* rt_hw_context_switch_interrupt()
-* Description : switch thread's contex
-* Argument(s) : void
-* Return(s) : void
-* Caller(s) : os kernel
-* Note(s) : none
-*********************************************************************************************************
-*/
-void rt_hw_context_switch_interrupt(rt_uint32_t from,
- rt_uint32_t to)
-{
- if(rt_thread_switch_interrupt_flag != 1)
- {
- rt_thread_switch_interrupt_flag = 1;
-
- // set rt_interrupt_from_thread
- rt_interrupt_from_thread = *((rt_uint32_t *)(from));
- }
-
- rt_interrupt_to_thread = *((rt_uint32_t *)(to));
-
- //trigger YIELD exception(cause context switch)
- TriggerSimulateInterrupt(CPU_INTERRUPT_YIELD);
-} /*** rt_hw_context_switch_interrupt ***/
-
-
-
-void rt_hw_context_switch(rt_uint32_t from,
- rt_uint32_t to)
-{
- if(rt_thread_switch_interrupt_flag != 1)
- {
- rt_thread_switch_interrupt_flag = 1;
-
- // set rt_interrupt_from_thread
- rt_interrupt_from_thread = *((rt_uint32_t *)(from));
-
- }
-
- // set rt_interrupt_to_thread
- rt_interrupt_to_thread = *((rt_uint32_t *)(to));
-
- //trigger YIELD exception(cause contex switch)
- TriggerSimulateInterrupt(CPU_INTERRUPT_YIELD);
-
-} /*** rt_hw_context_switch ***/
-
-/*
-*********************************************************************************************************
-* rt_hw_context_switch_to()
-* Description : switch to new thread
-* Argument(s) : rt_uint32_t to //the stack address of the thread which will switch to
-* Return(s) : void
-* Caller(s) : rt_thread schecale
-* Note(s) : this function is used to perform the first thread switch
-*********************************************************************************************************
-*/
-void rt_hw_context_switch_to(rt_uint32_t to)
-{
- //set to thread
- rt_interrupt_to_thread = *((rt_uint32_t *)(to));
-
- //clear from thread
- rt_interrupt_from_thread = 0;
-
- //set interrupt to 1
- rt_thread_switch_interrupt_flag = 1;
-
- //start WinThreadScheduler
- WinThreadScheduler();
-
- //never reach here!
- return;
-
-} /*** rt_hw_context_switch_to ***/
-
-
-
-/*
-*********************************************************************************************************
-* TriggerSimulateInterrupt()
-* Description : Trigger a simulated interrupts handle
-* Argument(s) : t_uint32_t IntIndex
-* Return(s) : void
-* Caller(s) : Applications
-* Note(s) : none
-*********************************************************************************************************
-*/
-void TriggerSimulateInterrupt(rt_uint32_t IntIndex)
-{
- if((IntIndex < MAX_INTERRUPT_NUM) && (hInterruptEventMutex != NULL))
- {
- /* Yield interrupts are processed even when critical nesting is non-zero */
- WaitForSingleObject(hInterruptEventMutex,
- INFINITE);
-
- CpuPendingInterrupts |= (1 << IntIndex);
-
- SetEvent(hInterruptEventHandle);
-
- ReleaseMutex(hInterruptEventMutex);
- }
-} /*** TriggerSimulateInterrupt ***/
-
-/*
-*********************************************************************************************************
-* RegisterSimulateInterrupt()
-* Description : Register a interrupt handle to simulate paltform
-* Argument(s) : rt_uint32_t IntIndex,rt_uint32_t (*IntHandler)(void)
-* Return(s) : void
-* Caller(s) : Applications
-* Note(s) : none
-*********************************************************************************************************
-*/
-void RegisterSimulateInterrupt(rt_uint32_t IntIndex,rt_uint32_t (*IntHandler)(void))
-{
- if(IntIndex < MAX_INTERRUPT_NUM)
- {
- if (hInterruptEventMutex != NULL)
- {
- WaitForSingleObject(hInterruptEventMutex,
- INFINITE);
-
- CpuIsrHandler[IntIndex] = IntHandler;
-
- ReleaseMutex(hInterruptEventMutex);
- }
- else
- {
- CpuIsrHandler[IntIndex] = IntHandler;
- }
- }
-
-} /*** RegisterSimulateInterrupt ***/
-
-
-
-/*
-*********************************************************************************************************
-* PRIVATE FUNCTION
-*********************************************************************************************************
-*/
-
-/*
-*********************************************************************************************************
-* WinThreadScheduler()
-* Description : Handle all simulate interrupts
-* Argument(s) : void
-* Return(s) : static void
-* Caller(s) : os scachle
-* Note(s) : none
-*********************************************************************************************************
-*/
-#define WIN_WM_MIN_RES (1)
- void WinThreadScheduler(void)
-{
- HANDLE hInterruptObjectList[2];
- HANDLE hThreadHandle;
- rt_uint32_t SwitchRequiredMask;
- rt_uint32_t i;
-
- win_thread_t *WinThreadFrom;
- win_thread_t *WinThreadTo;
-
- /*
- * Install the interrupt handlers used bye scheduler itself
- */
- RegisterSimulateInterrupt(CPU_INTERRUPT_YIELD,
- YieldInterruptHandle);
- RegisterSimulateInterrupt(CPU_INTERRUPT_TICK,
- SysTickInterruptHandle);
-
- /*
- * Create the events and mutex that are used to synchronise all the WinThreads
- */
- hInterruptEventMutex = CreateMutex(NULL,
- FALSE,
- NULL);
- hInterruptEventHandle = CreateEvent(NULL,
- FALSE,
- FALSE,
- NULL);
-
- if((hInterruptEventMutex == NULL) || (hInterruptEventHandle == NULL))
- {
- return;
- }
-
- /*
- * Set the priority of this WinThread such that it is above the priority of the WinThreads
- * that run rt-threads.
- * This is higher priority is required to ensure simulate interrupts take priority over rt-threads
- */
- hThreadHandle = GetCurrentThread();
- if(hThreadHandle == NULL)
- {
- return;
- }
-
- if (SetThreadPriority(hThreadHandle,
- THREAD_PRIORITY_HIGHEST) == 0)
- {
- return;
- }
- SetThreadPriorityBoost(hThreadHandle,
- TRUE);
- SetThreadAffinityMask(hThreadHandle,
- 0x01);
-
- /*
- * Start the thread that simulates the timer peripheral to generate tick interrupts.
- */
- OSTick_Thread = CreateThread(NULL,
- 0,
- ThreadforSysTickTimer,
- 0,
- CREATE_SUSPENDED,
- &OSTick_ThreadID);
- if(OSTick_Thread == NULL)
- {
- //Display Error Message
-
-
- return;
- }
- SetThreadPriority(OSTick_Thread,
- THREAD_PRIORITY_NORMAL);
- SetThreadPriorityBoost(OSTick_Thread,
- TRUE);
- SetThreadAffinityMask(OSTick_Thread,
- 0x01);
-
- /*
- * Set timer Caps
- */
- if (timeGetDevCaps(&OSTick_TimerCap,
- sizeof(OSTick_TimerCap)) != TIMERR_NOERROR)
- {
-
- CloseHandle(OSTick_Thread);
-
- return;
- }
- if (OSTick_TimerCap.wPeriodMin < WIN_WM_MIN_RES)
- {
- OSTick_TimerCap.wPeriodMin = WIN_WM_MIN_RES;
- }
-
- if(timeBeginPeriod(OSTick_TimerCap.wPeriodMin) != TIMERR_NOERROR)
- {
- CloseHandle(OSTick_Thread);
-
- return;
- }
-
- OSTick_SignalPtr = CreateEvent(NULL,TRUE,FALSE,NULL);
- if(OSTick_SignalPtr == NULL)
- {
- // disp error message
-
- timeEndPeriod(OSTick_TimerCap.wPeriodMin);
- CloseHandle(OSTick_Thread);
-
- return;
- }
-
- OSTick_TimerID = timeSetEvent((UINT ) (1000 / RT_TICK_PER_SECOND) ,
- (UINT ) OSTick_TimerCap.wPeriodMin,
- (LPTIMECALLBACK ) OSTick_SignalPtr,
- (DWORD_PTR ) NULL,
- (UINT ) (TIME_PERIODIC | TIME_CALLBACK_EVENT_SET));
-
- if(OSTick_TimerID == 0)
- {
- //disp
-
- CloseHandle(OSTick_SignalPtr);
- timeEndPeriod(OSTick_TimerCap.wPeriodMin);
- CloseHandle(OSTick_Thread);
-
- return;
- }
-
- /*
- * Start OS Tick Thread an release Interrupt Mutex
- */
- ResumeThread(OSTick_Thread);
- ReleaseMutex( hInterruptEventMutex );
-
- //trigger YEILD INTERRUPT
- TriggerSimulateInterrupt(CPU_INTERRUPT_YIELD);
-
- /*
- * block on the mutex that ensure exclusive access to the simulated interrupt objects
- * and the events that signals that a simulated interrupt should be processed.
- */
-
- hInterruptObjectList[0] = hInterruptEventHandle;
- hInterruptObjectList[1] = hInterruptEventMutex;
-
-
- while (1)
- {
- WaitForMultipleObjects(sizeof(hInterruptObjectList) / sizeof(HANDLE),
- hInterruptObjectList,
- TRUE,
- INFINITE);
-
- /*
- * Used to indicate whether the simulate interrupt processing has necessitated a contex
- * switch to another thread
- */
- SwitchRequiredMask = 0;
-
- /*
- * For each interrupt we are interested in processing ,each of which is represented
- * by a bit in the 32bit CpuPendingInterrupts variable.
- */
- for (i = 0; i < MAX_INTERRUPT_NUM; ++i)
- {
- /* is the simulated interrupt pending ? */
- if (CpuPendingInterrupts & (1UL << i))
- {
- /* Is a handler installed ?*/
- if (CpuIsrHandler[i] != NULL)
- {
- /* Run the actual handler */
- if (CpuIsrHandler[i]() != 0)
- {
- SwitchRequiredMask |= (1UL << i);
- }
- }
-
- /* Clear the interrupt pending bit */
- CpuPendingInterrupts &= ~(1UL << i);
- }
- }
-
- if(SwitchRequiredMask != 0)
- {
- WinThreadFrom = (win_thread_t *)rt_interrupt_from_thread;
- WinThreadTo = (win_thread_t *)rt_interrupt_to_thread;
-
- if ((WinThreadFrom != NULL) && (WinThreadFrom->ThreadHandle != NULL))
- {
- SuspendThread(WinThreadFrom->ThreadHandle);
- }
-
- ResumeThread(WinThreadTo->ThreadHandle);
-
- }
-
- ReleaseMutex(hInterruptEventMutex);
- }
-} /*** WinThreadScheduler ***/
-
-
-
-/*
-*********************************************************************************************************
-* ThreadforSysTickTimer()
-* Description : win thread to simulate a systick timer
-* Argument(s) : LPVOID lpParam
-* Return(s) : static DWORD WINAPI
-* Caller(s) : none
-* Note(s) : This is not a real time way of generating tick events as the next wake time should be relative
-* to the previous wake time,not the time Sleep() is called.
-* It is done this way to prevent overruns in this very non real time simulated/emulated environment
-*********************************************************************************************************
-*/
-static DWORD WINAPI ThreadforSysTickTimer(LPVOID lpParam)
-{
-
- (void)lpParam; //prevent compiler warnings
-
- for(;;)
- {
- /*
- * Wait until the timer expires and we can access the simulated interrupt variables.
- */
- WaitForSingleObject(OSTick_SignalPtr,INFINITE);
-
- ResetEvent(OSTick_SignalPtr);
-
- /*
- * Trigger a systick interrupt
- */
- TriggerSimulateInterrupt(CPU_INTERRUPT_TICK);
-
- }
-
- return 0;
-
-} /*** prvThreadforSysTickTimer ***/
-
-/*
-*********************************************************************************************************
-* SysTickInterruptHandle()
-* Description : Interrupt handle for systick
-* Argument(s) : void
-* Return(s) : rt_uint32_t
-* Caller(s) : none
-* Note(s) : none
-*********************************************************************************************************
-*/
-rt_uint32_t SysTickInterruptHandle(void)
-{
-
- /* enter interrupt */
- rt_interrupt_enter();
-
- rt_tick_increase();
-
- /* leave interrupt */
- rt_interrupt_leave();
-
- return 0;
-} /*** SysTickInterruptHandle ***/
-
-/*
-*********************************************************************************************************
-* YieldInterruptHandle()
-* Description : Interrupt handle for Yield
-* Argument(s) : void
-* Return(s) : rt_uint32_t
-* Caller(s) : none
-* Note(s) : none
-*********************************************************************************************************
-*/
-rt_uint32_t YieldInterruptHandle(void)
-{
-
- /*
- * if rt_thread_switch_interrupt_flag = 1 yield already handled
- */
- if(rt_thread_switch_interrupt_flag != 0)
- {
- rt_thread_switch_interrupt_flag = 0;
-
- /* return thread switch request = 1 */
- return 1;
- }
-
- return 0;
-} /*** YieldInterruptHandle ***/
+/* +************************************************************************************************************************ +* File : cpu_port.c +* By : xyou +* Version : V1.00.00 +* +* By : prife +* Version : V1.00.01 +************************************************************************************************************************ +*/ + +/* +********************************************************************************************************* +* INCLUDE FILES +********************************************************************************************************* +*/ +#include <rtthread.h> +#include <windows.h> +#include <mmsystem.h> +#include <stdio.h> +#include "cpu_port.h" + +/* +********************************************************************************************************* +* WinThread STRUCTURE +* Windows runs each task in a thread. +* The context switch is managed by the threads.So the task stack does not have to be managed directly, +* although the stack stack is still used to hold an WinThreadState structure this is the only thing it +* will be ever hold. +* the structure indirectly maps the task handle to a thread handle +********************************************************************************************************* +*/ +typedef struct +{ + void *Param; //Thread param + void (*Entry)(void *); //Thread entry + void (*Exit)(void); //Thread exit + HANDLE ThreadHandle; + DWORD ThreadID; +}win_thread_t; + +const DWORD MS_VC_EXCEPTION=0x406D1388; + +#pragma pack(push,8) +typedef struct tagTHREADNAME_INFO +{ + DWORD dwType; // Must be 0x1000. + LPCSTR szName; // Pointer to name (in user addr space). + DWORD dwThreadID; // Thread ID (-1=caller thread). + DWORD dwFlags; // Reserved for future use, must be zero. +} THREADNAME_INFO; +#pragma pack(pop) + +/* +********************************************************************************************************* +* LOCAL DEFINES +********************************************************************************************************* +*/ +#define MAX_INTERRUPT_NUM ((rt_uint32_t)sizeof(rt_uint32_t) * 8) + +/* + * Simulated interrupt waiting to be processed.this is a bit mask where each bit represent one interrupt + * so a maximum of 32 interrupts can be simulated + */ +static volatile rt_uint32_t CpuPendingInterrupts = 0; + +/* + * An event used to inform the simulated interrupt processing thread (a high priority thread + * that simulated interrupt processing) that an interrupt is pending + */ +static HANDLE hInterruptEventHandle = NULL; + +/* + * Mutex used to protect all the simulated interrupt variables that are accessed by multiple threads + */ +static HANDLE hInterruptEventMutex = NULL; + +/* + * Handler for all the simulate software interrupts. + * The first two positions are used the Yield and Tick interrupt so are handled slightly differently + * all the other interrupts can be user defined +*/ +static rt_uint32_t (*CpuIsrHandler[MAX_INTERRUPT_NUM])(void) = {0}; + +/* + * Handler for OSTick Thread + */ +static HANDLE OSTick_Thread; +static DWORD OSTick_ThreadID; +static HANDLE OSTick_SignalPtr; +static TIMECAPS OSTick_TimerCap; +static MMRESULT OSTick_TimerID; + +/* + * flag in interrupt handling + */ +rt_uint32_t rt_interrupt_from_thread, rt_interrupt_to_thread; +rt_uint32_t rt_thread_switch_interrupt_flag; + +/* +********************************************************************************************************* +* PRIVATE FUNCTION PROTOTYPES +********************************************************************************************************* +*/ +//static void WinThreadScheduler(void); +void WinThreadScheduler(void); +rt_uint32_t YieldInterruptHandle(void); +rt_uint32_t SysTickInterruptHandle(void); +static DWORD WINAPI ThreadforSysTickTimer(LPVOID lpParam); +static DWORD WINAPI ThreadforKeyGet(LPVOID lpParam); + +static void SetThreadName(DWORD dwThreadID, char* threadName) +{ + THREADNAME_INFO info; + info.dwType = 0x1000; + info.szName = threadName; + info.dwThreadID = dwThreadID; + info.dwFlags = 0; + + __try + { + RaiseException( MS_VC_EXCEPTION, 0, sizeof(info)/sizeof(ULONG_PTR), (ULONG_PTR*)&info ); + } + __except(EXCEPTION_EXECUTE_HANDLER) + { + } +} + +/* +********************************************************************************************************* +* rt_hw_stack_init() +* Description : Initialize stack of thread +* Argument(s) : void *pvEntry,void *pvParam,rt_uint8_t *pStackAddr,void *pvExit +* Return(s) : rt_uint8_t* +* Caller(s) : rt_thread_init or rt_thread_create +* Note(s) : none +********************************************************************************************************* +*/ + +static DWORD WINAPI thread_run( LPVOID lpThreadParameter ) +{ + rt_thread_t tid = rt_thread_self(); + win_thread_t *pWinThread = (win_thread_t *)lpThreadParameter; + + SetThreadName(GetCurrentThreadId(), tid->name); + + pWinThread->Entry(pWinThread->Param); + + pWinThread->Exit(); + return 0; +} + +rt_uint8_t* rt_hw_stack_init(void *pEntry,void *pParam,rt_uint8_t *pStackAddr,void *pExit) +{ + win_thread_t *pWinThread = NULL; + + /* + * In this simulated case a stack is not initialized + * The thread handles the context switching itself. The WinThreadState object is placed onto the stack + * that was created for the task + * so the stack buffer is still used,just not in the conventional way. + */ + pWinThread = (win_thread_t *)(pStackAddr - sizeof(win_thread_t)); + + pWinThread->Entry = pEntry; + pWinThread->Param = pParam; + pWinThread->Exit = pExit; + + pWinThread->ThreadHandle = NULL; + pWinThread->ThreadID = 0; + + /* Create the winthread */ + pWinThread->ThreadHandle = CreateThread(NULL, + 0, + (LPTHREAD_START_ROUTINE) thread_run, + pWinThread, + CREATE_SUSPENDED, + &(pWinThread->ThreadID)); + SetThreadAffinityMask(pWinThread->ThreadHandle, + 0x01); + SetThreadPriorityBoost(pWinThread->ThreadHandle, + TRUE); + SetThreadPriority(pWinThread->ThreadHandle, + THREAD_PRIORITY_IDLE); + + return (rt_uint8_t*)pWinThread; +} /*** rt_hw_stack_init ***/ + +/* +********************************************************************************************************* +* rt_hw_interrupt_disable() +* Description : disable cpu interrupts +* Argument(s) : void +* Return(s) : rt_base_t +* Caller(s) : Applicatios or os_kernel +* Note(s) : none +********************************************************************************************************* +*/ +rt_base_t rt_hw_interrupt_disable(void) +{ + if(hInterruptEventMutex != NULL) + { + WaitForSingleObject(hInterruptEventMutex,INFINITE); + } + + return 0; +} /*** rt_hw_interrupt_disable ***/ + + +/* +********************************************************************************************************* +* rt_hw_interrupt_enable() +* Description : enable cpu interrupts +* Argument(s) : rt_base_t level +* Return(s) : void +* Caller(s) : Applications or os_kernel +* Note(s) : none +********************************************************************************************************* +*/ +void rt_hw_interrupt_enable(rt_base_t level) +{ + level = level; + + if (hInterruptEventMutex != NULL) + { + ReleaseMutex(hInterruptEventMutex); + } + +} /*** rt_hw_interrupt_enable ***/ + +/* +********************************************************************************************************* +* rt_hw_context_switch_interrupt() +* Description : switch thread's contex +* Argument(s) : void +* Return(s) : void +* Caller(s) : os kernel +* Note(s) : none +********************************************************************************************************* +*/ +void rt_hw_context_switch_interrupt(rt_uint32_t from, + rt_uint32_t to) +{ + if(rt_thread_switch_interrupt_flag != 1) + { + rt_thread_switch_interrupt_flag = 1; + + // set rt_interrupt_from_thread + rt_interrupt_from_thread = *((rt_uint32_t *)(from)); + } + + rt_interrupt_to_thread = *((rt_uint32_t *)(to)); + + //trigger YIELD exception(cause context switch) + TriggerSimulateInterrupt(CPU_INTERRUPT_YIELD); +} /*** rt_hw_context_switch_interrupt ***/ + + + +void rt_hw_context_switch(rt_uint32_t from, + rt_uint32_t to) +{ + if(rt_thread_switch_interrupt_flag != 1) + { + rt_thread_switch_interrupt_flag = 1; + + // set rt_interrupt_from_thread + rt_interrupt_from_thread = *((rt_uint32_t *)(from)); + + } + + // set rt_interrupt_to_thread + rt_interrupt_to_thread = *((rt_uint32_t *)(to)); + + //trigger YIELD exception(cause contex switch) + TriggerSimulateInterrupt(CPU_INTERRUPT_YIELD); + +} /*** rt_hw_context_switch ***/ + +/* +********************************************************************************************************* +* rt_hw_context_switch_to() +* Description : switch to new thread +* Argument(s) : rt_uint32_t to //the stack address of the thread which will switch to +* Return(s) : void +* Caller(s) : rt_thread schecale +* Note(s) : this function is used to perform the first thread switch +********************************************************************************************************* +*/ +void rt_hw_context_switch_to(rt_uint32_t to) +{ + //set to thread + rt_interrupt_to_thread = *((rt_uint32_t *)(to)); + + //clear from thread + rt_interrupt_from_thread = 0; + + //set interrupt to 1 + rt_thread_switch_interrupt_flag = 1; + + //start WinThreadScheduler + WinThreadScheduler(); + + //never reach here! + return; + +} /*** rt_hw_context_switch_to ***/ + + + +/* +********************************************************************************************************* +* TriggerSimulateInterrupt() +* Description : Trigger a simulated interrupts handle +* Argument(s) : t_uint32_t IntIndex +* Return(s) : void +* Caller(s) : Applications +* Note(s) : none +********************************************************************************************************* +*/ +void TriggerSimulateInterrupt(rt_uint32_t IntIndex) +{ + if((IntIndex < MAX_INTERRUPT_NUM) && (hInterruptEventMutex != NULL)) + { + /* Yield interrupts are processed even when critical nesting is non-zero */ + WaitForSingleObject(hInterruptEventMutex, + INFINITE); + + CpuPendingInterrupts |= (1 << IntIndex); + + SetEvent(hInterruptEventHandle); + + ReleaseMutex(hInterruptEventMutex); + } +} /*** TriggerSimulateInterrupt ***/ + +/* +********************************************************************************************************* +* RegisterSimulateInterrupt() +* Description : Register a interrupt handle to simulate paltform +* Argument(s) : rt_uint32_t IntIndex,rt_uint32_t (*IntHandler)(void) +* Return(s) : void +* Caller(s) : Applications +* Note(s) : none +********************************************************************************************************* +*/ +void RegisterSimulateInterrupt(rt_uint32_t IntIndex,rt_uint32_t (*IntHandler)(void)) +{ + if(IntIndex < MAX_INTERRUPT_NUM) + { + if (hInterruptEventMutex != NULL) + { + WaitForSingleObject(hInterruptEventMutex, + INFINITE); + + CpuIsrHandler[IntIndex] = IntHandler; + + ReleaseMutex(hInterruptEventMutex); + } + else + { + CpuIsrHandler[IntIndex] = IntHandler; + } + } + +} /*** RegisterSimulateInterrupt ***/ + + + +/* +********************************************************************************************************* +* PRIVATE FUNCTION +********************************************************************************************************* +*/ + +/* +********************************************************************************************************* +* WinThreadScheduler() +* Description : Handle all simulate interrupts +* Argument(s) : void +* Return(s) : static void +* Caller(s) : os scachle +* Note(s) : none +********************************************************************************************************* +*/ +#define WIN_WM_MIN_RES (1) + void WinThreadScheduler(void) +{ + HANDLE hInterruptObjectList[2]; + HANDLE hThreadHandle; + rt_uint32_t SwitchRequiredMask; + rt_uint32_t i; + + win_thread_t *WinThreadFrom; + win_thread_t *WinThreadTo; + + /* + * Install the interrupt handlers used bye scheduler itself + */ + RegisterSimulateInterrupt(CPU_INTERRUPT_YIELD, + YieldInterruptHandle); + RegisterSimulateInterrupt(CPU_INTERRUPT_TICK, + SysTickInterruptHandle); + + /* + * Create the events and mutex that are used to synchronise all the WinThreads + */ + hInterruptEventMutex = CreateMutex(NULL, + FALSE, + NULL); + hInterruptEventHandle = CreateEvent(NULL, + FALSE, + FALSE, + NULL); + + if((hInterruptEventMutex == NULL) || (hInterruptEventHandle == NULL)) + { + return; + } + + /* + * Set the priority of this WinThread such that it is above the priority of the WinThreads + * that run rt-threads. + * This is higher priority is required to ensure simulate interrupts take priority over rt-threads + */ + hThreadHandle = GetCurrentThread(); + if(hThreadHandle == NULL) + { + return; + } + + if (SetThreadPriority(hThreadHandle, + THREAD_PRIORITY_HIGHEST) == 0) + { + return; + } + SetThreadPriorityBoost(hThreadHandle, + TRUE); + SetThreadAffinityMask(hThreadHandle, + 0x01); + + /* + * Start the thread that simulates the timer peripheral to generate tick interrupts. + */ + OSTick_Thread = CreateThread(NULL, + 0, + ThreadforSysTickTimer, + 0, + CREATE_SUSPENDED, + &OSTick_ThreadID); + if(OSTick_Thread == NULL) + { + //Display Error Message + + + return; + } + SetThreadPriority(OSTick_Thread, + THREAD_PRIORITY_NORMAL); + SetThreadPriorityBoost(OSTick_Thread, + TRUE); + SetThreadAffinityMask(OSTick_Thread, + 0x01); + + /* + * Set timer Caps + */ + if (timeGetDevCaps(&OSTick_TimerCap, + sizeof(OSTick_TimerCap)) != TIMERR_NOERROR) + { + + CloseHandle(OSTick_Thread); + + return; + } + if (OSTick_TimerCap.wPeriodMin < WIN_WM_MIN_RES) + { + OSTick_TimerCap.wPeriodMin = WIN_WM_MIN_RES; + } + + if(timeBeginPeriod(OSTick_TimerCap.wPeriodMin) != TIMERR_NOERROR) + { + CloseHandle(OSTick_Thread); + + return; + } + + OSTick_SignalPtr = CreateEvent(NULL,TRUE,FALSE,NULL); + if(OSTick_SignalPtr == NULL) + { + // disp error message + + timeEndPeriod(OSTick_TimerCap.wPeriodMin); + CloseHandle(OSTick_Thread); + + return; + } + + OSTick_TimerID = timeSetEvent((UINT ) (1000 / RT_TICK_PER_SECOND) , + (UINT ) OSTick_TimerCap.wPeriodMin, + (LPTIMECALLBACK ) OSTick_SignalPtr, + (DWORD_PTR ) NULL, + (UINT ) (TIME_PERIODIC | TIME_CALLBACK_EVENT_SET)); + + if(OSTick_TimerID == 0) + { + //disp + + CloseHandle(OSTick_SignalPtr); + timeEndPeriod(OSTick_TimerCap.wPeriodMin); + CloseHandle(OSTick_Thread); + + return; + } + + /* + * Start OS Tick Thread an release Interrupt Mutex + */ + ResumeThread(OSTick_Thread); + ReleaseMutex( hInterruptEventMutex ); + + //trigger YEILD INTERRUPT + TriggerSimulateInterrupt(CPU_INTERRUPT_YIELD); + + /* + * block on the mutex that ensure exclusive access to the simulated interrupt objects + * and the events that signals that a simulated interrupt should be processed. + */ + + hInterruptObjectList[0] = hInterruptEventHandle; + hInterruptObjectList[1] = hInterruptEventMutex; + + + while (1) + { + WaitForMultipleObjects(sizeof(hInterruptObjectList) / sizeof(HANDLE), + hInterruptObjectList, + TRUE, + INFINITE); + + /* + * Used to indicate whether the simulate interrupt processing has necessitated a contex + * switch to another thread + */ + SwitchRequiredMask = 0; + + /* + * For each interrupt we are interested in processing ,each of which is represented + * by a bit in the 32bit CpuPendingInterrupts variable. + */ + for (i = 0; i < MAX_INTERRUPT_NUM; ++i) + { + /* is the simulated interrupt pending ? */ + if (CpuPendingInterrupts & (1UL << i)) + { + /* Is a handler installed ?*/ + if (CpuIsrHandler[i] != NULL) + { + /* Run the actual handler */ + if (CpuIsrHandler[i]() != 0) + { + SwitchRequiredMask |= (1UL << i); + } + } + + /* Clear the interrupt pending bit */ + CpuPendingInterrupts &= ~(1UL << i); + } + } + + if(SwitchRequiredMask != 0) + { + WinThreadFrom = (win_thread_t *)rt_interrupt_from_thread; + WinThreadTo = (win_thread_t *)rt_interrupt_to_thread; + + if ((WinThreadFrom != NULL) && (WinThreadFrom->ThreadHandle != NULL)) + { + SuspendThread(WinThreadFrom->ThreadHandle); + } + + ResumeThread(WinThreadTo->ThreadHandle); + + } + + ReleaseMutex(hInterruptEventMutex); + } +} /*** WinThreadScheduler ***/ + + + +/* +********************************************************************************************************* +* ThreadforSysTickTimer() +* Description : win thread to simulate a systick timer +* Argument(s) : LPVOID lpParam +* Return(s) : static DWORD WINAPI +* Caller(s) : none +* Note(s) : This is not a real time way of generating tick events as the next wake time should be relative +* to the previous wake time,not the time Sleep() is called. +* It is done this way to prevent overruns in this very non real time simulated/emulated environment +********************************************************************************************************* +*/ +static DWORD WINAPI ThreadforSysTickTimer(LPVOID lpParam) +{ + + (void)lpParam; //prevent compiler warnings + + for(;;) + { + /* + * Wait until the timer expires and we can access the simulated interrupt variables. + */ + WaitForSingleObject(OSTick_SignalPtr,INFINITE); + + ResetEvent(OSTick_SignalPtr); + + /* + * Trigger a systick interrupt + */ + TriggerSimulateInterrupt(CPU_INTERRUPT_TICK); + + } + + return 0; + +} /*** prvThreadforSysTickTimer ***/ + +/* +********************************************************************************************************* +* SysTickInterruptHandle() +* Description : Interrupt handle for systick +* Argument(s) : void +* Return(s) : rt_uint32_t +* Caller(s) : none +* Note(s) : none +********************************************************************************************************* +*/ +rt_uint32_t SysTickInterruptHandle(void) +{ + + /* enter interrupt */ + rt_interrupt_enter(); + + rt_tick_increase(); + + /* leave interrupt */ + rt_interrupt_leave(); + + return 0; +} /*** SysTickInterruptHandle ***/ + +/* +********************************************************************************************************* +* YieldInterruptHandle() +* Description : Interrupt handle for Yield +* Argument(s) : void +* Return(s) : rt_uint32_t +* Caller(s) : none +* Note(s) : none +********************************************************************************************************* +*/ +rt_uint32_t YieldInterruptHandle(void) +{ + + /* + * if rt_thread_switch_interrupt_flag = 1 yield already handled + */ + if(rt_thread_switch_interrupt_flag != 0) + { + rt_thread_switch_interrupt_flag = 0; + + /* return thread switch request = 1 */ + return 1; + } + + return 0; +} /*** YieldInterruptHandle ***/ diff --git a/libcpu/sim/win32/cpu_port.h b/libcpu/sim/win32/cpu_port.h index 9d43d61c6d..8ab8ae23bd 100644 --- a/libcpu/sim/win32/cpu_port.h +++ b/libcpu/sim/win32/cpu_port.h @@ -1,33 +1,33 @@ -/*
-************************************************************************************************************************
-* File : cpu_port.h
-* By : xyou
-* Version : V1.00.00
-************************************************************************************************************************
-*/
-
-
-
-#ifndef _CPU_PORT_H_
-#define _CPU_PORT_H_
-
-
-/*
-*********************************************************************************************************
-* CPU INTERRUPT PRIORITY
-*********************************************************************************************************
-*/
-#define CPU_INTERRUPT_YIELD 0x00
-#define CPU_INTERRUPT_TICK 0x01
-
-
-
-/*
-*********************************************************************************************************
-* FUNCTION PROTOTYPES
-*********************************************************************************************************
-*/
-void TriggerSimulateInterrupt(rt_uint32_t IntIndex);
-
-void WinThreadScheduler(void);
-#endif /* _CPU_PORT_H_ */
+/* +************************************************************************************************************************ +* File : cpu_port.h +* By : xyou +* Version : V1.00.00 +************************************************************************************************************************ +*/ + + + +#ifndef _CPU_PORT_H_ +#define _CPU_PORT_H_ + + +/* +********************************************************************************************************* +* CPU INTERRUPT PRIORITY +********************************************************************************************************* +*/ +#define CPU_INTERRUPT_YIELD 0x00 +#define CPU_INTERRUPT_TICK 0x01 + + + +/* +********************************************************************************************************* +* FUNCTION PROTOTYPES +********************************************************************************************************* +*/ +void TriggerSimulateInterrupt(rt_uint32_t IntIndex); + +void WinThreadScheduler(void); +#endif /* _CPU_PORT_H_ */ |
