updated to 6.0.1 and added additional processors/toolchains

This commit is contained in:
tameraw
2020-07-16 14:32:40 -07:00
parent f8e91d4762
commit 2c35570dc9
1285 changed files with 550383 additions and 50 deletions

View 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();
}
}

View 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);
}

View 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);
}

View 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);
}

View 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++;
}
}

View 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;
}

View 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);
}
}

View 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);
}