updated to 6.0.1 and added additional processors/toolchains
This commit is contained in:
307
ports/win32/vs_2019/src/tx_initialize_low_level.c
Normal file
307
ports/win32/vs_2019/src/tx_initialize_low_level.c
Normal file
@@ -0,0 +1,307 @@
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* Copyright (c) Microsoft Corporation. All rights reserved. */
|
||||
/* */
|
||||
/* This software is licensed under the Microsoft Software License */
|
||||
/* Terms for Microsoft Azure RTOS. Full text of the license can be */
|
||||
/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
|
||||
/* and in the root directory of this software. */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
/** */
|
||||
/** ThreadX Component */
|
||||
/** */
|
||||
/** Initialize */
|
||||
/** */
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
|
||||
|
||||
#define TX_SOURCE_CODE
|
||||
|
||||
|
||||
/* Include necessary system files. */
|
||||
|
||||
#include "tx_api.h"
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <windows.h>
|
||||
|
||||
|
||||
/* Define various Win32 objects used by the ThreadX port. */
|
||||
|
||||
TX_WIN32_CRITICAL_SECTION _tx_win32_critical_section;
|
||||
HANDLE _tx_win32_scheduler_semaphore;
|
||||
DWORD _tx_win32_scheduler_id;
|
||||
ULONG _tx_win32_global_int_disabled_flag;
|
||||
LARGE_INTEGER _tx_win32_time_stamp;
|
||||
ULONG _tx_win32_system_error;
|
||||
extern TX_THREAD *_tx_thread_current_ptr;
|
||||
|
||||
|
||||
/* Define simulated timer interrupt. This is done inside a thread, which is
|
||||
how other interrupts may be defined as well. See code below for an
|
||||
example. */
|
||||
|
||||
HANDLE _tx_win32_timer_handle;
|
||||
DWORD _tx_win32_timer_id;
|
||||
DWORD WINAPI _tx_win32_timer_interrupt(LPVOID p);
|
||||
|
||||
|
||||
#ifdef TX_WIN32_DEBUG_ENABLE
|
||||
|
||||
extern ULONG _tx_thread_system_state;
|
||||
extern UINT _tx_thread_preempt_disable;
|
||||
extern TX_THREAD *_tx_thread_current_ptr;
|
||||
extern TX_THREAD *_tx_thread_execute_ptr;
|
||||
|
||||
|
||||
/* Define the maximum size of the Win32 debug array. */
|
||||
|
||||
#ifndef TX_WIN32_DEBUG_EVENT_SIZE
|
||||
#define TX_WIN32_DEBUG_EVENT_SIZE 400
|
||||
#endif
|
||||
|
||||
|
||||
/* Define debug log in order to debug Win32 issues with this port. */
|
||||
|
||||
typedef struct TX_WIN32_DEBUG_ENTRY_STRUCT
|
||||
{
|
||||
char *tx_win32_debug_entry_action;
|
||||
LARGE_INTEGER tx_win32_debug_entry_timestamp;
|
||||
char *tx_win32_debug_entry_file;
|
||||
unsigned long tx_win32_debug_entry_line;
|
||||
TX_WIN32_CRITICAL_SECTION tx_win32_debug_entry_critical_section;
|
||||
unsigned long tx_win32_debug_entry_int_disabled_flag;
|
||||
ULONG tx_win32_debug_entry_system_state;
|
||||
UINT tx_win32_debug_entry_preempt_disable;
|
||||
TX_THREAD *tx_win32_debug_entry_current_thread;
|
||||
DWORD tx_win32_debug_entry_current_thread_id;
|
||||
TX_THREAD *tx_win32_debug_entry_execute_thread;
|
||||
DWORD tx_win32_debug_entry_execute_thread_id;
|
||||
DWORD tx_win32_debug_entry_running_id;
|
||||
} TX_WIN32_DEBUG_ENTRY;
|
||||
|
||||
|
||||
/* Define the circular array of Win32 debug entries. */
|
||||
|
||||
TX_WIN32_DEBUG_ENTRY _tx_win32_debug_entry_array[TX_WIN32_DEBUG_EVENT_SIZE];
|
||||
|
||||
|
||||
/* Define the Win32 debug index. */
|
||||
|
||||
unsigned long _tx_win32_debug_entry_index = 0;
|
||||
|
||||
|
||||
/* Now define the debug entry function. */
|
||||
void _tx_win32_debug_entry_insert(char *action, char *file, unsigned long line)
|
||||
{
|
||||
|
||||
|
||||
/* Get the time stamp. */
|
||||
QueryPerformanceCounter((LARGE_INTEGER *)&_tx_win32_time_stamp);
|
||||
|
||||
/* Setup the debug entry. */
|
||||
_tx_win32_debug_entry_array[_tx_win32_debug_entry_index].tx_win32_debug_entry_action = action;
|
||||
_tx_win32_debug_entry_array[_tx_win32_debug_entry_index].tx_win32_debug_entry_timestamp = _tx_win32_time_stamp;
|
||||
_tx_win32_debug_entry_array[_tx_win32_debug_entry_index].tx_win32_debug_entry_file = file;
|
||||
_tx_win32_debug_entry_array[_tx_win32_debug_entry_index].tx_win32_debug_entry_line = line;
|
||||
_tx_win32_debug_entry_array[_tx_win32_debug_entry_index].tx_win32_debug_entry_critical_section = _tx_win32_critical_section;
|
||||
_tx_win32_debug_entry_array[_tx_win32_debug_entry_index].tx_win32_debug_entry_int_disabled_flag = _tx_win32_global_int_disabled_flag;
|
||||
_tx_win32_debug_entry_array[_tx_win32_debug_entry_index].tx_win32_debug_entry_system_state = _tx_thread_system_state;
|
||||
_tx_win32_debug_entry_array[_tx_win32_debug_entry_index].tx_win32_debug_entry_preempt_disable = _tx_thread_preempt_disable;
|
||||
_tx_win32_debug_entry_array[_tx_win32_debug_entry_index].tx_win32_debug_entry_current_thread = _tx_thread_current_ptr;
|
||||
if (_tx_thread_current_ptr)
|
||||
_tx_win32_debug_entry_array[_tx_win32_debug_entry_index].tx_win32_debug_entry_current_thread_id = _tx_thread_current_ptr -> tx_thread_win32_thread_id;
|
||||
else
|
||||
_tx_win32_debug_entry_array[_tx_win32_debug_entry_index].tx_win32_debug_entry_current_thread_id = 0;
|
||||
_tx_win32_debug_entry_array[_tx_win32_debug_entry_index].tx_win32_debug_entry_execute_thread = _tx_thread_execute_ptr;
|
||||
if (_tx_thread_execute_ptr)
|
||||
_tx_win32_debug_entry_array[_tx_win32_debug_entry_index].tx_win32_debug_entry_execute_thread_id = _tx_thread_execute_ptr -> tx_thread_win32_thread_id;
|
||||
else
|
||||
_tx_win32_debug_entry_array[_tx_win32_debug_entry_index].tx_win32_debug_entry_execute_thread_id = 0;
|
||||
_tx_win32_debug_entry_array[_tx_win32_debug_entry_index].tx_win32_debug_entry_running_id = GetCurrentThreadId();
|
||||
|
||||
/* Now move to the next entry. */
|
||||
_tx_win32_debug_entry_index++;
|
||||
|
||||
/* Determine if we need to wrap the list. */
|
||||
if (_tx_win32_debug_entry_index >= TX_WIN32_DEBUG_EVENT_SIZE)
|
||||
{
|
||||
|
||||
/* Yes, wrap the list! */
|
||||
_tx_win32_debug_entry_index = 0;
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
/* Define the ThreadX timer interrupt handler. */
|
||||
|
||||
void _tx_timer_interrupt(void);
|
||||
|
||||
|
||||
/* Define other external function references. */
|
||||
|
||||
VOID _tx_initialize_low_level(VOID);
|
||||
VOID _tx_thread_context_save(VOID);
|
||||
VOID _tx_thread_context_restore(VOID);
|
||||
|
||||
|
||||
/* Define other external variable references. */
|
||||
|
||||
extern VOID *_tx_initialize_unused_memory;
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* FUNCTION RELEASE */
|
||||
/* */
|
||||
/* _tx_initialize_low_level Win32/Visual */
|
||||
/* 6.0.1 */
|
||||
/* AUTHOR */
|
||||
/* */
|
||||
/* William E. Lamie, Microsoft Corporation */
|
||||
/* */
|
||||
/* DESCRIPTION */
|
||||
/* */
|
||||
/* This function is responsible for any low-level processor */
|
||||
/* initialization, including setting up interrupt vectors, setting */
|
||||
/* up a periodic timer interrupt source, saving the system stack */
|
||||
/* pointer for use in ISR processing later, and finding the first */
|
||||
/* available RAM memory address for tx_application_define. */
|
||||
/* */
|
||||
/* INPUT */
|
||||
/* */
|
||||
/* None */
|
||||
/* */
|
||||
/* OUTPUT */
|
||||
/* */
|
||||
/* None */
|
||||
/* */
|
||||
/* CALLS */
|
||||
/* */
|
||||
/* CreateMutex Win32 create mutex */
|
||||
/* CreateThread Win32 create thread */
|
||||
/* CreateSemaphore Win32 create semaphore */
|
||||
/* GetCurrentThreadId Win32 get current thread ID */
|
||||
/* SetProcessAffinityMask Win32 process affinity set */
|
||||
/* SetThreadPriority Win32 set thread priority */
|
||||
/* */
|
||||
/* CALLED BY */
|
||||
/* */
|
||||
/* _tx_initialize_kernel_enter ThreadX entry function */
|
||||
/* */
|
||||
/* RELEASE HISTORY */
|
||||
/* */
|
||||
/* DATE NAME DESCRIPTION */
|
||||
/* */
|
||||
/* 06-30-2020 William E. Lamie Initial Version 6.0.1 */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
VOID _tx_initialize_low_level(VOID)
|
||||
{
|
||||
|
||||
/* Deprecate TX_WIN32_MULTI_CORE build option and default to restricting
|
||||
execution to one core. */
|
||||
|
||||
#ifndef TX_WIN32_BYPASS_AFFINITY_SETUP
|
||||
|
||||
/* Limit this ThreadX simulation on Win32 to a single core. */
|
||||
if (SetProcessAffinityMask( GetCurrentProcess(), 1 ) == 0)
|
||||
{
|
||||
|
||||
/* Error restricting the process to one core. */
|
||||
printf("ThreadX Win32 error restricting the process to one core!\n");
|
||||
while(1)
|
||||
{
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Pickup the first available memory address. */
|
||||
|
||||
/* Save the first available memory address. */
|
||||
_tx_initialize_unused_memory = malloc(TX_WIN32_MEMORY_SIZE);
|
||||
|
||||
/* Pickup the unique Id of the current thread, which will also be the Id of the scheduler. */
|
||||
_tx_win32_scheduler_id = GetCurrentThreadId();
|
||||
|
||||
/* Create the system critical section mutex. This is used by the system to block all other access,
|
||||
analogous to an interrupt lockout on an embedded target. */
|
||||
_tx_win32_critical_section.tx_win32_critical_section_mutex_handle = CreateMutex(NULL, FALSE, NULL);
|
||||
_tx_win32_critical_section.tx_win32_critical_section_nested_count = 0;
|
||||
_tx_win32_critical_section.tx_win32_critical_section_owner = 0;
|
||||
|
||||
/* Create the semaphore that regulates when the scheduler executes. */
|
||||
_tx_win32_scheduler_semaphore = CreateSemaphore(NULL, 0, 1, NULL);
|
||||
|
||||
/* Initialize the global interrupt disabled flag. */
|
||||
_tx_win32_global_int_disabled_flag = TX_FALSE;
|
||||
|
||||
/* Setup periodic timer interrupt. */
|
||||
_tx_win32_timer_handle =
|
||||
CreateThread(NULL, 0, _tx_win32_timer_interrupt, (LPVOID) &_tx_win32_timer_handle,CREATE_SUSPENDED, &_tx_win32_timer_id);
|
||||
|
||||
/* Check for a good thread create. */
|
||||
if (!_tx_win32_timer_handle)
|
||||
{
|
||||
|
||||
/* Error creating the timer interrupt. */
|
||||
printf("ThreadX Win32 error creating timer interrupt thread!\n");
|
||||
while(1)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
/* Otherwise, we have a good thread create. Now set the priority to
|
||||
a level lower than the system thread but higher than the application
|
||||
threads. */
|
||||
SetThreadPriority(_tx_win32_timer_handle, THREAD_PRIORITY_BELOW_NORMAL);
|
||||
|
||||
/* Done, return to caller. */
|
||||
}
|
||||
|
||||
|
||||
/* This routine is called after initialization is complete in order to start
|
||||
all interrupt threads. Interrupt threads in addition to the timer may
|
||||
be added to this routine as well. */
|
||||
|
||||
void _tx_initialize_start_interrupts(void)
|
||||
{
|
||||
|
||||
/* Kick the timer thread off to generate the ThreadX periodic interrupt
|
||||
source. */
|
||||
ResumeThread(_tx_win32_timer_handle);
|
||||
}
|
||||
|
||||
|
||||
/* Define the ThreadX system timer interrupt. Other interrupts may be simulated
|
||||
in a similar way. */
|
||||
|
||||
|
||||
DWORD WINAPI _tx_win32_timer_interrupt(LPVOID p)
|
||||
{
|
||||
|
||||
while(1)
|
||||
{
|
||||
|
||||
/* Sleep for the desired time. */
|
||||
Sleep(TX_TIMER_PERIODIC);
|
||||
|
||||
/* Call ThreadX context save for interrupt preparation. */
|
||||
_tx_thread_context_save();
|
||||
|
||||
|
||||
/* Call the ThreadX system timer interrupt processing. */
|
||||
_tx_timer_interrupt();
|
||||
|
||||
/* Call ThreadX context restore for interrupt completion. */
|
||||
_tx_thread_context_restore();
|
||||
}
|
||||
}
|
||||
132
ports/win32/vs_2019/src/tx_thread_context_restore.c
Normal file
132
ports/win32/vs_2019/src/tx_thread_context_restore.c
Normal file
@@ -0,0 +1,132 @@
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* Copyright (c) Microsoft Corporation. All rights reserved. */
|
||||
/* */
|
||||
/* This software is licensed under the Microsoft Software License */
|
||||
/* Terms for Microsoft Azure RTOS. Full text of the license can be */
|
||||
/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
|
||||
/* and in the root directory of this software. */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
/** */
|
||||
/** ThreadX Component */
|
||||
/** */
|
||||
/** Thread */
|
||||
/** */
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
|
||||
|
||||
#define TX_SOURCE_CODE
|
||||
|
||||
|
||||
/* Include necessary system files. */
|
||||
|
||||
#include "tx_api.h"
|
||||
#include "tx_thread.h"
|
||||
#include "tx_timer.h"
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* FUNCTION RELEASE */
|
||||
/* */
|
||||
/* _tx_thread_context_restore Win32/Visual */
|
||||
/* 6.0.1 */
|
||||
/* AUTHOR */
|
||||
/* */
|
||||
/* William E. Lamie, Microsoft Corporation */
|
||||
/* */
|
||||
/* DESCRIPTION */
|
||||
/* */
|
||||
/* This function restores the interrupt context if it is processing a */
|
||||
/* nested interrupt. If not, it returns to the interrupt thread if no */
|
||||
/* preemption is necessary. Otherwise, if preemption is necessary or */
|
||||
/* if no thread was running, the function returns to the scheduler. */
|
||||
/* */
|
||||
/* INPUT */
|
||||
/* */
|
||||
/* None */
|
||||
/* */
|
||||
/* OUTPUT */
|
||||
/* */
|
||||
/* None */
|
||||
/* */
|
||||
/* CALLS */
|
||||
/* */
|
||||
/* ReleaseSemaphore Win32 release semaphore */
|
||||
/* ResumeThread Win32 resume thread */
|
||||
/* _tx_win32_critical_section_obtain Obtain critical section */
|
||||
/* _tx_win32_critical_section_release Release critical section */
|
||||
/* */
|
||||
/* CALLED BY */
|
||||
/* */
|
||||
/* ISRs Interrupt Service Routines */
|
||||
/* */
|
||||
/* RELEASE HISTORY */
|
||||
/* */
|
||||
/* DATE NAME DESCRIPTION */
|
||||
/* */
|
||||
/* 06-30-2020 William E. Lamie Initial Version 6.0.1 */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
VOID _tx_thread_context_restore(VOID)
|
||||
{
|
||||
|
||||
/* Enter critical section to ensure other threads are not playing with
|
||||
the core ThreadX data structures. */
|
||||
_tx_win32_critical_section_obtain(&_tx_win32_critical_section);
|
||||
|
||||
/* Debug entry. */
|
||||
_tx_win32_debug_entry_insert("CONTEXT_RESTORE", __FILE__, __LINE__);
|
||||
|
||||
/* Decrement the nested interrupt count. */
|
||||
_tx_thread_system_state--;
|
||||
|
||||
/* Determine if this is the first nested interrupt and if a ThreadX
|
||||
application thread was running at the time. */
|
||||
if ((!_tx_thread_system_state) && (_tx_thread_current_ptr))
|
||||
{
|
||||
|
||||
/* Yes, this is the first and last interrupt processed. */
|
||||
|
||||
/* Check to see if preemption is required. */
|
||||
if ((_tx_thread_preempt_disable == 0) && (_tx_thread_current_ptr != _tx_thread_execute_ptr))
|
||||
{
|
||||
|
||||
/* Preempt the running application thread. We don't need to suspend the
|
||||
application thread since that is done in the context save processing. */
|
||||
|
||||
/* Indicate that this thread was suspended asynchronously. */
|
||||
_tx_thread_current_ptr -> tx_thread_win32_suspension_type = 1;
|
||||
|
||||
/* Save the remaining time-slice and disable it. */
|
||||
if (_tx_timer_time_slice)
|
||||
{
|
||||
|
||||
_tx_thread_current_ptr -> tx_thread_time_slice = _tx_timer_time_slice;
|
||||
_tx_timer_time_slice = 0;
|
||||
}
|
||||
|
||||
/* Clear the current thread pointer. */
|
||||
_tx_thread_current_ptr = TX_NULL;
|
||||
|
||||
/* Wakeup the system thread by setting the system semaphore. */
|
||||
ReleaseSemaphore(_tx_win32_scheduler_semaphore, 1, NULL);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
/* Since preemption is not required, resume the interrupted thread. */
|
||||
ResumeThread(_tx_thread_current_ptr -> tx_thread_win32_thread_handle);
|
||||
}
|
||||
}
|
||||
|
||||
/* Leave Win32 critical section. */
|
||||
_tx_win32_critical_section_release_all(&_tx_win32_critical_section);
|
||||
}
|
||||
|
||||
113
ports/win32/vs_2019/src/tx_thread_context_save.c
Normal file
113
ports/win32/vs_2019/src/tx_thread_context_save.c
Normal file
@@ -0,0 +1,113 @@
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* Copyright (c) Microsoft Corporation. All rights reserved. */
|
||||
/* */
|
||||
/* This software is licensed under the Microsoft Software License */
|
||||
/* Terms for Microsoft Azure RTOS. Full text of the license can be */
|
||||
/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
|
||||
/* and in the root directory of this software. */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
/** */
|
||||
/** ThreadX Component */
|
||||
/** */
|
||||
/** Thread */
|
||||
/** */
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
|
||||
|
||||
#define TX_SOURCE_CODE
|
||||
|
||||
|
||||
/* Include necessary system files. */
|
||||
|
||||
#include "tx_api.h"
|
||||
#include "tx_thread.h"
|
||||
#include "tx_timer.h"
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* FUNCTION RELEASE */
|
||||
/* */
|
||||
/* _tx_thread_context_save Win32/Visual */
|
||||
/* 6.0.1 */
|
||||
/* AUTHOR */
|
||||
/* */
|
||||
/* William E. Lamie, Microsoft Corporation */
|
||||
/* */
|
||||
/* DESCRIPTION */
|
||||
/* */
|
||||
/* This function saves the context of an executing thread in the */
|
||||
/* beginning of interrupt processing. The function also ensures that */
|
||||
/* the system stack is used upon return to the calling ISR. */
|
||||
/* */
|
||||
/* INPUT */
|
||||
/* */
|
||||
/* None */
|
||||
/* */
|
||||
/* OUTPUT */
|
||||
/* */
|
||||
/* None */
|
||||
/* */
|
||||
/* CALLS */
|
||||
/* */
|
||||
/* SuspendThread Win32 thread suspend */
|
||||
/* _tx_win32_critical_section_obtain Obtain critical section */
|
||||
/* _tx_win32_critical_section_release Release critical section */
|
||||
/* */
|
||||
/* CALLED BY */
|
||||
/* */
|
||||
/* ISRs */
|
||||
/* */
|
||||
/* RELEASE HISTORY */
|
||||
/* */
|
||||
/* DATE NAME DESCRIPTION */
|
||||
/* */
|
||||
/* 06-30-2020 William E. Lamie Initial Version 6.0.1 */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
VOID _tx_thread_context_save(VOID)
|
||||
{
|
||||
|
||||
TX_THREAD *thread_ptr;
|
||||
|
||||
|
||||
/* Enter critical section to ensure other threads are not playing with
|
||||
the core ThreadX data structures. */
|
||||
_tx_win32_critical_section_obtain(&_tx_win32_critical_section);
|
||||
|
||||
/* Debug entry. */
|
||||
_tx_win32_debug_entry_insert("CONTEXT_SAVE", __FILE__, __LINE__);
|
||||
|
||||
/* Pickup the current thread pointer. */
|
||||
thread_ptr = _tx_thread_current_ptr;
|
||||
|
||||
/* If an application thread is running, suspend it to simulate preemption. */
|
||||
if ((thread_ptr) && (_tx_thread_system_state == 0))
|
||||
{
|
||||
|
||||
/* Yes, this is the first interrupt and an application thread is running...
|
||||
suspend it! */
|
||||
|
||||
/* Suspend the thread to simulate preemption. Note that the thread is suspended BEFORE the protection get
|
||||
flag is checked to ensure there is not a race condition between this thread and the update of that flag. */
|
||||
SuspendThread(thread_ptr -> tx_thread_win32_thread_handle);
|
||||
|
||||
/* Debug entry. */
|
||||
_tx_win32_debug_entry_insert("CONTEXT_SAVE-suspend_thread", __FILE__, __LINE__);
|
||||
|
||||
}
|
||||
|
||||
/* Increment the nested interrupt condition. */
|
||||
_tx_thread_system_state++;
|
||||
|
||||
/* Exit Win32 critical section. */
|
||||
_tx_win32_critical_section_release(&_tx_win32_critical_section);
|
||||
}
|
||||
|
||||
213
ports/win32/vs_2019/src/tx_thread_interrupt_control.c
Normal file
213
ports/win32/vs_2019/src/tx_thread_interrupt_control.c
Normal file
@@ -0,0 +1,213 @@
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* Copyright (c) Microsoft Corporation. All rights reserved. */
|
||||
/* */
|
||||
/* This software is licensed under the Microsoft Software License */
|
||||
/* Terms for Microsoft Azure RTOS. Full text of the license can be */
|
||||
/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
|
||||
/* and in the root directory of this software. */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
/** */
|
||||
/** ThreadX Component */
|
||||
/** */
|
||||
/** Thread */
|
||||
/** */
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
|
||||
#define TX_SOURCE_CODE
|
||||
|
||||
|
||||
/* Include necessary system files. */
|
||||
|
||||
#include "tx_api.h"
|
||||
#include "tx_thread.h"
|
||||
|
||||
#include <winbase.h>
|
||||
|
||||
/* Define small routines used for the TX_DISABLE/TX_RESTORE macros. */
|
||||
|
||||
UINT _tx_thread_interrupt_disable(void)
|
||||
{
|
||||
|
||||
UINT previous_value;
|
||||
|
||||
|
||||
previous_value = _tx_thread_interrupt_control(TX_INT_DISABLE);
|
||||
return(previous_value);
|
||||
}
|
||||
|
||||
|
||||
VOID _tx_thread_interrupt_restore(UINT previous_posture)
|
||||
{
|
||||
|
||||
previous_posture = _tx_thread_interrupt_control(previous_posture);
|
||||
}
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* FUNCTION RELEASE */
|
||||
/* */
|
||||
/* _tx_thread_interrupt_control Win32/Visual */
|
||||
/* 6.0.1 */
|
||||
/* AUTHOR */
|
||||
/* */
|
||||
/* William E. Lamie, Microsoft Corporation */
|
||||
/* */
|
||||
/* DESCRIPTION */
|
||||
/* */
|
||||
/* This function is responsible for changing the interrupt lockout */
|
||||
/* posture of the system. */
|
||||
/* */
|
||||
/* INPUT */
|
||||
/* */
|
||||
/* new_posture New interrupt lockout posture */
|
||||
/* */
|
||||
/* OUTPUT */
|
||||
/* */
|
||||
/* old_posture Old interrupt lockout posture */
|
||||
/* */
|
||||
/* CALLS */
|
||||
/* */
|
||||
/* ExitThread Win32 thread exit */
|
||||
/* GetCurrentThread Win32 get current thread */
|
||||
/* GetCurrentThreadId Win32 get current thread ID */
|
||||
/* GetThreadPriority Win32 get thread priority */
|
||||
/* _tx_win32_critical_section_obtain Obtain critical section */
|
||||
/* _tx_win32_critical_section_release Release critical section */
|
||||
/* _tx_win32_critical_section_release_all */
|
||||
/* Release critical section */
|
||||
/* */
|
||||
/* CALLED BY */
|
||||
/* */
|
||||
/* Application Code */
|
||||
/* */
|
||||
/* RELEASE HISTORY */
|
||||
/* */
|
||||
/* DATE NAME DESCRIPTION */
|
||||
/* */
|
||||
/* 06-30-2020 William E. Lamie Initial Version 6.0.1 */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
UINT _tx_thread_interrupt_control(UINT new_posture)
|
||||
{
|
||||
|
||||
UINT old_posture;
|
||||
HANDLE threadhandle;
|
||||
int threadpriority;
|
||||
DWORD threadid;
|
||||
TX_THREAD *thread_ptr;
|
||||
|
||||
|
||||
/* Enter Win32 critical section. */
|
||||
_tx_win32_critical_section_obtain(&_tx_win32_critical_section);
|
||||
|
||||
#ifdef TX_WIN32_DEBUG_ENABLE
|
||||
|
||||
/* Determine if this is a disable or enable request. */
|
||||
if (new_posture == TX_INT_ENABLE)
|
||||
{
|
||||
/* Enable. */
|
||||
_tx_win32_debug_entry_insert("RESTORE", __FILE__, __LINE__);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Disable. */
|
||||
_tx_win32_debug_entry_insert("DISABLE", __FILE__, __LINE__);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Determine if the thread was terminated. */
|
||||
|
||||
/* Pickup the handle of the current thread. */
|
||||
threadhandle = GetCurrentThread();
|
||||
|
||||
/* Pickup the current thread pointer. */
|
||||
thread_ptr = _tx_thread_current_ptr;
|
||||
|
||||
/* Pickup the priority of the current thread. */
|
||||
threadpriority = GetThreadPriority(threadhandle);
|
||||
|
||||
/* Pickup the ID of the current thread. */
|
||||
threadid = GetCurrentThreadId();
|
||||
|
||||
/* Determine if this is a thread (THREAD_PRIORITY_LOWEST) and it does not
|
||||
match the current thread pointer. */
|
||||
if ((threadpriority == THREAD_PRIORITY_LOWEST) &&
|
||||
((!thread_ptr) || (thread_ptr -> tx_thread_win32_thread_id != threadid)))
|
||||
{
|
||||
|
||||
/* This indicates the Win32 thread was actually terminated by ThreadX is only
|
||||
being allowed to run in order to cleanup its resources. */
|
||||
_tx_win32_critical_section_release_all(&_tx_win32_critical_section);
|
||||
|
||||
/* Exit this thread. */
|
||||
ExitThread(0);
|
||||
}
|
||||
|
||||
/* Determine the current interrupt lockout condition. */
|
||||
if (_tx_win32_critical_section.tx_win32_critical_section_nested_count == 1)
|
||||
{
|
||||
|
||||
/* First pass through, interrupts are enabled. */
|
||||
old_posture = TX_INT_ENABLE;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
/* Interrupts are disabled. */
|
||||
old_posture = TX_INT_DISABLE;
|
||||
}
|
||||
|
||||
/* First, determine if this call is from a non-thread. */
|
||||
if (_tx_thread_system_state)
|
||||
{
|
||||
|
||||
/* Determine how to apply the new posture. */
|
||||
if (new_posture == TX_INT_ENABLE)
|
||||
{
|
||||
|
||||
/* Clear the disabled flag. */
|
||||
_tx_win32_global_int_disabled_flag = TX_FALSE;
|
||||
|
||||
/* Determine if the critical section is locked. */
|
||||
_tx_win32_critical_section_release_all(&_tx_win32_critical_section);
|
||||
}
|
||||
else if (new_posture == TX_INT_DISABLE)
|
||||
{
|
||||
|
||||
/* Set the disabled flag. */
|
||||
_tx_win32_global_int_disabled_flag = TX_TRUE;
|
||||
}
|
||||
}
|
||||
else if (thread_ptr)
|
||||
{
|
||||
|
||||
/* Determine how to apply the new posture. */
|
||||
if (new_posture == TX_INT_ENABLE)
|
||||
{
|
||||
|
||||
/* Clear the disabled flag. */
|
||||
_tx_thread_current_ptr -> tx_thread_win32_int_disabled_flag = TX_FALSE;
|
||||
|
||||
/* Determine if the critical section is locked. */
|
||||
_tx_win32_critical_section_release_all(&_tx_win32_critical_section);
|
||||
}
|
||||
else if (new_posture == TX_INT_DISABLE)
|
||||
{
|
||||
|
||||
/* Set the disabled flag. */
|
||||
_tx_thread_current_ptr -> tx_thread_win32_int_disabled_flag = TX_TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
/* Return the previous interrupt disable posture. */
|
||||
return(old_posture);
|
||||
}
|
||||
|
||||
291
ports/win32/vs_2019/src/tx_thread_schedule.c
Normal file
291
ports/win32/vs_2019/src/tx_thread_schedule.c
Normal file
@@ -0,0 +1,291 @@
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* Copyright (c) Microsoft Corporation. All rights reserved. */
|
||||
/* */
|
||||
/* This software is licensed under the Microsoft Software License */
|
||||
/* Terms for Microsoft Azure RTOS. Full text of the license can be */
|
||||
/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
|
||||
/* and in the root directory of this software. */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
/** */
|
||||
/** ThreadX Component */
|
||||
/** */
|
||||
/** Thread */
|
||||
/** */
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
|
||||
|
||||
#define TX_SOURCE_CODE
|
||||
|
||||
|
||||
/* Include necessary system files. */
|
||||
|
||||
#include "tx_api.h"
|
||||
#include "tx_thread.h"
|
||||
#include "tx_timer.h"
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* FUNCTION RELEASE */
|
||||
/* */
|
||||
/* _tx_thread_schedule Win32/Visual */
|
||||
/* 6.0.1 */
|
||||
/* AUTHOR */
|
||||
/* */
|
||||
/* William E. Lamie, Microsoft Corporation */
|
||||
/* */
|
||||
/* DESCRIPTION */
|
||||
/* */
|
||||
/* This function waits for a thread control block pointer to appear in */
|
||||
/* the _tx_thread_execute_ptr variable. Once a thread pointer appears */
|
||||
/* in the variable, the corresponding thread is resumed. */
|
||||
/* */
|
||||
/* INPUT */
|
||||
/* */
|
||||
/* None */
|
||||
/* */
|
||||
/* OUTPUT */
|
||||
/* */
|
||||
/* None */
|
||||
/* */
|
||||
/* CALLS */
|
||||
/* */
|
||||
/* ReleaseSemaphore Win32 release semaphore */
|
||||
/* ResumeThread Win32 resume thread */
|
||||
/* Sleep Win32 thread sleep */
|
||||
/* WaitForSingleObject Win32 wait on a semaphore */
|
||||
/* _tx_win32_critical_section_obtain Obtain critical section */
|
||||
/* _tx_win32_critical_section_release Release critical section */
|
||||
/* */
|
||||
/* CALLED BY */
|
||||
/* */
|
||||
/* _tx_initialize_kernel_enter ThreadX entry function */
|
||||
/* */
|
||||
/* RELEASE HISTORY */
|
||||
/* */
|
||||
/* DATE NAME DESCRIPTION */
|
||||
/* */
|
||||
/* 06-30-2020 William E. Lamie Initial Version 6.0.1 */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
VOID _tx_thread_schedule(VOID)
|
||||
{
|
||||
|
||||
|
||||
/* Loop forever. */
|
||||
while(1)
|
||||
{
|
||||
|
||||
/* Wait for a thread to execute and all ISRs to complete. */
|
||||
while(1)
|
||||
{
|
||||
|
||||
|
||||
/* Enter Win32 critical section. */
|
||||
_tx_win32_critical_section_obtain(&_tx_win32_critical_section);
|
||||
|
||||
/* Debug entry. */
|
||||
_tx_win32_debug_entry_insert("SCHEDULE-wake_up", __FILE__, __LINE__);
|
||||
|
||||
/* Determine if there is a thread ready to execute AND all ISRs
|
||||
are complete. */
|
||||
if ((_tx_thread_execute_ptr != TX_NULL) && (_tx_thread_system_state == 0))
|
||||
{
|
||||
|
||||
/* Get out of this loop and schedule the thread! */
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
/* Leave the critical section. */
|
||||
_tx_win32_critical_section_release(&_tx_win32_critical_section);
|
||||
|
||||
/* Now sleep so we don't block forever. */
|
||||
Sleep(2);
|
||||
}
|
||||
}
|
||||
|
||||
/* Yes! We have a thread to execute. Note that the critical section is already
|
||||
active from the scheduling loop above. */
|
||||
|
||||
/* Setup the current thread pointer. */
|
||||
_tx_thread_current_ptr = _tx_thread_execute_ptr;
|
||||
|
||||
/* Increment the run count for this thread. */
|
||||
_tx_thread_current_ptr -> tx_thread_run_count++;
|
||||
|
||||
/* Setup time-slice, if present. */
|
||||
_tx_timer_time_slice = _tx_thread_current_ptr -> tx_thread_time_slice;
|
||||
|
||||
/* Determine how the thread was suspended. */
|
||||
if (_tx_thread_current_ptr -> tx_thread_win32_suspension_type)
|
||||
{
|
||||
|
||||
/* Debug entry. */
|
||||
_tx_win32_debug_entry_insert("SCHEDULE-resume_thread", __FILE__, __LINE__);
|
||||
|
||||
/* Pseudo interrupt suspension. The thread is not waiting on
|
||||
its run semaphore. */
|
||||
ResumeThread(_tx_thread_current_ptr -> tx_thread_win32_thread_handle);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
/* Debug entry. */
|
||||
_tx_win32_debug_entry_insert("SCHEDULE-release_sem", __FILE__, __LINE__);
|
||||
|
||||
/* Let the thread run again by releasing its run semaphore. */
|
||||
ReleaseSemaphore(_tx_thread_current_ptr -> tx_thread_win32_thread_run_semaphore, 1, NULL);
|
||||
}
|
||||
|
||||
/* Debug entry. */
|
||||
_tx_win32_debug_entry_insert("SCHEDULE-self_suspend_sem", __FILE__, __LINE__);
|
||||
|
||||
/* Exit Win32 critical section. */
|
||||
_tx_win32_critical_section_release(&_tx_win32_critical_section);
|
||||
|
||||
/* Now suspend the main thread so the application thread can run. */
|
||||
WaitForSingleObject(_tx_win32_scheduler_semaphore, INFINITE);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Define the ThreadX Win32 critical section get, release, and release all functions. */
|
||||
|
||||
void _tx_win32_critical_section_obtain(TX_WIN32_CRITICAL_SECTION *critical_section)
|
||||
{
|
||||
|
||||
TX_THREAD *thread_ptr;
|
||||
|
||||
|
||||
/* Is the protection owned? */
|
||||
if (critical_section -> tx_win32_critical_section_owner == GetCurrentThreadId())
|
||||
{
|
||||
|
||||
/* Simply increment the nested counter. */
|
||||
critical_section -> tx_win32_critical_section_nested_count++;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
/* Pickup the current thread pointer. */
|
||||
thread_ptr = _tx_thread_current_ptr;
|
||||
|
||||
/* Get the Win32 critical section. */
|
||||
while (WaitForSingleObject(critical_section -> tx_win32_critical_section_mutex_handle, 3) != WAIT_OBJECT_0)
|
||||
{
|
||||
}
|
||||
|
||||
/* At this point we have the mutex. */
|
||||
|
||||
/* Increment the nesting counter. */
|
||||
critical_section -> tx_win32_critical_section_nested_count = 1;
|
||||
|
||||
/* Remember the owner. */
|
||||
critical_section -> tx_win32_critical_section_owner = GetCurrentThreadId();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void _tx_win32_critical_section_release(TX_WIN32_CRITICAL_SECTION *critical_section)
|
||||
{
|
||||
|
||||
|
||||
/* Ensure the caller is the mutex owner. */
|
||||
if (critical_section -> tx_win32_critical_section_owner == GetCurrentThreadId())
|
||||
{
|
||||
|
||||
/* Determine if there is protection. */
|
||||
if (critical_section -> tx_win32_critical_section_nested_count)
|
||||
{
|
||||
|
||||
/* Decrement the nesting counter. */
|
||||
critical_section -> tx_win32_critical_section_nested_count--;
|
||||
|
||||
/* Determine if the critical section is now being released. */
|
||||
if (critical_section -> tx_win32_critical_section_nested_count == 0)
|
||||
{
|
||||
|
||||
/* Yes, it is being released clear the owner. */
|
||||
critical_section -> tx_win32_critical_section_owner = 0;
|
||||
|
||||
/* Finally, release the mutex. */
|
||||
if (ReleaseMutex(critical_section -> tx_win32_critical_section_mutex_handle) != TX_TRUE)
|
||||
{
|
||||
|
||||
/* Increment the system error counter. */
|
||||
_tx_win32_system_error++;
|
||||
}
|
||||
|
||||
/* Just in case, make sure there the mutex is not owned. */
|
||||
while (ReleaseMutex(critical_section -> tx_win32_critical_section_mutex_handle) == TX_TRUE)
|
||||
{
|
||||
|
||||
/* Increment the system error counter. */
|
||||
_tx_win32_system_error++;
|
||||
}
|
||||
|
||||
/* Sleep for 0, just to relinquish to other ready threads. */
|
||||
Sleep(0);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
/* Increment the system error counter. */
|
||||
_tx_win32_system_error++;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void _tx_win32_critical_section_release_all(TX_WIN32_CRITICAL_SECTION *critical_section)
|
||||
{
|
||||
|
||||
/* Ensure the caller is the mutex owner. */
|
||||
if (critical_section -> tx_win32_critical_section_owner == GetCurrentThreadId())
|
||||
{
|
||||
|
||||
/* Determine if there is protection. */
|
||||
if (critical_section -> tx_win32_critical_section_nested_count)
|
||||
{
|
||||
|
||||
/* Clear the nesting counter. */
|
||||
critical_section -> tx_win32_critical_section_nested_count = 0;
|
||||
|
||||
/* Yes, it is being release clear the owner. */
|
||||
critical_section -> tx_win32_critical_section_owner = 0;
|
||||
|
||||
/* Finally, release the mutex. */
|
||||
if (ReleaseMutex(critical_section -> tx_win32_critical_section_mutex_handle) != TX_TRUE)
|
||||
{
|
||||
|
||||
/* Increment the system error counter. */
|
||||
_tx_win32_system_error++;
|
||||
}
|
||||
|
||||
/* Just in case, make sure there the mutex is not owned. */
|
||||
while (ReleaseMutex(critical_section -> tx_win32_critical_section_mutex_handle) == TX_TRUE)
|
||||
{
|
||||
|
||||
/* Increment the system error counter. */
|
||||
_tx_win32_system_error++;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
/* Increment the system error counter. */
|
||||
_tx_win32_system_error++;
|
||||
}
|
||||
}
|
||||
|
||||
157
ports/win32/vs_2019/src/tx_thread_stack_build.c
Normal file
157
ports/win32/vs_2019/src/tx_thread_stack_build.c
Normal file
@@ -0,0 +1,157 @@
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* Copyright (c) Microsoft Corporation. All rights reserved. */
|
||||
/* */
|
||||
/* This software is licensed under the Microsoft Software License */
|
||||
/* Terms for Microsoft Azure RTOS. Full text of the license can be */
|
||||
/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
|
||||
/* and in the root directory of this software. */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
/** */
|
||||
/** ThreadX Component */
|
||||
/** */
|
||||
/** Thread */
|
||||
/** */
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
|
||||
|
||||
#define TX_SOURCE_CODE
|
||||
|
||||
|
||||
/* Include necessary system files. */
|
||||
|
||||
#include "tx_api.h"
|
||||
#include "tx_thread.h"
|
||||
#include <stdio.h>
|
||||
|
||||
|
||||
/* Prototype for new thread entry function. */
|
||||
|
||||
DWORD WINAPI _tx_win32_thread_entry(LPVOID p);
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* FUNCTION RELEASE */
|
||||
/* */
|
||||
/* _tx_thread_stack_build Win32/Visual */
|
||||
/* 6.0.1 */
|
||||
/* AUTHOR */
|
||||
/* */
|
||||
/* William E. Lamie, Microsoft Corporation */
|
||||
/* */
|
||||
/* DESCRIPTION */
|
||||
/* */
|
||||
/* This function builds a stack frame on the supplied thread's stack. */
|
||||
/* The stack frame results in a fake interrupt return to the supplied */
|
||||
/* function pointer. */
|
||||
/* */
|
||||
/* INPUT */
|
||||
/* */
|
||||
/* thread_ptr Pointer to thread control blk */
|
||||
/* function_ptr Pointer to return function */
|
||||
/* */
|
||||
/* OUTPUT */
|
||||
/* */
|
||||
/* None */
|
||||
/* */
|
||||
/* CALLS */
|
||||
/* */
|
||||
/* CreateThread Win32 create thread */
|
||||
/* ResumeThread Win32 resume thread */
|
||||
/* SetThreadPriority Win32 set thread priority */
|
||||
/* */
|
||||
/* CALLED BY */
|
||||
/* */
|
||||
/* _tx_thread_create Create thread service */
|
||||
/* _tx_thread_reset Reset thread service */
|
||||
/* */
|
||||
/* RELEASE HISTORY */
|
||||
/* */
|
||||
/* DATE NAME DESCRIPTION */
|
||||
/* */
|
||||
/* 06-30-2020 William E. Lamie Initial Version 6.0.1 */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
VOID _tx_thread_stack_build(TX_THREAD *thread_ptr, VOID (*function_ptr)(VOID))
|
||||
{
|
||||
|
||||
/* Create a Win32 thread for the application thread. */
|
||||
thread_ptr -> tx_thread_win32_thread_handle =
|
||||
CreateThread(NULL, 0, _tx_win32_thread_entry, (LPVOID) thread_ptr, CREATE_SUSPENDED,
|
||||
&(thread_ptr -> tx_thread_win32_thread_id));
|
||||
|
||||
/* Check for a good thread create. */
|
||||
if (!thread_ptr -> tx_thread_win32_thread_handle)
|
||||
{
|
||||
|
||||
/* Display an error message. */
|
||||
printf("ThreadX Win32 error creating thread!\n");
|
||||
while(1)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
/* Otherwise, we have a good thread create. Now set the priority to
|
||||
a lower level. */
|
||||
SetThreadPriority(thread_ptr -> tx_thread_win32_thread_handle, THREAD_PRIORITY_LOWEST);
|
||||
|
||||
/* Create the run semaphore for the thread. This will allow the scheduler
|
||||
control over when the thread actually runs. */
|
||||
thread_ptr -> tx_thread_win32_thread_run_semaphore = CreateSemaphore(NULL, 0, 1, NULL);
|
||||
|
||||
/* Determine if the run semaphore was created successfully. */
|
||||
if (!thread_ptr -> tx_thread_win32_thread_run_semaphore)
|
||||
{
|
||||
|
||||
/* Display an error message. */
|
||||
printf("ThreadX Win32 error creating thread running semaphore!\n");
|
||||
while(1)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
/* Setup the thread suspension type to solicited thread suspension.
|
||||
Pseudo interrupt handlers will suspend with this field set to 1. */
|
||||
thread_ptr -> tx_thread_win32_suspension_type = 0;
|
||||
|
||||
/* Clear the disabled count that will keep track of the
|
||||
tx_interrupt_control nesting. */
|
||||
thread_ptr -> tx_thread_win32_int_disabled_flag = 0;
|
||||
|
||||
/* Setup a fake thread stack pointer. */
|
||||
thread_ptr -> tx_thread_stack_ptr = (VOID *) (((CHAR *) thread_ptr -> tx_thread_stack_end) - 8);
|
||||
|
||||
/* Clear the first word of the stack. */
|
||||
*(((ULONG *) thread_ptr -> tx_thread_stack_ptr) - 1) = 0;
|
||||
|
||||
/* Make the thread initially ready so it will run to the initial wait on
|
||||
its run semaphore. */
|
||||
ResumeThread(thread_ptr -> tx_thread_win32_thread_handle);
|
||||
}
|
||||
|
||||
|
||||
DWORD WINAPI _tx_win32_thread_entry(LPVOID ptr)
|
||||
{
|
||||
|
||||
TX_THREAD *thread_ptr;
|
||||
|
||||
/* Pickup the current thread pointer. */
|
||||
thread_ptr = (TX_THREAD *) ptr;
|
||||
|
||||
/* Now suspend the thread initially. If the thread has already
|
||||
been scheduled, this will return immediately. */
|
||||
WaitForSingleObject(thread_ptr -> tx_thread_win32_thread_run_semaphore, INFINITE);
|
||||
|
||||
/* Call ThreadX thread entry point. */
|
||||
_tx_thread_shell_entry();
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
212
ports/win32/vs_2019/src/tx_thread_system_return.c
Normal file
212
ports/win32/vs_2019/src/tx_thread_system_return.c
Normal file
@@ -0,0 +1,212 @@
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* Copyright (c) Microsoft Corporation. All rights reserved. */
|
||||
/* */
|
||||
/* This software is licensed under the Microsoft Software License */
|
||||
/* Terms for Microsoft Azure RTOS. Full text of the license can be */
|
||||
/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
|
||||
/* and in the root directory of this software. */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
/** */
|
||||
/** ThreadX Component */
|
||||
/** */
|
||||
/** Thread */
|
||||
/** */
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
|
||||
#define TX_SOURCE_CODE
|
||||
|
||||
|
||||
/* Include necessary system files. */
|
||||
|
||||
#include "tx_api.h"
|
||||
#include "tx_thread.h"
|
||||
#include "tx_timer.h"
|
||||
#include <stdio.h>
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* FUNCTION RELEASE */
|
||||
/* */
|
||||
/* _tx_thread_system_return Win32/Visual */
|
||||
/* 6.0.1 */
|
||||
/* AUTHOR */
|
||||
/* */
|
||||
/* William E. Lamie, Microsoft Corporation */
|
||||
/* */
|
||||
/* DESCRIPTION */
|
||||
/* */
|
||||
/* This function is target processor specific. It is used to transfer */
|
||||
/* control from a thread back to the system. Only a minimal context */
|
||||
/* is saved since the compiler assumes temp registers are going to get */
|
||||
/* slicked by a function call anyway. */
|
||||
/* */
|
||||
/* INPUT */
|
||||
/* */
|
||||
/* None */
|
||||
/* */
|
||||
/* OUTPUT */
|
||||
/* */
|
||||
/* None */
|
||||
/* */
|
||||
/* CALLS */
|
||||
/* */
|
||||
/* _tx_win32_critical_section_obtain Obtain critical section */
|
||||
/* _tx_win32_critical_section_release Release critical section */
|
||||
/* _tx_win32_critical_section_release_all */
|
||||
/* Release critical section */
|
||||
/* ExitThread Win32 thread exit */
|
||||
/* GetCurrentThread Win32 get current thread */
|
||||
/* GetCurrentThreadId Win32 get current thread ID */
|
||||
/* GetThreadPriority Win32 get thread priority */
|
||||
/* ReleaseSemaphore Win32 release semaphore */
|
||||
/* WaitForSingleObject Win32 wait on semaphore */
|
||||
/* */
|
||||
/* CALLED BY */
|
||||
/* */
|
||||
/* ThreadX components */
|
||||
/* */
|
||||
/* RELEASE HISTORY */
|
||||
/* */
|
||||
/* DATE NAME DESCRIPTION */
|
||||
/* */
|
||||
/* 06-30-2020 William E. Lamie Initial Version 6.0.1 */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
VOID _tx_thread_system_return(VOID)
|
||||
{
|
||||
|
||||
TX_THREAD *temp_thread_ptr;
|
||||
HANDLE temp_run_semaphore;
|
||||
UINT temp_thread_state;
|
||||
HANDLE threadhandle;
|
||||
int threadpriority;
|
||||
DWORD threadid;
|
||||
|
||||
|
||||
/* Enter Win32 critical section. */
|
||||
_tx_win32_critical_section_obtain(&_tx_win32_critical_section);
|
||||
|
||||
/* Pickup the handle of the current thread. */
|
||||
threadhandle = GetCurrentThread();
|
||||
|
||||
/* Debug entry. */
|
||||
_tx_win32_debug_entry_insert("SYSTEM_RETURN", __FILE__, __LINE__);
|
||||
|
||||
/* First, determine if the thread was terminated. */
|
||||
|
||||
/* Pickup the priority of the current thread. */
|
||||
threadpriority = GetThreadPriority(threadhandle);
|
||||
|
||||
/* Pickup the ID of the current thread. */
|
||||
threadid = GetCurrentThreadId();
|
||||
|
||||
/* Pickup the current thread pointer. */
|
||||
temp_thread_ptr = _tx_thread_current_ptr;
|
||||
|
||||
/* Determine if this is a thread (THREAD_PRIORITY_LOWEST) and it does not
|
||||
match the current thread pointer. */
|
||||
if ((threadpriority == THREAD_PRIORITY_LOWEST) &&
|
||||
((!temp_thread_ptr) || (temp_thread_ptr -> tx_thread_win32_thread_id != threadid)))
|
||||
{
|
||||
|
||||
/* This indicates the Win32 thread was actually terminated by ThreadX and is only
|
||||
being allowed to run in order to cleanup its resources. */
|
||||
|
||||
/* Release critical section. */
|
||||
_tx_win32_critical_section_release_all(&_tx_win32_critical_section);
|
||||
|
||||
/* Exit thread. */
|
||||
ExitThread(0);
|
||||
}
|
||||
|
||||
/* Determine if the time-slice is active. */
|
||||
if (_tx_timer_time_slice)
|
||||
{
|
||||
|
||||
/* Preserve current remaining time-slice for the thread and clear the current time-slice. */
|
||||
temp_thread_ptr -> tx_thread_time_slice = _tx_timer_time_slice;
|
||||
_tx_timer_time_slice = 0;
|
||||
}
|
||||
|
||||
/* Save the run semaphore into a temporary variable as well. */
|
||||
temp_run_semaphore = temp_thread_ptr -> tx_thread_win32_thread_run_semaphore;
|
||||
|
||||
/* Pickup the current thread state. */
|
||||
temp_thread_state = temp_thread_ptr -> tx_thread_state;
|
||||
|
||||
/* Setup the suspension type for this thread. */
|
||||
temp_thread_ptr -> tx_thread_win32_suspension_type = 0;
|
||||
|
||||
/* Set the current thread pointer to NULL. */
|
||||
_tx_thread_current_ptr = TX_NULL;
|
||||
|
||||
/* Debug entry. */
|
||||
_tx_win32_debug_entry_insert("SYSTEM_RETURN-release_sem", __FILE__, __LINE__);
|
||||
|
||||
/* Release the semaphore that the main scheduling thread is waiting
|
||||
on. Note that the main scheduling algorithm will take care of
|
||||
setting the current thread pointer to NULL. */
|
||||
ReleaseSemaphore(_tx_win32_scheduler_semaphore, 1, NULL);
|
||||
|
||||
/* Leave Win32 critical section. */
|
||||
_tx_win32_critical_section_release_all(&_tx_win32_critical_section);
|
||||
|
||||
/* Determine if the thread was self-terminating. */
|
||||
if (temp_thread_state == TX_TERMINATED)
|
||||
{
|
||||
|
||||
/* Exit the thread instead of waiting on the semaphore! */
|
||||
ExitThread(0);
|
||||
}
|
||||
|
||||
/* Wait on the run semaphore for this thread. This won't get set again
|
||||
until the thread is scheduled. */
|
||||
WaitForSingleObject(temp_run_semaphore, INFINITE);
|
||||
|
||||
/* Enter Win32 critical section. */
|
||||
_tx_win32_critical_section_obtain(&_tx_win32_critical_section);
|
||||
|
||||
/* Debug entry. */
|
||||
_tx_win32_debug_entry_insert("SYSTEM_RETURN-wake_up", __FILE__, __LINE__);
|
||||
|
||||
/* Determine if the thread was terminated. */
|
||||
|
||||
/* Pickup the current thread pointer. */
|
||||
temp_thread_ptr = _tx_thread_current_ptr;
|
||||
|
||||
/* Determine if this is a thread (THREAD_PRIORITY_LOWEST) and it does not
|
||||
match the current thread pointer. */
|
||||
if ((threadpriority == THREAD_PRIORITY_LOWEST) &&
|
||||
((!temp_thread_ptr) || (temp_thread_ptr -> tx_thread_win32_thread_id != threadid)))
|
||||
{
|
||||
|
||||
/* Leave Win32 critical section. */
|
||||
_tx_win32_critical_section_release_all(&_tx_win32_critical_section);
|
||||
|
||||
/* This indicates the Win32 thread was actually terminated by ThreadX and is only
|
||||
being allowed to run in order to cleanup its resources. */
|
||||
ExitThread(0);
|
||||
}
|
||||
|
||||
/* Now determine if the application thread last had interrupts disabled. */
|
||||
|
||||
/* Debug entry. */
|
||||
_tx_win32_debug_entry_insert("SYSTEM_RETURN-finish", __FILE__, __LINE__);
|
||||
|
||||
/* Determine if this thread had interrupts disabled. */
|
||||
if (!_tx_thread_current_ptr -> tx_thread_win32_int_disabled_flag)
|
||||
{
|
||||
|
||||
/* Leave Win32 critical section. */
|
||||
_tx_win32_critical_section_release(&_tx_win32_critical_section);
|
||||
}
|
||||
}
|
||||
|
||||
153
ports/win32/vs_2019/src/tx_timer_interrupt.c
Normal file
153
ports/win32/vs_2019/src/tx_timer_interrupt.c
Normal file
@@ -0,0 +1,153 @@
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* Copyright (c) Microsoft Corporation. All rights reserved. */
|
||||
/* */
|
||||
/* This software is licensed under the Microsoft Software License */
|
||||
/* Terms for Microsoft Azure RTOS. Full text of the license can be */
|
||||
/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
|
||||
/* and in the root directory of this software. */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
/** */
|
||||
/** ThreadX Component */
|
||||
/** */
|
||||
/** Timer */
|
||||
/** */
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
|
||||
#define TX_SOURCE_CODE
|
||||
|
||||
|
||||
/* Include necessary system files. */
|
||||
|
||||
#include "tx_api.h"
|
||||
#include "tx_timer.h"
|
||||
#include "tx_thread.h"
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* FUNCTION RELEASE */
|
||||
/* */
|
||||
/* _tx_timer_interrupt Win32/Visual */
|
||||
/* 6.0.1 */
|
||||
/* AUTHOR */
|
||||
/* */
|
||||
/* William E. Lamie, Microsoft Corporation */
|
||||
/* */
|
||||
/* DESCRIPTION */
|
||||
/* */
|
||||
/* This function processes the hardware timer interrupt. This */
|
||||
/* processing includes incrementing the system clock and checking for */
|
||||
/* time slice and/or timer expiration. If either is found, the */
|
||||
/* interrupt context save/restore functions are called along with the */
|
||||
/* expiration functions. */
|
||||
/* */
|
||||
/* INPUT */
|
||||
/* */
|
||||
/* None */
|
||||
/* */
|
||||
/* OUTPUT */
|
||||
/* */
|
||||
/* None */
|
||||
/* */
|
||||
/* CALLS */
|
||||
/* */
|
||||
/* _tx_thread_time_slice Time slice interrupted thread */
|
||||
/* _tx_timer_expiration_process Timer expiration processing */
|
||||
/* _tx_win32_critical_section_obtain Obtain critical section */
|
||||
/* _tx_win32_critical_section_release Release critical section */
|
||||
/* */
|
||||
/* CALLED BY */
|
||||
/* */
|
||||
/* interrupt vector */
|
||||
/* */
|
||||
/* RELEASE HISTORY */
|
||||
/* */
|
||||
/* DATE NAME DESCRIPTION */
|
||||
/* */
|
||||
/* 06-30-2020 William E. Lamie Initial Version 6.0.1 */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
VOID _tx_timer_interrupt(VOID)
|
||||
{
|
||||
|
||||
|
||||
/* Enter critical section to ensure other threads are not playing with
|
||||
the core ThreadX data structures. */
|
||||
_tx_win32_critical_section_obtain(&_tx_win32_critical_section);
|
||||
|
||||
/* Debug entry. */
|
||||
_tx_win32_debug_entry_insert("TIMER INTERRUPT", __FILE__, __LINE__);
|
||||
|
||||
/* Increment the system clock. */
|
||||
_tx_timer_system_clock++;
|
||||
|
||||
/* Test for time-slice expiration. */
|
||||
if (_tx_timer_time_slice)
|
||||
{
|
||||
|
||||
/* Decrement the time_slice. */
|
||||
_tx_timer_time_slice--;
|
||||
|
||||
/* Check for expiration. */
|
||||
if (_tx_timer_time_slice == 0)
|
||||
{
|
||||
|
||||
/* Set the time-slice expired flag. */
|
||||
_tx_timer_expired_time_slice = TX_TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
/* Test for timer expiration. */
|
||||
if (*_tx_timer_current_ptr)
|
||||
{
|
||||
|
||||
/* Set expiration flag. */
|
||||
_tx_timer_expired = TX_TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
/* No timer expired, increment the timer pointer. */
|
||||
_tx_timer_current_ptr++;
|
||||
|
||||
/* Check for wrap-around. */
|
||||
if (_tx_timer_current_ptr == _tx_timer_list_end)
|
||||
{
|
||||
|
||||
/* Wrap to beginning of list. */
|
||||
_tx_timer_current_ptr = _tx_timer_list_start;
|
||||
}
|
||||
}
|
||||
|
||||
/* See if anything has expired. */
|
||||
if ((_tx_timer_expired_time_slice) || (_tx_timer_expired))
|
||||
{
|
||||
|
||||
/* Did a timer expire? */
|
||||
if (_tx_timer_expired)
|
||||
{
|
||||
|
||||
/* Process timer expiration. */
|
||||
_tx_timer_expiration_process();
|
||||
}
|
||||
|
||||
/* Did time slice expire? */
|
||||
if (_tx_timer_expired_time_slice)
|
||||
{
|
||||
|
||||
/* Time slice interrupted thread. */
|
||||
_tx_thread_time_slice();
|
||||
}
|
||||
}
|
||||
|
||||
/* Exit Win32 critical section. */
|
||||
_tx_win32_critical_section_release(&_tx_win32_critical_section);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user