add SMP, Modules, and more processor/tools releases

This commit is contained in:
Scott Larson
2020-08-07 16:56:45 -07:00
parent 49e3c27f3f
commit 6f61053f2a
1858 changed files with 617131 additions and 4 deletions

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,188 @@
/**************************************************************************/
/* */
/* 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 */
/** */
/** Module Manager */
/** */
/**************************************************************************/
/**************************************************************************/
/**************************************************************************/
/* */
/* COMPONENT DEFINITION RELEASE */
/* */
/* txm_module_manager_util.h PORTABLE C */
/* 6.0.1 */
/* AUTHOR */
/* */
/* Scott Larson, Microsoft Corporation */
/* */
/* DESCRIPTION */
/* */
/* This file declares prototypes of utility functions used by the */
/* module manager. */
/* */
/* RELEASE HISTORY */
/* */
/* DATE NAME DESCRIPTION */
/* */
/* 06-30-2020 Scott Larson Initial Version 6.0.1 */
/* */
/**************************************************************************/
#ifndef TXM_MODULE_MANAGER_UTIL_H
#define TXM_MODULE_MANAGER_UTIL_H
/* Define utility macros. */
/* Define inside/outside check macros. The _INCLUSIVE/_EXCLUSIVE suffix applies only to range_end. */
#define TXM_MODULE_MANAGER_CHECK_OUTSIDE_RANGE_INCLUSIVE(range_start, range_end, obj_start, obj_size) \
((obj_start) > (ALIGN_TYPE) (range_end) || \
((obj_start) + (obj_size)) <= (ALIGN_TYPE) (range_start))
#define TXM_MODULE_MANAGER_CHECK_OUTSIDE_RANGE_EXCLUSIVE(range_start, range_end, obj_start, obj_size) \
((obj_start) >= (ALIGN_TYPE) (range_end) || \
((obj_start) + (obj_size)) <= (ALIGN_TYPE) (range_start))
#define TXM_MODULE_MANAGER_CHECK_INSIDE_RANGE_INCLUSIVE(range_start, range_end, obj_start, obj_size) \
(((obj_start) >= (ALIGN_TYPE) (range_start)) && \
(((obj_start) + (obj_size)) <= (ALIGN_TYPE) (range_end) + 1))
#define TXM_MODULE_MANAGER_CHECK_INSIDE_RANGE_INCLUSIVE_BYTE(range_start, range_end, byte_ptr) \
(((byte_ptr) >= (ALIGN_TYPE) (range_start)) && \
((byte_ptr) <= (ALIGN_TYPE) (range_end)))
#define TXM_MODULE_MANAGER_CHECK_INSIDE_RANGE_EXCLUSIVE(range_start, range_end, obj_start, obj_size) \
(((obj_start) >= (ALIGN_TYPE) (range_start)) && \
(((obj_start) + (obj_size)) <= (ALIGN_TYPE) (range_end)))
#define TXM_MODULE_MANAGER_CHECK_INSIDE_RANGE_EXCLUSIVE_BYTE(range_start, range_end, byte_ptr) \
(((byte_ptr) >= (ALIGN_TYPE) (range_start)) && \
((byte_ptr) < (ALIGN_TYPE) (range_end)))
/* Define check macros for modules. */
#define TXM_MODULE_MANAGER_CHECK_OUTSIDE_DATA(module_instance, obj_ptr, obj_size) \
TXM_MODULE_MANAGER_CHECK_OUTSIDE_RANGE_INCLUSIVE(module_instance -> txm_module_instance_data_start, \
module_instance -> txm_module_instance_data_end, \
obj_ptr, obj_size)
#define TXM_MODULE_MANAGER_CHECK_OUTSIDE_CODE(module_instance, obj_ptr, obj_size) \
TXM_MODULE_MANAGER_CHECK_OUTSIDE_RANGE_INCLUSIVE(module_instance -> txm_module_instance_code_start, \
module_instance -> txm_module_instance_code_end, \
obj_ptr, obj_size)
#define TXM_MODULE_MANAGER_CHECK_INSIDE_DATA(module_instance, obj_ptr, obj_size) \
TXM_MODULE_MANAGER_CHECK_INSIDE_RANGE_INCLUSIVE(module_instance -> txm_module_instance_data_start, \
module_instance -> txm_module_instance_data_end, \
obj_ptr, obj_size)
#define TXM_MODULE_MANAGER_CHECK_INSIDE_DATA_BYTE(module_instance, byte_ptr) \
TXM_MODULE_MANAGER_CHECK_INSIDE_RANGE_INCLUSIVE_BYTE(module_instance -> txm_module_instance_data_start, \
module_instance -> txm_module_instance_data_end, \
byte_ptr)
#define TXM_MODULE_MANAGER_CHECK_INSIDE_CODE(module_instance, obj_ptr, obj_size) \
TXM_MODULE_MANAGER_CHECK_INSIDE_RANGE_INCLUSIVE(module_instance -> txm_module_instance_code_start, \
module_instance -> txm_module_instance_code_end, \
obj_ptr, obj_size)
#define TXM_MODULE_MANAGER_CHECK_INSIDE_CODE_BYTE(module_instance, byte_ptr) \
TXM_MODULE_MANAGER_CHECK_INSIDE_RANGE_INCLUSIVE_BYTE(module_instance -> txm_module_instance_code_start, \
module_instance -> txm_module_instance_code_end, \
byte_ptr)
#define TXM_MODULE_MANAGER_CHECK_INSIDE_OBJ_POOL(module_instance, obj_ptr, obj_size) \
((_txm_module_manager_object_pool_created == TX_TRUE) && \
TXM_MODULE_MANAGER_CHECK_INSIDE_RANGE_EXCLUSIVE(_txm_module_manager_object_pool.tx_byte_pool_start, \
_txm_module_manager_object_pool.tx_byte_pool_start + _txm_module_manager_object_pool.tx_byte_pool_size, \
obj_ptr, obj_size))
/* Define macros for module. */
#define TXM_MODULE_MANAGER_ENSURE_INSIDE_MODULE(module_instance, obj_ptr, obj_size) \
(TXM_MODULE_MANAGER_CHECK_INSIDE_DATA(module_instance, obj_ptr, obj_size) || \
_txm_module_manager_shared_memory_check_inside(module_instance, (ALIGN_TYPE) obj_ptr, obj_size) || \
TXM_MODULE_MANAGER_CHECK_INSIDE_CODE(module_instance, obj_ptr, obj_size))
#define TXM_MODULE_MANAGER_ENSURE_INSIDE_MODULE_BYTE(module_instance, byte_ptr) \
(TXM_MODULE_MANAGER_CHECK_INSIDE_DATA_BYTE(module_instance, byte_ptr) || \
_txm_module_manager_shared_memory_check_inside_byte(module_instance, (ALIGN_TYPE) byte_ptr) || \
TXM_MODULE_MANAGER_CHECK_INSIDE_CODE_BYTE(module_instance, byte_ptr))
#define TXM_MODULE_MANAGER_ENSURE_INSIDE_MODULE_DATA(module_instance, obj_ptr, obj_size) \
(TXM_MODULE_MANAGER_CHECK_INSIDE_DATA(module_instance, obj_ptr, obj_size) || \
_txm_module_manager_shared_memory_check_inside(module_instance, (ALIGN_TYPE) obj_ptr, obj_size))
#define TXM_MODULE_MANAGER_ENSURE_OUTSIDE_MODULE(module_instance, obj_ptr, obj_size) \
(TXM_MODULE_MANAGER_CHECK_OUTSIDE_DATA(module_instance, obj_ptr, obj_size) && \
_txm_module_manager_shared_memory_check_outside(module_instance, (ALIGN_TYPE) obj_ptr, obj_size) && \
TXM_MODULE_MANAGER_CHECK_OUTSIDE_CODE(module_instance, obj_ptr, obj_size))
#define TXM_MODULE_MANAGER_ENSURE_INSIDE_OBJ_POOL(module_instance, obj_ptr, obj_size) \
(TXM_MODULE_MANAGER_CHECK_INSIDE_OBJ_POOL(module_instance, obj_ptr, obj_size))
/* Define macros for parameter types. */
/* Buffers we read from can be in RW/RO/Shared areas. */
#define TXM_MODULE_MANAGER_PARAM_CHECK_BUFFER_READ(module_instance, buffer_ptr, buffer_size) \
(((void *) (buffer_ptr) == TX_NULL) || \
(TXM_MODULE_MANAGER_ENSURE_INSIDE_MODULE(module_instance, buffer_ptr, buffer_size)))
/* Buffers we write to can only be in RW/Shared areas. */
#define TXM_MODULE_MANAGER_PARAM_CHECK_BUFFER_WRITE(module_instance, buffer_ptr, buffer_size) \
(((void *) (buffer_ptr) == TX_NULL) || \
(TXM_MODULE_MANAGER_ENSURE_INSIDE_MODULE_DATA(module_instance, buffer_ptr, buffer_size)))
/* Kernel objects should be outside the module at the very least. */
#define TXM_MODULE_MANAGER_PARAM_CHECK_OBJECT_FOR_USE(module_instance, obj_ptr, obj_size) \
(((void *) (obj_ptr) == TX_NULL) || \
(TXM_MODULE_MANAGER_ENSURE_OUTSIDE_MODULE(module_instance, obj_ptr, obj_size)))
/* When creating an object, the object must be inside the object pool. */
#define TXM_MODULE_MANAGER_PARAM_CHECK_OBJECT_FOR_CREATION(module_instance, obj_ptr, obj_size) \
(((void *) (obj_ptr) == TX_NULL) || \
(TXM_MODULE_MANAGER_ENSURE_INSIDE_OBJ_POOL(module_instance, obj_ptr, obj_size) && \
(_txm_module_manager_object_size_check(obj_ptr, obj_size) == TX_SUCCESS)))
/* Strings we dereference can be in RW/RO/Shared areas. */
#define TXM_MODULE_MANAGER_PARAM_CHECK_DEREFERENCE_STRING(module_instance, string_ptr) \
(((void *) (string_ptr) == TX_NULL) || \
(TXM_MODULE_MANAGER_ENSURE_INSIDE_MODULE_BYTE(module_instance, string_ptr)))
#define TXM_MODULE_MANAGER_UTIL_MAX_VALUE_OF_TYPE_UNSIGNED(type) ((1ULL << (sizeof(type) * 8)) - 1)
#define TXM_MODULE_MANAGER_UTIL_MATH_ADD_ULONG(augend, addend, result) \
if ((ULONG)-1 - (augend) < (addend)) \
{ \
return(TXM_MODULE_MATH_OVERFLOW); \
} \
else \
{ \
(result) = (augend) + (addend); \
}
/* Define utility functions. */
UINT _txm_module_manager_object_memory_check(TXM_MODULE_INSTANCE *module_instance, ALIGN_TYPE object_ptr, ULONG object_size);
UINT _txm_module_manager_object_size_check(ALIGN_TYPE object_ptr, ULONG object_size);
UINT _txm_module_manager_object_name_compare(CHAR *object_name1, UINT object_name1_length, CHAR *object_name2);
UCHAR _txm_module_manager_created_object_check(TXM_MODULE_INSTANCE *module_instance, void *object_ptr);
UINT _txm_module_manager_util_code_allocation_size_and_alignment_get(TXM_MODULE_PREAMBLE *module_preamble, ULONG *code_alignment_dest, ULONG *code_allocation_size_dest);
#endif

View File

@@ -0,0 +1,79 @@
/**************************************************************************/
/* */
/* 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 */
/** */
/** Module Manager */
/** */
/**************************************************************************/
/**************************************************************************/
/* Include necessary system files. */
#include "tx_api.h"
#include "txm_module.h"
/**************************************************************************/
/* */
/* FUNCTION RELEASE */
/* */
/* _txm_module_manager_application_request PORTABLE C */
/* 6.0.1 */
/* AUTHOR */
/* */
/* Scott Larson, Microsoft Corporation */
/* */
/* DESCRIPTION */
/* */
/* This function processes the application-specific module request. */
/* The entire contents of the request structure is application */
/* specific and thus the processing in this file is left to the */
/* application to define. */
/* */
/* INPUT */
/* */
/* request_id Module request ID */
/* param_1 First parameter */
/* param_2 Second parameter */
/* param_3 Third parameter */
/* */
/* OUTPUT */
/* */
/* status Completion status */
/* */
/* CALLS */
/* */
/* None */
/* */
/* CALLED BY */
/* */
/* _txm_module_manager_kernel_dispatch Kernel dispatch function */
/* */
/* RELEASE HISTORY */
/* */
/* DATE NAME DESCRIPTION */
/* */
/* 06-30-2020 Scott Larson Initial Version 6.0.1 */
/* */
/**************************************************************************/
UINT _txm_module_manager_application_request(ULONG request_id, ALIGN_TYPE param_1, ALIGN_TYPE param_2, ALIGN_TYPE param_3)
{
/* By default, simply return the status of not available. */
return(TX_NOT_AVAILABLE);
}

View File

@@ -0,0 +1,176 @@
/**************************************************************************/
/* */
/* 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 */
/** */
/** Module Manager */
/** */
/**************************************************************************/
/**************************************************************************/
#define TX_SOURCE_CODE
#include "tx_api.h"
#include "tx_queue.h"
#include "tx_thread.h"
#include "txm_module.h"
/**************************************************************************/
/* */
/* FUNCTION RELEASE */
/* */
/* _txm_module_manager_callback_request PORTABLE C */
/* 6.0.1 */
/* AUTHOR */
/* */
/* Scott Larson, Microsoft Corporation */
/* */
/* DESCRIPTION */
/* */
/* This function sends a notification callback function request to */
/* the associated module. */
/* */
/* INPUT */
/* */
/* module_callback_queue Module callback request queue */
/* callback_request Callback request */
/* */
/* OUTPUT */
/* */
/* None */
/* */
/* CALLS */
/* */
/* tx_queue_send Send module callback request */
/* */
/* CALLED BY */
/* */
/* ThreadX */
/* */
/* RELEASE HISTORY */
/* */
/* DATE NAME DESCRIPTION */
/* */
/* 06-30-2020 Scott Larson Initial Version 6.0.1 */
/* */
/**************************************************************************/
VOID _txm_module_manager_callback_request(TX_QUEUE *module_callback_queue, TXM_MODULE_CALLBACK_MESSAGE *callback_message)
{
TX_INTERRUPT_SAVE_AREA
TXM_MODULE_CALLBACK_MESSAGE *queued_message;
UINT enqueued;
UINT found;
UINT status;
/* Lockout interrupts. */
TX_DISABLE
/* Determine if the queue is valid. */
if ((module_callback_queue) && (module_callback_queue -> tx_queue_id == TX_QUEUE_ID))
{
/* Yes, the queue is valid. */
/* Pickup the current callback request in the queue. */
queued_message = (TXM_MODULE_CALLBACK_MESSAGE *) module_callback_queue -> tx_queue_read;
/* Pickup the number of items enqueued. */
enqueued = module_callback_queue -> tx_queue_enqueued;
/* Set the found flag to false. */
found = TX_FALSE;
/* Loop to look for duplicates in the queue. */
while (enqueued != 0)
{
/* Does this entry match the new callback message? */
if ((queued_message -> txm_module_callback_message_application_function == callback_message -> txm_module_callback_message_application_function) &&
(queued_message -> txm_module_callback_message_param_1 == callback_message -> txm_module_callback_message_param_1) &&
(queued_message -> txm_module_callback_message_param_2 == callback_message -> txm_module_callback_message_param_2) &&
(queued_message -> txm_module_callback_message_param_3 == callback_message -> txm_module_callback_message_param_3) &&
(queued_message -> txm_module_callback_message_param_4 == callback_message -> txm_module_callback_message_param_4) &&
(queued_message -> txm_module_callback_message_param_5 == callback_message -> txm_module_callback_message_param_5) &&
(queued_message -> txm_module_callback_message_param_6 == callback_message -> txm_module_callback_message_param_6) &&
(queued_message -> txm_module_callback_message_param_7 == callback_message -> txm_module_callback_message_param_7) &&
(queued_message -> txm_module_callback_message_param_8 == callback_message -> txm_module_callback_message_param_8) &&
(queued_message -> txm_module_callback_message_reserved1 == callback_message -> txm_module_callback_message_reserved1) &&
(queued_message -> txm_module_callback_message_reserved2 == callback_message -> txm_module_callback_message_reserved2))
{
/* Update the activation count in the queued request. */
queued_message -> txm_module_callback_message_activation_count++;
/* Set the found flag to true. */
found = TX_TRUE;
/* Get out of the loop. */
break;
}
/* Decrease the number of messages to examine. */
enqueued--;
/* Move the callback message to the next message. */
queued_message++;
/* Check for wrap? */
if (((ULONG *) queued_message) >= module_callback_queue -> tx_queue_end)
{
/* Yes, set the queued message to the beginning of the queue. */
queued_message = (TXM_MODULE_CALLBACK_MESSAGE *) module_callback_queue -> tx_queue_start;
}
}
/* Restore interrupts. */
TX_RESTORE
/* Determine if we need to send the new callback request. */
if (found == TX_FALSE)
{
/* Yes, send the message. */
status = _tx_queue_send(module_callback_queue, (VOID *) callback_message, TX_NO_WAIT);
/* Determine if an error was detected. */
if (status != TX_SUCCESS)
{
/* Error, increment the error counter and return. */
_txm_module_manager_callback_error_count++;
}
}
/* Increment the total number of callbacks. */
_txm_module_manager_callback_total_count++;
}
else
{
/* Module instance is not valid. */
/* Error, increment the error counter and return. */
_txm_module_manager_callback_error_count++;
/* Restore interrupts. */
TX_RESTORE
}
}

View File

@@ -0,0 +1,133 @@
/**************************************************************************/
/* */
/* 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 */
/** */
/** Module Manager */
/** */
/**************************************************************************/
/**************************************************************************/
#define TX_SOURCE_CODE
#include "tx_api.h"
#include "tx_event_flags.h"
#include "tx_thread.h"
#include "txm_module.h"
#ifndef TX_DISABLE_NOTIFY_CALLBACKS
/**************************************************************************/
/* */
/* FUNCTION RELEASE */
/* */
/* _txm_module_manager_event_flags_notify_trampoline PORTABLE C */
/* 6.0.1 */
/* AUTHOR */
/* */
/* Scott Larson, Microsoft Corporation */
/* */
/* DESCRIPTION */
/* */
/* This function processes the event flags set notification call from */
/* ThreadX. */
/* */
/* INPUT */
/* */
/* group_ptr Event flags group pointer */
/* */
/* OUTPUT */
/* */
/* None */
/* */
/* CALLS */
/* */
/* _txm_module_manager_callback_request Send module callback request */
/* */
/* CALLED BY */
/* */
/* ThreadX */
/* */
/* RELEASE HISTORY */
/* */
/* DATE NAME DESCRIPTION */
/* */
/* 06-30-2020 Scott Larson Initial Version 6.0.1 */
/* */
/**************************************************************************/
VOID _txm_module_manager_event_flags_notify_trampoline(TX_EVENT_FLAGS_GROUP *group_ptr)
{
TX_INTERRUPT_SAVE_AREA
TXM_MODULE_INSTANCE *module_instance;
TXM_MODULE_CALLBACK_MESSAGE callback_message;
TX_QUEUE *module_callback_queue;
/* We now know the callback is for a module. */
/* Disable interrupts. */
TX_DISABLE
/* Pickup the module instance pointer. */
module_instance = (TXM_MODULE_INSTANCE *) group_ptr -> tx_event_flags_group_module_instance;
/* Determine if this module is still valid. */
if ((module_instance) && (module_instance -> txm_module_instance_id == TXM_MODULE_ID) &&
(module_instance -> txm_module_instance_state == TXM_MODULE_STARTED))
{
/* Yes, the module is still valid. */
/* Pickup the module's callback message queue. */
module_callback_queue = &(module_instance -> txm_module_instance_callback_request_queue);
/* Build the queue notification message. */
callback_message.txm_module_callback_message_type = TXM_EVENTS_SET_CALLBACK;
callback_message.txm_module_callback_message_activation_count = 1;
callback_message.txm_module_callback_message_application_function = (VOID (*)(VOID)) group_ptr -> tx_event_flags_group_set_module_notify;
callback_message.txm_module_callback_message_param_1 = (ALIGN_TYPE) group_ptr;
callback_message.txm_module_callback_message_param_2 = 0;
callback_message.txm_module_callback_message_param_3 = 0;
callback_message.txm_module_callback_message_param_4 = 0;
callback_message.txm_module_callback_message_param_5 = 0;
callback_message.txm_module_callback_message_param_6 = 0;
callback_message.txm_module_callback_message_param_7 = 0;
callback_message.txm_module_callback_message_param_8 = 0;
callback_message.txm_module_callback_message_reserved1 = 0;
callback_message.txm_module_callback_message_reserved2 = 0;
/* Restore interrupts. */
TX_RESTORE
/* Call the general processing that will place the callback on the
module's callback request queue. */
_txm_module_manager_callback_request(module_callback_queue, &callback_message);
}
else
{
/* Module no longer valid. */
/* Error, increment the error counter and return. */
_txm_module_manager_callback_error_count++;
/* Restore interrupts. */
TX_RESTORE
}
}
#endif

View File

@@ -0,0 +1,217 @@
/**************************************************************************/
/* */
/* 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 */
/** */
/** Module Manager */
/** */
/**************************************************************************/
/**************************************************************************/
#ifdef FX_FILEX_PRESENT
#define TX_SOURCE_CODE
#include "tx_api.h"
#include "tx_initialize.h"
#include "tx_mutex.h"
#include "tx_thread.h"
#include "tx_byte_pool.h"
#include "fx_api.h"
#include "txm_module.h"
#include "txm_module_manager_util.h"
/**************************************************************************/
/* */
/* FUNCTION RELEASE */
/* */
/* _txm_module_manager_file_load PORTABLE C */
/* 6.0.1 */
/* AUTHOR */
/* */
/* Scott Larson, Microsoft Corporation */
/* */
/* DESCRIPTION */
/* */
/* This function reads the module preamble, allocates memory for */
/* module code, loads the module code from the file, and calls */
/* _txm_module_manager_internal_load to load the data and prepare the */
/* module for execution. */
/* */
/* INPUT */
/* */
/* module_instance Module instance pointer */
/* module_name Name of module */
/* media_ptr FileX media pointer */
/* file_name Name of module binary file */
/* */
/* OUTPUT */
/* */
/* status Completion status */
/* */
/* CALLS */
/* */
/* fx_file_close Close file */
/* fx_file_open Open file */
/* fx_file_read File read */
/* fx_file_seek File seek */
/* _tx_byte_allocate Allocate data area */
/* _txm_module_manager_internal_load Load data and prepare module for */
/* execution */
/* */
/* CALLED BY */
/* */
/* Application code */
/* */
/* RELEASE HISTORY */
/* */
/* DATE NAME DESCRIPTION */
/* */
/* 06-30-2020 Scott Larson Initial Version 6.0.1 */
/* */
/**************************************************************************/
UINT _txm_module_manager_file_load(TXM_MODULE_INSTANCE *module_instance, CHAR *module_name, FX_MEDIA *media_ptr, CHAR *file_name)
{
TXM_MODULE_PREAMBLE *module_preamble;
FX_FILE module_file;
TXM_MODULE_PREAMBLE preamble;
ULONG code_start;
ULONG code_size;
ULONG code_alignment;
ULONG code_allocation_size;
CHAR *code_memory_ptr;
UCHAR *destination_ptr;
ULONG actual_size;
UINT status;
/* Attempt to open the file. */
status = fx_file_open(media_ptr, &module_file, file_name, FX_OPEN_FOR_READ);
/* Check the file open status. */
if (status == FX_SUCCESS)
{
/* Read the preamble of the module. */
status = fx_file_read(&module_file, (VOID *) &preamble, sizeof(TXM_MODULE_PREAMBLE), &actual_size);
/* Check the file read status. */
if (status == FX_SUCCESS)
{
/* Check the number of bytes read. */
if (actual_size == sizeof(TXM_MODULE_PREAMBLE))
{
/* Pickup the module's information. */
module_preamble = (TXM_MODULE_PREAMBLE *) &preamble;
/* Pickup the module code size. */
code_size = module_preamble -> txm_module_preamble_code_size;
/* Check for valid sizes. */
if (code_size != 0)
{
/* Initialize module control block to all zeros. */
TX_MEMSET(module_instance, 0, sizeof(TXM_MODULE_INSTANCE));
/* Get the amount of the bytes we need to allocate for the module's code as well as the required alignment. */
status = _txm_module_manager_util_code_allocation_size_and_alignment_get(module_preamble, &code_alignment, &code_allocation_size);
if (status == TX_SUCCESS)
{
/* Allocate code memory for the module. */
status = _tx_byte_allocate(&_txm_module_manager_byte_pool, (VOID **) &code_memory_ptr, code_allocation_size, TX_NO_WAIT);
/* Determine if the module's code memory allocation was successful. */
if (status == TX_SUCCESS)
{
/* Prepare to read the module code into memory. */
code_start = (ULONG) code_memory_ptr;
code_start = (code_start + (code_alignment - 1)) & ~(code_alignment - 1);
destination_ptr = (UCHAR *) code_start;
/* Seek back to the beginning of the file. */
status = fx_file_seek(&module_file, 0);
if (status == FX_SUCCESS)
{
/* Read the module into memory. */
status = fx_file_read(&module_file, (VOID *) destination_ptr, code_size, &actual_size);
if (status == FX_SUCCESS)
{
/* Check the actual size read. */
if (actual_size == code_size)
{
/* At this point, the module's instruction area is now in the RAM code area. */
/* Now load it in-place. */
status = _txm_module_manager_internal_load(module_instance, module_name, (VOID *) code_start,
code_size, code_memory_ptr, code_allocation_size);
if (status == TX_SUCCESS)
{
/* Close the file. */
fx_file_close(&module_file);
/* Return success. */
return(TX_SUCCESS);
}
}
else
{
/* Invalid number of bytes read. */
status = TXM_MODULE_FILEX_INVALID_BYTES_READ;
}
}
}
/* Release the memory. */
_tx_byte_release(code_memory_ptr);
}
}
}
else
{
/* Invalid module preamble. */
status = TXM_MODULE_INVALID;
}
}
else
{
/* Invalid number of bytes read. */
status = TXM_MODULE_FILEX_INVALID_BYTES_READ;
}
}
/* Close the file. */
fx_file_close(&module_file);
}
/* Return success. */
return(status);
}
#endif

View File

@@ -0,0 +1,120 @@
/**************************************************************************/
/* */
/* 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 */
/** */
/** Module Manager */
/** */
/**************************************************************************/
/**************************************************************************/
#define TX_SOURCE_CODE
#include "tx_api.h"
#include "tx_initialize.h"
#include "tx_mutex.h"
#include "tx_thread.h"
#include "tx_byte_pool.h"
#include "txm_module.h"
#include "txm_module_manager_util.h"
/**************************************************************************/
/* */
/* FUNCTION RELEASE */
/* */
/* _txm_module_manager_in_place_load PORTABLE C */
/* 6.0.1 */
/* AUTHOR */
/* */
/* Scott Larson, Microsoft Corporation */
/* */
/* DESCRIPTION */
/* */
/* This function ensures the code-related parts of the module preamble */
/* are valid and calls _txm_module_manager_internal_load to load the */
/* data and prepare the module for execution. */
/* */
/* INPUT */
/* */
/* module_instance Module instance pointer */
/* module_name Module name pointer */
/* module_location Module code location */
/* */
/* OUTPUT */
/* */
/* status Completion status */
/* */
/* CALLS */
/* */
/* _txm_module_manager_internal_load Load data and prepare module for */
/* execution */
/* */
/* CALLED BY */
/* */
/* Application code */
/* */
/* RELEASE HISTORY */
/* */
/* DATE NAME DESCRIPTION */
/* */
/* 06-30-2020 Scott Larson Initial Version 6.0.1 */
/* */
/**************************************************************************/
UINT _txm_module_manager_in_place_load(TXM_MODULE_INSTANCE *module_instance, CHAR *module_name, VOID *module_location)
{
TXM_MODULE_PREAMBLE *module_preamble;
ULONG code_size;
ULONG code_alignment;
ULONG code_allocation_size_ignored;
UINT status;
/* Pickup the module's information. */
module_preamble = (TXM_MODULE_PREAMBLE *) module_location;
/* Pickup the basic module sizes. */
code_size = module_preamble -> txm_module_preamble_code_size;
/* Check for valid sizes. */
if (code_size == 0)
{
/* Invalid module preamble. */
return(TXM_MODULE_INVALID);
}
/* Get the amount of the bytes we need to allocate for the module's code
as well as the required alignment. Note that because this is an in-place
load, we only want the code alignment so we can check it. */
status = _txm_module_manager_util_code_allocation_size_and_alignment_get(module_preamble, &code_alignment, &code_allocation_size_ignored);
if (status != TX_SUCCESS)
{
/* Math overflow error occurred. */
return(status);
}
/* Since this is an in-place load, check the alignment of the module's instruction area (code). */
TXM_MODULE_MANAGER_CHECK_CODE_ALIGNMENT(module_location, code_alignment)
/* Now load the module in-place. */
status = _txm_module_manager_internal_load(module_instance, module_name, module_location,
code_size, TX_NULL, 0);
/* Return status. */
return(status);
}

View File

@@ -0,0 +1,186 @@
/**************************************************************************/
/* */
/* 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 */
/** */
/** Module Manager */
/** */
/**************************************************************************/
/**************************************************************************/
#define TX_SOURCE_CODE
#define TX_MODULE_MANAGER_INIT
#include "tx_api.h"
#include "tx_initialize.h"
#include "tx_thread.h"
#include "tx_byte_pool.h"
#include "tx_queue.h"
#include "tx_mutex.h"
#include "txm_module.h"
TXM_MODULE_MANAGER_VERSION_ID
/* Define global variables associated with the module manager. */
/* Define the module properties supported by this module manager. */
ULONG _txm_module_manager_properties_supported;
/* Define the module properties required by this module manager. */
ULONG _txm_module_manager_properties_required;
/* Define byte pool that will be used for allocating module data areas. */
TX_BYTE_POOL _txm_module_manager_byte_pool;
/* Define byte pool that will be used for allocating external memory for module objects. */
TX_BYTE_POOL _txm_module_manager_object_pool;
/* Define the flag indicating that the module manager byte pool is created. */
UINT _txm_module_manager_object_pool_created;
/* Define module manager protection mutex. */
TX_MUTEX _txm_module_manager_mutex;
/* Define the loaded modules list, which keeps track of all loaded modules. */
TXM_MODULE_INSTANCE *_txm_module_manager_loaded_list_ptr;
/* Define the count of loaded modules. */
ULONG _txm_module_manger_loaded_count;
/* Define the ready flag, which is checked by other module manager APIs
to make sure the manager has been initialized. */
UINT _txm_module_manager_ready;
/* Define the total callback activation count. This is simply incremented on every
callback activation. */
ULONG _txm_module_manager_callback_total_count;
/* Define the callback activation error count. This occurs when the available callback
structures have been exhausted. */
ULONG _txm_module_manager_callback_error_count;
/**************************************************************************/
/* */
/* FUNCTION RELEASE */
/* */
/* _txm_module_manager_initialize PORTABLE C */
/* 6.0.1 */
/* AUTHOR */
/* */
/* Scott Larson, Microsoft Corporation */
/* */
/* DESCRIPTION */
/* */
/* This function initializes the module manager. */
/* */
/* INPUT */
/* */
/* module_memory_start Start of module area */
/* module_memory_size Size in bytes of module area */
/* */
/* OUTPUT */
/* */
/* status Completion status */
/* */
/* CALLS */
/* */
/* _tx_byte_pool_create Create module memory byte pool */
/* _tx_mutex_create Create module manager */
/* protection mutex */
/* */
/* CALLED BY */
/* */
/* Application code */
/* */
/* RELEASE HISTORY */
/* */
/* DATE NAME DESCRIPTION */
/* */
/* 06-30-2020 Scott Larson Initial Version 6.0.1 */
/* */
/**************************************************************************/
UINT _txm_module_manager_initialize(VOID *module_memory_start, ULONG module_memory_size)
{
/* Check for interrupt call. */
if (TX_THREAD_GET_SYSTEM_STATE() != 0)
{
/* Now, make sure the call is from an interrupt and not initialization. */
if (TX_THREAD_GET_SYSTEM_STATE() < TX_INITIALIZE_IN_PROGRESS)
{
/* Invalid caller of this function, return appropriate error code. */
return(TX_CALLER_ERROR);
}
}
/* Setup the module properties supported by this module manager. */
_txm_module_manager_properties_supported = TXM_MODULE_MANAGER_SUPPORTED_OPTIONS;
/* Setup the module properties required by this module manager. */
_txm_module_manager_properties_required = TXM_MODULE_MANAGER_REQUIRED_OPTIONS;
/* Clear the module manager ready flag. */
_txm_module_manager_ready = TX_FALSE;
/* Initialize the empty module list. */
_txm_module_manager_loaded_list_ptr = TX_NULL;
/* Clear the number of loaded modules. */
_txm_module_manger_loaded_count = 0;
/* Create the module manager protection mutex. */
_tx_mutex_create(&_txm_module_manager_mutex, "Module Manager Protection Mutex", TX_NO_INHERIT);
/* Create a byte pool for allocating RAM areas for modules. */
_tx_byte_pool_create(&_txm_module_manager_byte_pool, "Module Manager Byte Pool", module_memory_start, module_memory_size);
/* Indicate the module manager object pool has not been created. */
_txm_module_manager_object_pool_created = TX_FALSE;
/* Mark the module manager as ready! */
_txm_module_manager_ready = TX_TRUE;
/* Return success. */
return(TX_SUCCESS);
}

View File

@@ -0,0 +1,424 @@
/**************************************************************************/
/* */
/* 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 */
/** */
/** Module Manager */
/** */
/**************************************************************************/
/**************************************************************************/
#define TX_SOURCE_CODE
#include "tx_api.h"
#include "tx_initialize.h"
#include "tx_mutex.h"
#include "tx_thread.h"
#include "tx_byte_pool.h"
#include "txm_module.h"
#include "txm_module_manager_util.h"
/**************************************************************************/
/* */
/* FUNCTION RELEASE */
/* */
/* _txm_module_manager_internal_load PORTABLE C */
/* 6.0.1 */
/* AUTHOR */
/* */
/* Scott Larson, Microsoft Corporation */
/* */
/* DESCRIPTION */
/* */
/* This function allocates data memory for module and prepares the */
/* module for execution from the supplied code location. */
/* */
/* INPUT */
/* */
/* module_instance Module instance pointer */
/* module_name Module name pointer */
/* module_location Module code location */
/* code_size Module code size */
/* code_allocation_ptr Allocated code location */
/* code_allocation_size Allocated code size */
/* */
/* OUTPUT */
/* */
/* status Completion status */
/* */
/* CALLS */
/* */
/* _tx_byte_allocate Allocate data area */
/* _tx_mutex_get Get protection mutex */
/* _tx_mutex_put Release protection mutex */
/* */
/* CALLED BY */
/* */
/* Application code */
/* */
/* RELEASE HISTORY */
/* */
/* DATE NAME DESCRIPTION */
/* */
/* 06-30-2020 Scott Larson Initial Version 6.0.1 */
/* */
/**************************************************************************/
UINT _txm_module_manager_internal_load(TXM_MODULE_INSTANCE *module_instance, CHAR *module_name, VOID *module_location,
ULONG code_size, VOID *code_allocation_ptr, ULONG code_allocation_size)
{
TX_INTERRUPT_SAVE_AREA
TXM_MODULE_PREAMBLE *module_preamble;
TXM_MODULE_INSTANCE *next_module, *previous_module;
ULONG shell_function_adjust;
ULONG start_function_adjust;
ULONG stop_function_adjust;
ULONG callback_function_adjust;
ULONG start_stop_stack_size;
ULONG callback_stack_size;
ULONG code_size_ignored;
ULONG code_alignment_ignored;
ALIGN_TYPE data_start;
ULONG data_size;
ULONG data_alignment;
ULONG data_allocation_size;
ULONG module_properties;
CHAR *memory_ptr;
UINT status;
/* Check for interrupt call. */
if (TX_THREAD_GET_SYSTEM_STATE() != 0)
{
/* Now, make sure the call is from an interrupt and not initialization. */
if (TX_THREAD_GET_SYSTEM_STATE() < TX_INITIALIZE_IN_PROGRESS)
{
/* Invalid caller of this function, return appropriate error code. */
return(TX_CALLER_ERROR);
}
}
/* Determine if the module manager has not been initialized yet. */
if (_txm_module_manager_ready != TX_TRUE)
{
/* Module manager has not been initialized. */
return(TX_NOT_AVAILABLE);
}
/* Determine if the module is valid. */
if (module_instance == TX_NULL)
{
/* Invalid module pointer. */
return(TX_PTR_ERROR);
}
/* Get module manager protection mutex. */
_tx_mutex_get(&_txm_module_manager_mutex, TX_WAIT_FOREVER);
/* Determine if the module is already valid. */
if (module_instance -> txm_module_instance_id == TXM_MODULE_ID)
{
/* Release the protection mutex. */
_tx_mutex_put(&_txm_module_manager_mutex);
/* Module already loaded. */
return(TXM_MODULE_ALREADY_LOADED);
}
/* Pickup the module's information. */
module_preamble = (TXM_MODULE_PREAMBLE *) module_location;
/* Check to make sure there is a valid module to load. */
if (module_preamble -> txm_module_preamble_id != TXM_MODULE_ID)
{
/* Release the protection mutex. */
_tx_mutex_put(&_txm_module_manager_mutex);
/* Invalid module preamble. */
return(TXM_MODULE_INVALID);
}
/* Check the properties of this module. */
module_properties = module_preamble -> txm_module_preamble_property_flags & TXM_MODULE_OPTIONS_MASK;
if (/* Ensure the requested properties are supported. */
((module_properties & _txm_module_manager_properties_supported) != module_properties) ||
/* Ensure the required properties are there. */
((_txm_module_manager_properties_required & module_properties) != _txm_module_manager_properties_required) ||
/* If memory protection is enabled, then so must user mode. */
((module_properties & TXM_MODULE_MEMORY_PROTECTION) && !(module_properties & TXM_MODULE_USER_MODE))
)
{
/* Release the protection mutex. */
_tx_mutex_put(&_txm_module_manager_mutex);
/* Invalid properties. Return error. */
return(TXM_MODULE_INVALID_PROPERTIES);
}
/* Check for valid module entry offsets. */
if ((module_preamble -> txm_module_preamble_shell_entry_function == 0) ||
(module_preamble -> txm_module_preamble_start_function == 0))
{
/* Release the protection mutex. */
_tx_mutex_put(&_txm_module_manager_mutex);
/* Invalid module preamble. */
return(TXM_MODULE_INVALID);
}
/* Check for valid sizes. */
if ((module_preamble -> txm_module_preamble_code_size == 0) ||
(module_preamble -> txm_module_preamble_data_size == 0) ||
(module_preamble -> txm_module_preamble_start_stop_stack_size == 0) ||
(module_preamble -> txm_module_preamble_callback_stack_size == 0))
{
/* Release the protection mutex. */
_tx_mutex_put(&_txm_module_manager_mutex);
/* Invalid module preamble. */
return(TXM_MODULE_INVALID);
}
/* Initialize module control block to all zeros. */
TX_MEMSET(module_instance, 0, sizeof(TXM_MODULE_INSTANCE));
/* Pickup the basic module sizes. */
data_size = module_preamble -> txm_module_preamble_data_size;
start_stop_stack_size = module_preamble -> txm_module_preamble_start_stop_stack_size;
callback_stack_size = module_preamble -> txm_module_preamble_callback_stack_size;
/* Adjust the size of the module elements to be aligned to the default alignment. We do this
so that when we partition the allocated memory, we can simply place these regions right beside
each other without having to align their pointers. Note this only works when they all have
the same alignment. */
TXM_MODULE_MANAGER_UTIL_MATH_ADD_ULONG(data_size, TXM_MODULE_DATA_ALIGNMENT, data_size);
data_size = ((data_size - 1)/TXM_MODULE_DATA_ALIGNMENT) * TXM_MODULE_DATA_ALIGNMENT;
TXM_MODULE_MANAGER_UTIL_MATH_ADD_ULONG(start_stop_stack_size, TXM_MODULE_DATA_ALIGNMENT, start_stop_stack_size);
start_stop_stack_size = ((start_stop_stack_size - 1)/TXM_MODULE_DATA_ALIGNMENT) * TXM_MODULE_DATA_ALIGNMENT;
TXM_MODULE_MANAGER_UTIL_MATH_ADD_ULONG(callback_stack_size, TXM_MODULE_DATA_ALIGNMENT, callback_stack_size);
callback_stack_size = ((callback_stack_size - 1)/TXM_MODULE_DATA_ALIGNMENT) * TXM_MODULE_DATA_ALIGNMENT;
/* Update the data size to account for the default thread stacks. */
TXM_MODULE_MANAGER_UTIL_MATH_ADD_ULONG(data_size, start_stop_stack_size, data_size);
TXM_MODULE_MANAGER_UTIL_MATH_ADD_ULONG(data_size, callback_stack_size, data_size);
/* Setup the default code and data alignments. */
data_alignment = (ULONG) TXM_MODULE_DATA_ALIGNMENT;
/* Get the port-specific alignment for the data size. Note we only want data
so we pass values of 1 for code (to avoid any possible div by 0 errors). */
code_size_ignored = 1;
code_alignment_ignored = 1;
TXM_MODULE_MANAGER_ALIGNMENT_ADJUST(module_preamble, code_size_ignored, code_alignment_ignored, data_size, data_alignment)
/* Calculate the module's total RAM memory requirement. This entire area is allocated from the module
manager's byte pool. The general layout is defined as follows:
Lowest Address: Start of start/stop thread stack
... [note: thread entry info is embedded near end of stack areas]
End of start/stop thread stack
Start of callback thread stack
... [note: thread entry info is embedded near end of stack areas]
End of callback thread stack
Module's Data Area
...
End of Module's Data Area
Highest Address: */
/* Add an extra alignment increment so we can align the pointer after allocation. */
TXM_MODULE_MANAGER_UTIL_MATH_ADD_ULONG(data_size, data_alignment, data_allocation_size);
/* Allocate memory for the module. */
status = _tx_byte_allocate(&_txm_module_manager_byte_pool, (VOID **) &memory_ptr, data_allocation_size, TX_NO_WAIT);
/* Determine if the module memory allocation was successful. */
if (status)
{
/* Release the protection mutex. */
_tx_mutex_put(&_txm_module_manager_mutex);
/* No memory, return an error. */
return(TX_NO_MEMORY);
}
/* Clear the allocated memory. */
TX_MEMSET(memory_ptr, ((UCHAR) 0), data_allocation_size);
/* Disable interrupts. */
TX_DISABLE
/* Setup the module instance structure. */
module_instance -> txm_module_instance_id = TXM_MODULE_ID;
/* Save the module name. */
module_instance -> txm_module_instance_name = module_name;
/* Save the module properties. */
module_instance -> txm_module_instance_property_flags = module_preamble -> txm_module_preamble_property_flags;
/* Set the module data memory allocation. This is the address released
when the module is unloaded. */
module_instance -> txm_module_instance_data_allocation_ptr = (VOID *) memory_ptr;
/* Save the data allocation size. */
module_instance -> txm_module_instance_data_allocation_size = data_allocation_size;
/* Calculate the actual start of the data area. This needs to be adjusted based on the alignment. */
data_start = (ALIGN_TYPE) memory_ptr;
data_start = (data_start + (((ALIGN_TYPE)data_alignment) - 1)) & ~(((ALIGN_TYPE)data_alignment) - 1);
memory_ptr = (CHAR *) data_start;
module_instance -> txm_module_instance_data_start = (VOID *) memory_ptr;
/* Compute the end of the data memory allocation. */
module_instance -> txm_module_instance_data_end = (VOID *) (memory_ptr + (data_size - 1));
/* Save the size of the data area. */
module_instance -> txm_module_instance_data_size = data_size;
/* Set the module code memory allocation. This is the address released
when the module is unloaded. */
module_instance -> txm_module_instance_code_allocation_ptr = (VOID *) code_allocation_ptr;
/* Save the code allocation size. */
module_instance -> txm_module_instance_code_allocation_size = code_allocation_size;
/* Setup the code pointers. Since the code was loaded in-place, this is effectively just the values supplied in the API call. */
module_instance -> txm_module_instance_code_start = (VOID *) module_location;
module_instance -> txm_module_instance_code_end = (VOID *) (((CHAR *) module_location) + (code_size - 1));
/* Setup the code size. */
module_instance -> txm_module_instance_code_size = code_size;
/* Save the module's total memory usage. */
module_instance -> txm_module_instance_total_ram_usage = data_allocation_size + code_allocation_size;
/* Set the module state to started. */
module_instance -> txm_module_instance_state = TXM_MODULE_LOADED;
/* Save the preamble pointer. */
module_instance -> txm_module_instance_preamble_ptr = module_preamble;
/* Save the module application ID in the module instance. */
module_instance -> txm_module_instance_application_module_id = module_preamble -> txm_module_preamble_application_module_id;
/* Setup the module's start/stop thread stack area. */
module_instance -> txm_module_instance_start_stop_stack_start_address = (VOID *) (memory_ptr);
module_instance -> txm_module_instance_start_stop_stack_size = start_stop_stack_size;
module_instance -> txm_module_instance_start_stop_stack_end_address = (VOID *) (memory_ptr + (start_stop_stack_size - 1));
/* Move the memory pointer forward. */
memory_ptr = memory_ptr + start_stop_stack_size;
/* Save the start/stop thread priority. */
module_instance -> txm_module_instance_start_stop_priority = module_preamble -> txm_module_preamble_start_stop_priority;
/* Setup the module's callback thread stack area. */
module_instance -> txm_module_instance_callback_stack_start_address = (VOID *) (memory_ptr);
module_instance -> txm_module_instance_callback_stack_size = callback_stack_size;
module_instance -> txm_module_instance_callback_stack_end_address = (VOID *) (memory_ptr + (callback_stack_size - 1));
/* Move the memory pointer forward. */
memory_ptr = memory_ptr + callback_stack_size;
/* Save the callback thread priority. */
module_instance -> txm_module_instance_callback_priority = module_preamble -> txm_module_preamble_callback_priority;
/* Setup the start of the module data section. */
module_instance -> txm_module_instance_module_data_base_address = (VOID *) (memory_ptr);
/* Calculate the function adjustments based on the specific implementation of the module manager/module. */
TXM_MODULE_MANAGER_CALCULATE_ADJUSTMENTS(module_preamble -> txm_module_preamble_property_flags, shell_function_adjust, start_function_adjust, stop_function_adjust, callback_function_adjust)
/* Build actual addresses based on load... Setup all the function pointers. Any adjustments needed to shell entry, start function, and callback function are defined in the
module preamble. */
module_instance -> txm_module_instance_shell_entry_function = (VOID (*)(TX_THREAD *, TXM_MODULE_INSTANCE *)) (((CHAR *) module_instance -> txm_module_instance_code_start) +
(module_preamble -> txm_module_preamble_shell_entry_function) +
(shell_function_adjust));
module_instance -> txm_module_instance_start_thread_entry = (VOID (*)(ULONG)) (((CHAR *) module_instance -> txm_module_instance_code_start) +
(module_preamble -> txm_module_preamble_start_function) +
(start_function_adjust));
module_instance -> txm_module_instance_callback_request_thread_entry = (VOID (*)(ULONG)) (((CHAR *) module_instance -> txm_module_instance_code_start) +
(module_preamble -> txm_module_preamble_callback_function) +
(callback_function_adjust));
/* Determine if there is a stop function for this module. */
if (module_preamble -> txm_module_preamble_stop_function)
{
/* Yes, there is a stop function, build the address. */
module_instance -> txm_module_instance_stop_thread_entry = (VOID (*)(ULONG)) (((CHAR *) module_instance -> txm_module_instance_code_start) +
(module_preamble -> txm_module_preamble_stop_function) +
(stop_function_adjust));
}
else
{
/* No, there is no stop function. Just set the pointer to NULL. */
module_instance -> txm_module_instance_stop_thread_entry = TX_NULL;
}
/* Load the module control block with port-specific information. */
TXM_MODULE_MANAGER_MODULE_SETUP(module_instance);
/* Now add the module to the linked list of created modules. */
if (_txm_module_manger_loaded_count++ == 0)
{
/* The loaded module list is empty. Add module to empty list. */
_txm_module_manager_loaded_list_ptr = module_instance;
module_instance -> txm_module_instance_loaded_next = module_instance;
module_instance -> txm_module_instance_loaded_previous = module_instance;
}
else
{
/* This list is not NULL, add to the end of the list. */
next_module = _txm_module_manager_loaded_list_ptr;
previous_module = next_module -> txm_module_instance_loaded_previous;
/* Place the new module in the list. */
next_module -> txm_module_instance_loaded_previous = module_instance;
previous_module -> txm_module_instance_loaded_next = module_instance;
/* Setup this module's created links. */
module_instance -> txm_module_instance_loaded_previous = previous_module;
module_instance -> txm_module_instance_loaded_next = next_module;
}
/* Restore interrupts. */
TX_RESTORE
/* Release the protection mutex. */
_tx_mutex_put(&_txm_module_manager_mutex);
/* Return success. */
return(TX_SUCCESS);
}

View File

@@ -0,0 +1,741 @@
/**************************************************************************/
/* */
/* 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 */
/** */
/** Module Manager */
/** */
/**************************************************************************/
/**************************************************************************/
#define TX_SOURCE_CODE
#include "tx_api.h"
#include "tx_block_pool.h"
#include "tx_byte_pool.h"
#include "tx_event_flags.h"
#include "tx_queue.h"
#include "tx_mutex.h"
#include "tx_semaphore.h"
#include "tx_thread.h"
#include "tx_timer.h"
#include "tx_trace.h"
#include "txm_module.h"
#include "txm_module_manager_util.h"
#include "txm_module_manager_dispatch.h"
/**************************************************************************/
/* */
/* FUNCTION RELEASE */
/* */
/* _txm_module_kernel_dispatch PORTABLE C */
/* 6.0.1 */
/* AUTHOR */
/* */
/* Scott Larson, Microsoft Corporation */
/* */
/* DESCRIPTION */
/* */
/* This function dispatches the module's kernel request based upon the */
/* ID and parameters specified in the request. */
/* */
/* INPUT */
/* */
/* kernel_request Module's kernel request */
/* param_1 First parameter */
/* param_2 Second parameter */
/* param_3 Third parameter */
/* */
/* OUTPUT */
/* */
/* status Completion status */
/* */
/* CALLS */
/* */
/* _txm_module_manager_application_request Application-specific req */
/* _txm_module_manager_object_pointer_get Find object pointer */
/* _txm_module_manager_thread_create Module thread create */
/* [_txm_module_manager_*_dispatch] Optional external */
/* component dispatch */
/* ThreadX API Calls */
/* */
/* CALLED BY */
/* */
/* Application code */
/* */
/* RELEASE HISTORY */
/* */
/* DATE NAME DESCRIPTION */
/* */
/* 06-30-2020 Scott Larson Initial Version 6.0.1 */
/* */
/**************************************************************************/
ALIGN_TYPE _txm_module_manager_kernel_dispatch(ULONG kernel_request, ALIGN_TYPE param_0, ALIGN_TYPE param_1, ALIGN_TYPE param_2)
{
ALIGN_TYPE return_value = TX_NOT_AVAILABLE;
TXM_MODULE_INSTANCE *module_instance;
/* Get the module instance. */
module_instance = _tx_thread_current_ptr -> tx_thread_module_instance_ptr;
/* Sanity-check for a valid module instance. */
if (module_instance == TX_NULL)
{
/* Just return! */
return(TXM_MODULE_INVALID);
}
switch (kernel_request)
{
case TXM_BLOCK_ALLOCATE_CALL:
{
return_value = _txm_module_manager_tx_block_allocate_dispatch(module_instance, param_0, param_1, param_2);
break;
}
case TXM_BLOCK_POOL_CREATE_CALL:
{
return_value = _txm_module_manager_tx_block_pool_create_dispatch(module_instance, param_0, param_1, (ALIGN_TYPE *) param_2);
break;
}
case TXM_BLOCK_POOL_DELETE_CALL:
{
return_value = _txm_module_manager_tx_block_pool_delete_dispatch(module_instance, param_0);
break;
}
case TXM_BLOCK_POOL_INFO_GET_CALL:
{
return_value = _txm_module_manager_tx_block_pool_info_get_dispatch(module_instance, param_0, param_1, (ALIGN_TYPE *) param_2);
break;
}
case TXM_BLOCK_POOL_PERFORMANCE_INFO_GET_CALL:
{
return_value = _txm_module_manager_tx_block_pool_performance_info_get_dispatch(module_instance, param_0, param_1, (ALIGN_TYPE *) param_2);
break;
}
case TXM_BLOCK_POOL_PERFORMANCE_SYSTEM_INFO_GET_CALL:
{
return_value = _txm_module_manager_tx_block_pool_performance_system_info_get_dispatch(module_instance, param_0, param_1, (ALIGN_TYPE *) param_2);
break;
}
case TXM_BLOCK_POOL_PRIORITIZE_CALL:
{
return_value = _txm_module_manager_tx_block_pool_prioritize_dispatch(module_instance, param_0);
break;
}
case TXM_BLOCK_RELEASE_CALL:
{
return_value = _txm_module_manager_tx_block_release_dispatch(module_instance, param_0);
break;
}
case TXM_BYTE_ALLOCATE_CALL:
{
return_value = _txm_module_manager_tx_byte_allocate_dispatch(module_instance, param_0, param_1, (ALIGN_TYPE *) param_2);
break;
}
case TXM_BYTE_POOL_CREATE_CALL:
{
return_value = _txm_module_manager_tx_byte_pool_create_dispatch(module_instance, param_0, param_1, (ALIGN_TYPE *) param_2);
break;
}
case TXM_BYTE_POOL_DELETE_CALL:
{
return_value = _txm_module_manager_tx_byte_pool_delete_dispatch(module_instance, param_0);
break;
}
case TXM_BYTE_POOL_INFO_GET_CALL:
{
return_value = _txm_module_manager_tx_byte_pool_info_get_dispatch(module_instance, param_0, param_1, (ALIGN_TYPE *) param_2);
break;
}
case TXM_BYTE_POOL_PERFORMANCE_INFO_GET_CALL:
{
return_value = _txm_module_manager_tx_byte_pool_performance_info_get_dispatch(module_instance, param_0, param_1, (ALIGN_TYPE *) param_2);
break;
}
case TXM_BYTE_POOL_PERFORMANCE_SYSTEM_INFO_GET_CALL:
{
return_value = _txm_module_manager_tx_byte_pool_performance_system_info_get_dispatch(module_instance, param_0, param_1, (ALIGN_TYPE *) param_2);
break;
}
case TXM_BYTE_POOL_PRIORITIZE_CALL:
{
return_value = _txm_module_manager_tx_byte_pool_prioritize_dispatch(module_instance, param_0);
break;
}
case TXM_BYTE_RELEASE_CALL:
{
return_value = _txm_module_manager_tx_byte_release_dispatch(module_instance, param_0);
break;
}
case TXM_EVENT_FLAGS_CREATE_CALL:
{
return_value = _txm_module_manager_tx_event_flags_create_dispatch(module_instance, param_0, param_1, param_2);
break;
}
case TXM_EVENT_FLAGS_DELETE_CALL:
{
return_value = _txm_module_manager_tx_event_flags_delete_dispatch(module_instance, param_0);
break;
}
case TXM_EVENT_FLAGS_GET_CALL:
{
return_value = _txm_module_manager_tx_event_flags_get_dispatch(module_instance, param_0, param_1, (ALIGN_TYPE *) param_2);
break;
}
case TXM_EVENT_FLAGS_INFO_GET_CALL:
{
return_value = _txm_module_manager_tx_event_flags_info_get_dispatch(module_instance, param_0, param_1, (ALIGN_TYPE *) param_2);
break;
}
case TXM_EVENT_FLAGS_PERFORMANCE_INFO_GET_CALL:
{
return_value = _txm_module_manager_tx_event_flags_performance_info_get_dispatch(module_instance, param_0, param_1, (ALIGN_TYPE *) param_2);
break;
}
case TXM_EVENT_FLAGS_PERFORMANCE_SYSTEM_INFO_GET_CALL:
{
return_value = _txm_module_manager_tx_event_flags_performance_system_info_get_dispatch(module_instance, param_0, param_1, (ALIGN_TYPE *) param_2);
break;
}
case TXM_EVENT_FLAGS_SET_CALL:
{
return_value = _txm_module_manager_tx_event_flags_set_dispatch(module_instance, param_0, param_1, param_2);
break;
}
case TXM_EVENT_FLAGS_SET_NOTIFY_CALL:
{
return_value = _txm_module_manager_tx_event_flags_set_notify_dispatch(module_instance, param_0, param_1);
break;
}
case TXM_MUTEX_CREATE_CALL:
{
return_value = _txm_module_manager_tx_mutex_create_dispatch(module_instance, param_0, param_1, (ALIGN_TYPE *) param_2);
break;
}
case TXM_MUTEX_DELETE_CALL:
{
return_value = _txm_module_manager_tx_mutex_delete_dispatch(module_instance, param_0);
break;
}
case TXM_MUTEX_GET_CALL:
{
return_value = _txm_module_manager_tx_mutex_get_dispatch(module_instance, param_0, param_1);
break;
}
case TXM_MUTEX_INFO_GET_CALL:
{
return_value = _txm_module_manager_tx_mutex_info_get_dispatch(module_instance, param_0, param_1, (ALIGN_TYPE *) param_2);
break;
}
case TXM_MUTEX_PERFORMANCE_INFO_GET_CALL:
{
return_value = _txm_module_manager_tx_mutex_performance_info_get_dispatch(module_instance, param_0, param_1, (ALIGN_TYPE *) param_2);
break;
}
case TXM_MUTEX_PERFORMANCE_SYSTEM_INFO_GET_CALL:
{
return_value = _txm_module_manager_tx_mutex_performance_system_info_get_dispatch(module_instance, param_0, param_1, (ALIGN_TYPE *) param_2);
break;
}
case TXM_MUTEX_PRIORITIZE_CALL:
{
return_value = _txm_module_manager_tx_mutex_prioritize_dispatch(module_instance, param_0);
break;
}
case TXM_MUTEX_PUT_CALL:
{
return_value = _txm_module_manager_tx_mutex_put_dispatch(module_instance, param_0);
break;
}
case TXM_QUEUE_CREATE_CALL:
{
return_value = _txm_module_manager_tx_queue_create_dispatch(module_instance, param_0, param_1, (ALIGN_TYPE *) param_2);
break;
}
case TXM_QUEUE_DELETE_CALL:
{
return_value = _txm_module_manager_tx_queue_delete_dispatch(module_instance, param_0);
break;
}
case TXM_QUEUE_FLUSH_CALL:
{
return_value = _txm_module_manager_tx_queue_flush_dispatch(module_instance, param_0);
break;
}
case TXM_QUEUE_FRONT_SEND_CALL:
{
return_value = _txm_module_manager_tx_queue_front_send_dispatch(module_instance, param_0, param_1, param_2);
break;
}
case TXM_QUEUE_INFO_GET_CALL:
{
return_value = _txm_module_manager_tx_queue_info_get_dispatch(module_instance, param_0, param_1, (ALIGN_TYPE *) param_2);
break;
}
case TXM_QUEUE_PERFORMANCE_INFO_GET_CALL:
{
return_value = _txm_module_manager_tx_queue_performance_info_get_dispatch(module_instance, param_0, param_1, (ALIGN_TYPE *) param_2);
break;
}
case TXM_QUEUE_PERFORMANCE_SYSTEM_INFO_GET_CALL:
{
return_value = _txm_module_manager_tx_queue_performance_system_info_get_dispatch(module_instance, param_0, param_1, (ALIGN_TYPE *) param_2);
break;
}
case TXM_QUEUE_PRIORITIZE_CALL:
{
return_value = _txm_module_manager_tx_queue_prioritize_dispatch(module_instance, param_0);
break;
}
case TXM_QUEUE_RECEIVE_CALL:
{
return_value = _txm_module_manager_tx_queue_receive_dispatch(module_instance, param_0, param_1, param_2);
break;
}
case TXM_QUEUE_SEND_CALL:
{
return_value = _txm_module_manager_tx_queue_send_dispatch(module_instance, param_0, param_1, param_2);
break;
}
case TXM_QUEUE_SEND_NOTIFY_CALL:
{
return_value = _txm_module_manager_tx_queue_send_notify_dispatch(module_instance, param_0, param_1);
break;
}
case TXM_SEMAPHORE_CEILING_PUT_CALL:
{
return_value = _txm_module_manager_tx_semaphore_ceiling_put_dispatch(module_instance, param_0, param_1);
break;
}
case TXM_SEMAPHORE_CREATE_CALL:
{
return_value = _txm_module_manager_tx_semaphore_create_dispatch(module_instance, param_0, param_1, (ALIGN_TYPE *) param_2);
break;
}
case TXM_SEMAPHORE_DELETE_CALL:
{
return_value = _txm_module_manager_tx_semaphore_delete_dispatch(module_instance, param_0);
break;
}
case TXM_SEMAPHORE_GET_CALL:
{
return_value = _txm_module_manager_tx_semaphore_get_dispatch(module_instance, param_0, param_1);
break;
}
case TXM_SEMAPHORE_INFO_GET_CALL:
{
return_value = _txm_module_manager_tx_semaphore_info_get_dispatch(module_instance, param_0, param_1, (ALIGN_TYPE *) param_2);
break;
}
case TXM_SEMAPHORE_PERFORMANCE_INFO_GET_CALL:
{
return_value = _txm_module_manager_tx_semaphore_performance_info_get_dispatch(module_instance, param_0, param_1, (ALIGN_TYPE *) param_2);
break;
}
case TXM_SEMAPHORE_PERFORMANCE_SYSTEM_INFO_GET_CALL:
{
return_value = _txm_module_manager_tx_semaphore_performance_system_info_get_dispatch(module_instance, param_0, param_1, (ALIGN_TYPE *) param_2);
break;
}
case TXM_SEMAPHORE_PRIORITIZE_CALL:
{
return_value = _txm_module_manager_tx_semaphore_prioritize_dispatch(module_instance, param_0);
break;
}
case TXM_SEMAPHORE_PUT_CALL:
{
return_value = _txm_module_manager_tx_semaphore_put_dispatch(module_instance, param_0);
break;
}
case TXM_SEMAPHORE_PUT_NOTIFY_CALL:
{
return_value = _txm_module_manager_tx_semaphore_put_notify_dispatch(module_instance, param_0, param_1);
break;
}
case TXM_THREAD_CREATE_CALL:
{
return_value = _txm_module_manager_tx_thread_create_dispatch(module_instance, param_0, param_1, (ALIGN_TYPE *) param_2);
break;
}
case TXM_THREAD_DELETE_CALL:
{
return_value = _txm_module_manager_tx_thread_delete_dispatch(module_instance, param_0);
break;
}
case TXM_THREAD_ENTRY_EXIT_NOTIFY_CALL:
{
return_value = _txm_module_manager_tx_thread_entry_exit_notify_dispatch(module_instance, param_0, param_1);
break;
}
case TXM_THREAD_IDENTIFY_CALL:
{
return_value = _txm_module_manager_tx_thread_identify_dispatch(module_instance, param_0, param_1, (ALIGN_TYPE *) param_2);
break;
}
case TXM_THREAD_INFO_GET_CALL:
{
return_value = _txm_module_manager_tx_thread_info_get_dispatch(module_instance, param_0, param_1, (ALIGN_TYPE *) param_2);
break;
}
case TXM_THREAD_INTERRUPT_CONTROL_CALL:
{
return_value = _txm_module_manager_tx_thread_interrupt_control_dispatch(module_instance, param_0);
break;
}
case TXM_THREAD_PERFORMANCE_INFO_GET_CALL:
{
return_value = _txm_module_manager_tx_thread_performance_info_get_dispatch(module_instance, param_0, param_1, (ALIGN_TYPE *) param_2);
break;
}
case TXM_THREAD_PERFORMANCE_SYSTEM_INFO_GET_CALL:
{
return_value = _txm_module_manager_tx_thread_performance_system_info_get_dispatch(module_instance, param_0, param_1, (ALIGN_TYPE *) param_2);
break;
}
case TXM_THREAD_PREEMPTION_CHANGE_CALL:
{
return_value = _txm_module_manager_tx_thread_preemption_change_dispatch(module_instance, param_0, param_1, param_2);
break;
}
case TXM_THREAD_PRIORITY_CHANGE_CALL:
{
return_value = _txm_module_manager_tx_thread_priority_change_dispatch(module_instance, param_0, param_1, param_2);
break;
}
case TXM_THREAD_RELINQUISH_CALL:
{
return_value = _txm_module_manager_tx_thread_relinquish_dispatch(module_instance, param_0, param_1, (ALIGN_TYPE *) param_2);
break;
}
case TXM_THREAD_RESET_CALL:
{
return_value = _txm_module_manager_tx_thread_reset_dispatch(module_instance, param_0);
break;
}
case TXM_THREAD_RESUME_CALL:
{
return_value = _txm_module_manager_tx_thread_resume_dispatch(module_instance, param_0);
break;
}
case TXM_THREAD_SLEEP_CALL:
{
return_value = _txm_module_manager_tx_thread_sleep_dispatch(module_instance, param_0);
break;
}
case TXM_THREAD_STACK_ERROR_NOTIFY_CALL:
{
return_value = _txm_module_manager_tx_thread_stack_error_notify_dispatch(module_instance, param_0);
break;
}
case TXM_THREAD_SUSPEND_CALL:
{
return_value = _txm_module_manager_tx_thread_suspend_dispatch(module_instance, param_0);
break;
}
case TXM_THREAD_SYSTEM_SUSPEND_CALL:
{
return_value = _txm_module_manager_tx_thread_system_suspend_dispatch(module_instance, param_0);
break;
}
case TXM_THREAD_TERMINATE_CALL:
{
return_value = _txm_module_manager_tx_thread_terminate_dispatch(module_instance, param_0);
break;
}
case TXM_THREAD_TIME_SLICE_CHANGE_CALL:
{
return_value = _txm_module_manager_tx_thread_time_slice_change_dispatch(module_instance, param_0, param_1, param_2);
break;
}
case TXM_THREAD_WAIT_ABORT_CALL:
{
return_value = _txm_module_manager_tx_thread_wait_abort_dispatch(module_instance, param_0);
break;
}
case TXM_TIME_GET_CALL:
{
return_value = _txm_module_manager_tx_time_get_dispatch(module_instance, param_0, param_1, (ALIGN_TYPE *) param_2);
break;
}
case TXM_TIME_SET_CALL:
{
return_value = _txm_module_manager_tx_time_set_dispatch(module_instance, param_0);
break;
}
case TXM_TIMER_ACTIVATE_CALL:
{
return_value = _txm_module_manager_tx_timer_activate_dispatch(module_instance, param_0);
break;
}
case TXM_TIMER_CHANGE_CALL:
{
return_value = _txm_module_manager_tx_timer_change_dispatch(module_instance, param_0, param_1, param_2);
break;
}
case TXM_TIMER_CREATE_CALL:
{
return_value = _txm_module_manager_tx_timer_create_dispatch(module_instance, param_0, param_1, (ALIGN_TYPE *) param_2);
break;
}
case TXM_TIMER_DEACTIVATE_CALL:
{
return_value = _txm_module_manager_tx_timer_deactivate_dispatch(module_instance, param_0);
break;
}
case TXM_TIMER_DELETE_CALL:
{
return_value = _txm_module_manager_tx_timer_delete_dispatch(module_instance, param_0);
break;
}
case TXM_TIMER_INFO_GET_CALL:
{
return_value = _txm_module_manager_tx_timer_info_get_dispatch(module_instance, param_0, param_1, (ALIGN_TYPE *) param_2);
break;
}
case TXM_TIMER_PERFORMANCE_INFO_GET_CALL:
{
return_value = _txm_module_manager_tx_timer_performance_info_get_dispatch(module_instance, param_0, param_1, (ALIGN_TYPE *) param_2);
break;
}
case TXM_TIMER_PERFORMANCE_SYSTEM_INFO_GET_CALL:
{
return_value = _txm_module_manager_tx_timer_performance_system_info_get_dispatch(module_instance, param_0, param_1, (ALIGN_TYPE *) param_2);
break;
}
case TXM_TRACE_BUFFER_FULL_NOTIFY_CALL:
{
return_value = _txm_module_manager_tx_trace_buffer_full_notify_dispatch(module_instance, param_0);
break;
}
case TXM_TRACE_DISABLE_CALL:
{
return_value = _txm_module_manager_tx_trace_disable_dispatch(module_instance, param_0, param_1, (ALIGN_TYPE *) param_2);
break;
}
case TXM_TRACE_ENABLE_CALL:
{
return_value = _txm_module_manager_tx_trace_enable_dispatch(module_instance, param_0, param_1, param_2);
break;
}
case TXM_TRACE_EVENT_FILTER_CALL:
{
return_value = _txm_module_manager_tx_trace_event_filter_dispatch(module_instance, param_0);
break;
}
case TXM_TRACE_EVENT_UNFILTER_CALL:
{
return_value = _txm_module_manager_tx_trace_event_unfilter_dispatch(module_instance, param_0);
break;
}
case TXM_TRACE_INTERRUPT_CONTROL_CALL:
{
return_value = _txm_module_manager_tx_trace_interrupt_control_dispatch(module_instance, param_0);
break;
}
case TXM_TRACE_ISR_ENTER_INSERT_CALL:
{
return_value = _txm_module_manager_tx_trace_isr_enter_insert_dispatch(module_instance, param_0);
break;
}
case TXM_TRACE_ISR_EXIT_INSERT_CALL:
{
return_value = _txm_module_manager_tx_trace_isr_exit_insert_dispatch(module_instance, param_0);
break;
}
case TXM_TRACE_USER_EVENT_INSERT_CALL:
{
return_value = _txm_module_manager_tx_trace_user_event_insert_dispatch(module_instance, param_0, param_1, (ALIGN_TYPE *) param_2);
break;
}
case TXM_MODULE_OBJECT_ALLOCATE_CALL:
{
return_value = _txm_module_manager_txm_module_object_allocate_dispatch(module_instance, param_0, param_1);
break;
}
case TXM_MODULE_OBJECT_DEALLOCATE_CALL:
{
return_value = _txm_module_manager_txm_module_object_deallocate_dispatch(module_instance, param_0);
break;
}
case TXM_MODULE_OBJECT_POINTER_GET_CALL:
{
return_value = _txm_module_manager_txm_module_object_pointer_get_dispatch(module_instance, param_0, param_1, param_2);
break;
}
case TXM_MODULE_OBJECT_POINTER_GET_EXTENDED_CALL:
{
return_value = _txm_module_manager_txm_module_object_pointer_get_extended_dispatch(module_instance, param_0, param_1, (ALIGN_TYPE *) param_2);
break;
}
default:
{
/* Determine if an application request is present. */
if (kernel_request >= TXM_APPLICATION_REQUEST_ID_BASE)
{
/* Yes, call the module manager function that the application defines in order to
support application-specific requests. */
return_value = (ALIGN_TYPE) _txm_module_manager_application_request(kernel_request-TXM_APPLICATION_REQUEST_ID_BASE, param_0, param_1, param_2);
}
#ifdef TXM_MODULE_ENABLE_NETX
/* Determine if there is a NetX request. */
else if ((kernel_request >= TXM_NETX_API_ID_START) && (kernel_request < TXM_NETX_API_ID_END))
{
/* Call the NetX module dispatch function. */
return_value = _txm_module_manager_netx_dispatch(module_instance, kernel_request, param_0, param_1, param_2);
}
#endif
#ifdef TXM_MODULE_ENABLE_NETXDUO
/* Determine if there is a NetX Duo request. */
else if ((kernel_request >= TXM_NETXDUO_API_ID_START) && (kernel_request < TXM_NETXDUO_API_ID_END))
{
/* Call the NetX Duo module dispatch function. */
return_value = _txm_module_manager_netxduo_dispatch(module_instance, kernel_request, param_0, param_1, param_2);
}
#endif
#ifdef TXM_MODULE_ENABLE_FILEX
/* Determine if there is a FileX request. */
else if ((kernel_request >= TXM_FILEX_API_ID_START) && (kernel_request < TXM_FILEX_API_ID_END))
{
/* Call the FileX module dispatch function. */
return_value = _txm_module_manager_filex_dispatch(module_instance, kernel_request, param_0, param_1, param_2);
}
#endif
#ifdef TXM_MODULE_ENABLE_GUIX
/* Determine if there is a GUIX request. */
else if ((kernel_request >= TXM_GUIX_API_ID_START) && (kernel_request < TXM_GUIX_API_ID_END))
{
/* Call the GUIX module dispatch function. */
return_value = _txm_module_manager_guix_dispatch(module_instance, kernel_request, param_0, param_1, param_2);
}
#endif
#ifdef TXM_MODULE_ENABLE_USBX
/* Determine if there is a USBX request. */
else if ((kernel_request >= TXM_USBX_API_ID_START) && (kernel_request < TXM_USBX_API_ID_END))
{
/* Call the USBX dispatch function. */
return_value = _txm_module_manager_usbx_dispatch(module_instance, kernel_request, param_0, param_1, param_2);
}
#endif
/* Unhandled kernel request, return an error! */
break;
}
}
return(return_value);
}

View File

@@ -0,0 +1,116 @@
/**************************************************************************/
/* */
/* 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 */
/** */
/** Module Manager */
/** */
/**************************************************************************/
/**************************************************************************/
#define TX_SOURCE_CODE
#include "tx_api.h"
#include "tx_mutex.h"
#include "txm_module.h"
/**************************************************************************/
/* */
/* FUNCTION RELEASE */
/* */
/* _txm_module_manager_maximum_module_priority_set PORTABLE C */
/* 6.0.1 */
/* AUTHOR */
/* */
/* Scott Larson, Microsoft Corporation */
/* */
/* DESCRIPTION */
/* */
/* This function sets the maximum thread priority allowed in a module. */
/* */
/* INPUT */
/* */
/* module_instance Module instance pointer */
/* priority Maximum thread priority */
/* */
/* OUTPUT */
/* */
/* status Completion status */
/* */
/* CALLS */
/* */
/* _tx_mutex_get Get protection mutex */
/* _tx_mutex_put Release protection mutex */
/* */
/* CALLED BY */
/* */
/* Application code */
/* */
/* RELEASE HISTORY */
/* */
/* DATE NAME DESCRIPTION */
/* */
/* 06-30-2020 Scott Larson Initial Version 6.0.1 */
/* */
/**************************************************************************/
UINT _txm_module_manager_maximum_module_priority_set(TXM_MODULE_INSTANCE *module_instance, UINT priority)
{
/* Determine if the module manager has not been initialized yet. */
if (_txm_module_manager_ready != TX_TRUE)
{
/* Module manager has not been initialized. */
return(TX_NOT_AVAILABLE);
}
/* Determine if the module is valid. */
if (module_instance == TX_NULL)
{
/* Invalid module pointer. */
return(TX_PTR_ERROR);
}
/* Get module manager protection mutex. */
_tx_mutex_get(&_txm_module_manager_mutex, TX_WAIT_FOREVER);
/* Determine if the module instance is valid. */
if (module_instance -> txm_module_instance_id != TXM_MODULE_ID)
{
/* Release the protection mutex. */
_tx_mutex_put(&_txm_module_manager_mutex);
/* Invalid module pointer. */
return(TX_PTR_ERROR);
}
/* Determine if the module instance is in the loaded state. */
if ((module_instance -> txm_module_instance_state != TXM_MODULE_LOADED) && (module_instance -> txm_module_instance_state != TXM_MODULE_STOPPED))
{
/* Release the protection mutex. */
_tx_mutex_put(&_txm_module_manager_mutex);
/* Return error if the module is not ready. */
return(TX_START_ERROR);
}
/* Set module's maximum priority. */
module_instance->txm_module_instance_maximum_priority = priority;
/* Release the protection mutex. */
_tx_mutex_put(&_txm_module_manager_mutex);
return(TX_SUCCESS);
}

View File

@@ -0,0 +1,162 @@
/**************************************************************************/
/* */
/* 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 */
/** */
/** Module Manager */
/** */
/**************************************************************************/
/**************************************************************************/
#define TX_SOURCE_CODE
#include "tx_api.h"
#include "tx_initialize.h"
#include "tx_mutex.h"
#include "tx_thread.h"
#include "tx_byte_pool.h"
#include "txm_module.h"
#include "txm_module_manager_util.h"
/**************************************************************************/
/* */
/* FUNCTION RELEASE */
/* */
/* _txm_module_manager_memory_load PORTABLE C */
/* 6.0.1 */
/* AUTHOR */
/* */
/* Scott Larson, Microsoft Corporation */
/* */
/* DESCRIPTION */
/* */
/* This function allocates memory for module code and and calls */
/* _txm_module_manager_internal_load to load the data and prepare the */
/* module for execution. */
/* */
/* INPUT */
/* */
/* module_instance Module instance pointer */
/* module_name Module name pointer */
/* module_location Module code location */
/* */
/* OUTPUT */
/* */
/* status Completion status */
/* */
/* CALLS */
/* */
/* _tx_byte_allocate Allocate data area */
/* _txm_module_manager_internal_load Load data and prepare module for */
/* execution */
/* */
/* CALLED BY */
/* */
/* Application code */
/* */
/* RELEASE HISTORY */
/* */
/* DATE NAME DESCRIPTION */
/* */
/* 06-30-2020 Scott Larson Initial Version 6.0.1 */
/* */
/**************************************************************************/
UINT _txm_module_manager_memory_load(TXM_MODULE_INSTANCE *module_instance, CHAR *module_name, VOID *module_location)
{
TXM_MODULE_PREAMBLE *module_preamble;
ALIGN_TYPE code_start;
ULONG code_size;
ULONG code_alignment;
ULONG code_allocation_size;
CHAR *code_memory_ptr;
UCHAR *source_ptr;
UCHAR *destination_ptr;
ULONG copy_size;
ULONG i;
UINT status;
/* Pickup the module's information. */
module_preamble = (TXM_MODULE_PREAMBLE *) module_location;
/* Pickup the basic module sizes. */
code_size = module_preamble -> txm_module_preamble_code_size;
/* Check for valid sizes. */
if (code_size == 0)
{
/* Invalid module preamble. */
return(TXM_MODULE_INVALID);
}
/* Get the amount of the bytes we need to allocate for the module's code as well as the required alignment. */
status = _txm_module_manager_util_code_allocation_size_and_alignment_get(module_preamble, &code_alignment, &code_allocation_size);
if (status != TX_SUCCESS)
{
/* Math overflow error occurred. */
return(status);
}
/* Allocate code memory for the module. */
status = _tx_byte_allocate(&_txm_module_manager_byte_pool, (VOID **) &code_memory_ptr, code_allocation_size, TX_NO_WAIT);
/* Determine if the module's code memory allocation was successful. */
if (status != TX_SUCCESS)
{
/* No memory, return an error. */
return(TX_NO_MEMORY);
}
/* Copy the module code into memory. */
source_ptr = (UCHAR *) module_location;
code_start = (ALIGN_TYPE) code_memory_ptr;
code_start = (code_start + (code_alignment - 1)) & ~(code_alignment - 1);
destination_ptr = (UCHAR *) code_start;
/* Calculate the size. */
copy_size = module_preamble -> txm_module_preamble_code_size;
/* Loop to copy the code to RAM. */
for (i = 0; i < copy_size; i++)
{
/* Copy one byte at a time. */
*destination_ptr++ = *source_ptr++;
}
/* At this point, the module's instruction area is now in the RAM code area. */
/* Now load it in-place. */
status = _txm_module_manager_internal_load(module_instance, module_name, (VOID *) code_start,
code_size, code_memory_ptr, code_allocation_size);
if (status != TX_SUCCESS)
{
/* Release code memory. */
_tx_byte_release(code_memory_ptr);
/* Return error. */
return(status);
}
/* Return success. */
return(TX_SUCCESS);
}

View File

@@ -0,0 +1,155 @@
/**************************************************************************/
/* */
/* 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 */
/** */
/** Module Manager */
/** */
/**************************************************************************/
/**************************************************************************/
#define TX_SOURCE_CODE
#include "txm_module.h"
/**************************************************************************/
/* */
/* FUNCTION RELEASE */
/* */
/* _txm_module_manager_object_allocate PORTABLE C */
/* 6.0.1 */
/* AUTHOR */
/* */
/* Scott Larson, Microsoft Corporation */
/* */
/* DESCRIPTION */
/* */
/* This function allocates memory for an object from the memory pool */
/* supplied to txm_module_manager_initialize. */
/* */
/* INPUT */
/* */
/* object_ptr Destination of object pointer on */
/* successful allocation */
/* object_size Size in bytes of the object to be */
/* allocated */
/* module_instance The module instance that the */
/* object belongs to */
/* */
/* OUTPUT */
/* */
/* status Completion status */
/* */
/* CALLS */
/* */
/* _txe_mutex_get Get module instance mutex */
/* _txe_mutex_put Release module instance mutex */
/* _txe_byte_allocate Allocate object from pool */
/* */
/* CALLED BY */
/* */
/* Application code */
/* */
/* RELEASE HISTORY */
/* */
/* DATE NAME DESCRIPTION */
/* */
/* 06-30-2020 Scott Larson Initial Version 6.0.1 */
/* */
/**************************************************************************/
UINT _txm_module_manager_object_allocate(VOID **object_ptr_ptr, ULONG object_size, TXM_MODULE_INSTANCE *module_instance)
{
TXM_MODULE_ALLOCATED_OBJECT *object_ptr;
UINT return_value;
/* Ensure the object pointer pointer is valid. */
if (object_ptr_ptr == (VOID **) TX_NULL)
{
/* The object pointer pointer is invalid, return an error. */
return(TXM_MODULE_INVALID_MEMORY);
}
/* Initialize the return pointer to NULL. */
*((VOID **) object_ptr_ptr) = TX_NULL;
/* Get module manager protection mutex. */
_txe_mutex_get(&_txm_module_manager_mutex, TX_WAIT_FOREVER);
/* Determine if an object pool was created. */
if (_txm_module_manager_object_pool_created)
{
TXM_MODULE_ALLOCATED_OBJECT *next_object, *previous_object;
/* Allocate the object requested by the module - adding an extra ULONG in order to
store the module instance pointer. */
return_value = (ULONG) _txe_byte_allocate(&_txm_module_manager_object_pool, (VOID **) &object_ptr,
(ULONG) (object_size + sizeof(TXM_MODULE_ALLOCATED_OBJECT)), TX_NO_WAIT);
/* Determine if the request was successful. */
if (return_value == TX_SUCCESS)
{
/* Yes, now store the module instance in the allocated memory block. */
/* Link the allocated memory to the module instance. */
if (module_instance -> txm_module_instance_object_list_count++ == 0)
{
/* The allocated object list is empty. Add object to empty list. */
module_instance -> txm_module_instance_object_list_head = object_ptr;
object_ptr -> txm_module_allocated_object_next = object_ptr;
object_ptr -> txm_module_allocated_object_previous = object_ptr;
}
else
{
/* This list is not NULL, add to the end of the list. */
next_object = module_instance -> txm_module_instance_object_list_head;
previous_object = next_object -> txm_module_allocated_object_previous;
/* Place the new object in the list. */
next_object -> txm_module_allocated_object_previous = object_ptr;
previous_object -> txm_module_allocated_object_next = object_ptr;
/* Setup this object's allocated links. */
object_ptr -> txm_module_allocated_object_previous = previous_object;
object_ptr -> txm_module_allocated_object_next = next_object;
}
/* Setup the module instance pointer in the allocated object. */
object_ptr -> txm_module_allocated_object_module_instance = module_instance;
/* Set the object size. */
object_ptr -> txm_module_object_size = object_size;
/* Move the object pointer forward. This is what the module is given. */
object_ptr++;
/* Return this pointer to the application. */
*((VOID **) object_ptr_ptr) = object_ptr;
}
}
else
{
/* Set return value to not enabled. */
return_value = TX_NOT_AVAILABLE;
}
/* Release the protection mutex. */
_txe_mutex_put(&_txm_module_manager_mutex);
return(return_value);
}

View File

@@ -0,0 +1,138 @@
/**************************************************************************/
/* */
/* 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 */
/** */
/** Module Manager */
/** */
/**************************************************************************/
/**************************************************************************/
#define TX_SOURCE_CODE
#include "tx_api.h"
#include "tx_thread.h"
#include "txm_module.h"
/**************************************************************************/
/* */
/* FUNCTION RELEASE */
/* */
/* _txm_module_manager_object_deallocate PORTABLE C */
/* 6.0.1 */
/* AUTHOR */
/* */
/* Scott Larson, Microsoft Corporation */
/* */
/* DESCRIPTION */
/* */
/* This function deallocates a previously allocated object. */
/* */
/* INPUT */
/* */
/* object_ptr Object pointer to deallocate */
/* */
/* OUTPUT */
/* */
/* status Completion status */
/* */
/* CALLS */
/* */
/* _txe_mutex_get Get module instance mutex */
/* _txe_mutex_put Release module instance mutex */
/* _txe_byte_release Release object back to pool */
/* */
/* */
/* CALLED BY */
/* */
/* Application code */
/* */
/* RELEASE HISTORY */
/* */
/* DATE NAME DESCRIPTION */
/* */
/* 06-30-2020 Scott Larson Initial Version 6.0.1 */
/* */
/**************************************************************************/
UINT _txm_module_manager_object_deallocate(VOID *object_ptr)
{
TXM_MODULE_INSTANCE *module_instance;
TXM_MODULE_ALLOCATED_OBJECT *module_allocated_object_ptr;
UINT return_value;
/* Get module manager protection mutex. */
_txe_mutex_get(&_txm_module_manager_mutex, TX_WAIT_FOREVER);
/* Determine if an object pool was created. */
if (_txm_module_manager_object_pool_created)
{
TXM_MODULE_ALLOCATED_OBJECT *next_object, *previous_object;
/* Pickup module instance pointer. */
module_instance = _tx_thread_current_ptr -> tx_thread_module_instance_ptr;
/* Setup the memory pointer. */
module_allocated_object_ptr = (TXM_MODULE_ALLOCATED_OBJECT *) object_ptr;
/* Position the object pointer backwards to position back to the module manager information. */
previous_object = module_allocated_object_ptr--;
/* Make sure the object is valid. */
if ((module_allocated_object_ptr == TX_NULL) || (module_allocated_object_ptr -> txm_module_allocated_object_module_instance != module_instance) || (module_instance -> txm_module_instance_object_list_count == 0))
{
/* Set return value to invalid pointer. */
return_value = TX_PTR_ERROR;
}
else
{
/* Unlink the node. */
if ((--module_instance -> txm_module_instance_object_list_count) == 0)
{
/* Only allocated object, just set the allocated list to NULL. */
module_instance -> txm_module_instance_object_list_head = TX_NULL;
}
else
{
/* Otherwise, not the only allocated object, link-up the neighbors. */
next_object = module_allocated_object_ptr -> txm_module_allocated_object_next;
previous_object = module_allocated_object_ptr -> txm_module_allocated_object_previous;
next_object -> txm_module_allocated_object_previous = previous_object;
previous_object -> txm_module_allocated_object_next = next_object;
/* See if we have to update the allocated object list head pointer. */
if (module_instance -> txm_module_instance_object_list_head == module_allocated_object_ptr)
{
/* Yes, move the head pointer to the next link. */
module_instance -> txm_module_instance_object_list_head = next_object;
}
}
/* Release the object memory. */
return_value = (ULONG) _txe_byte_release((VOID *) module_allocated_object_ptr);
}
}
else
{
/* Set return value to not enabled. */
return_value = TX_NOT_AVAILABLE;
}
/* Release the protection mutex. */
_txe_mutex_put(&_txm_module_manager_mutex);
return(return_value);
}

View File

@@ -0,0 +1,91 @@
/**************************************************************************/
/* */
/* 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 */
/** */
/** Module Manager */
/** */
/**************************************************************************/
/**************************************************************************/
#define TX_SOURCE_CODE
#include "txm_module.h"
#include "txm_module_manager_util.h"
/**************************************************************************/
/* */
/* FUNCTION RELEASE */
/* */
/* _txm_module_manager_object_pointer_get PORTABLE C */
/* 6.0.1 */
/* AUTHOR */
/* */
/* Scott Larson, Microsoft Corporation */
/* */
/* DESCRIPTION */
/* */
/* This function is deprecated and calls the secure version of this */
/* function (_txm_module_manager_object_pointer_get_extended) with the */
/* maximum possible name length since none was passed. */
/* */
/* INPUT */
/* */
/* object_type Type of object, as follows: */
/* */
/* TXM_BLOCK_POOL_OBJECT */
/* TXM_BYTE_POOL_OBJECT */
/* TXM_EVENT_FLAGS_OBJECT */
/* TXM_MUTEX_OBJECT */
/* TXM_QUEUE_OBJECT */
/* TXM_SEMAPHORE_OBJECT */
/* TXM_THREAD_OBJECT */
/* TXM_TIMER_OBJECT */
/* name Name to search for */
/* object_ptr Pointer to the object */
/* */
/* OUTPUT */
/* */
/* TX_SUCCESS Successful completion */
/* TX_PTR_ERROR Invalid name or object ptr */
/* TX_OPTION_ERROR Invalid option type */
/* TX_NO_INSTANCE Object not found */
/* */
/* CALLS */
/* */
/* _txm_module_manager_object_pointer_get_extended */
/* Secure version of this function */
/* */
/* CALLED BY */
/* */
/* Application code */
/* */
/* RELEASE HISTORY */
/* */
/* DATE NAME DESCRIPTION */
/* */
/* 06-30-2020 Scott Larson Initial Version 6.0.1 */
/* */
/**************************************************************************/
UINT _txm_module_manager_object_pointer_get(UINT object_type, CHAR *name, VOID **object_ptr)
{
UINT status;
/* Call the secure version of this function with the maximum length
possible since none was passed. */
status = _txm_module_manager_object_pointer_get_extended(object_type, name, TXM_MODULE_MANAGER_UTIL_MAX_VALUE_OF_TYPE_UNSIGNED(UINT), object_ptr);
return(status);
}

View File

@@ -0,0 +1,506 @@
/**************************************************************************/
/* */
/* 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 */
/** */
/** Module Manager */
/** */
/**************************************************************************/
/**************************************************************************/
#define TX_SOURCE_CODE
#include "tx_api.h"
#include "tx_initialize.h"
#include "tx_thread.h"
#include "tx_timer.h"
#include "tx_queue.h"
#include "tx_event_flags.h"
#include "tx_semaphore.h"
#include "tx_mutex.h"
#include "tx_block_pool.h"
#include "tx_byte_pool.h"
#include "txm_module.h"
#include "txm_module_manager_util.h"
/**************************************************************************/
/* */
/* FUNCTION RELEASE */
/* */
/* _txm_module_manager_object_pointer_get_extended PORTABLE C */
/* 6.0.1 */
/* AUTHOR */
/* */
/* Scott Larson, Microsoft Corporation */
/* */
/* DESCRIPTION */
/* */
/* This function retrieves the object pointer of a particular type */
/* with a particular name. If the object is not found, an error is */
/* returned. Otherwise, if the object is found, the address of that */
/* object is placed in object_ptr. */
/* */
/* INPUT */
/* */
/* object_type Type of object, as follows: */
/* */
/* TXM_BLOCK_POOL_OBJECT */
/* TXM_BYTE_POOL_OBJECT */
/* TXM_EVENT_FLAGS_OBJECT */
/* TXM_MUTEX_OBJECT */
/* TXM_QUEUE_OBJECT */
/* TXM_SEMAPHORE_OBJECT */
/* TXM_THREAD_OBJECT */
/* TXM_TIMER_OBJECT */
/* search_name Name to search for */
/* search_name_length Length of the name excluding */
/* null-terminator */
/* object_ptr Pointer to the object */
/* */
/* OUTPUT */
/* */
/* TX_SUCCESS Successful completion */
/* TX_PTR_ERROR Invalid name or object ptr */
/* TX_OPTION_ERROR Invalid option type */
/* TX_NO_INSTANCE Object not found */
/* */
/* CALLS */
/* */
/* _txm_module_manager_object_name_compare */
/* String compare routine */
/* [_txm_module_manager_*_object_pointer_get] */
/* Optional external component */
/* object pointer get */
/* */
/* CALLED BY */
/* */
/* Application code */
/* */
/* RELEASE HISTORY */
/* */
/* DATE NAME DESCRIPTION */
/* */
/* 06-30-2020 Scott Larson Initial Version 6.0.1 */
/* */
/**************************************************************************/
UINT _txm_module_manager_object_pointer_get_extended(UINT object_type, CHAR *search_name, UINT search_name_length, VOID **object_ptr)
{
TX_INTERRUPT_SAVE_AREA
TX_THREAD *thread_ptr;
TX_TIMER *timer_ptr;
TX_QUEUE *queue_ptr;
TX_EVENT_FLAGS_GROUP *events_ptr;
TX_SEMAPHORE *semaphore_ptr;
TX_MUTEX *mutex_ptr;
TX_BLOCK_POOL *block_pool_ptr;
TX_BYTE_POOL *byte_pool_ptr;
ULONG i;
UINT status;
TXM_MODULE_INSTANCE *module_instance;
/* Determine if the name or object pointer are NULL. */
if ((search_name == TX_NULL) || (object_ptr == TX_NULL))
{
/* Return error! */
return(TX_PTR_ERROR);
}
/* Default status to not found. */
status = TX_NO_INSTANCE;
/* Set the return value to NULL. */
*object_ptr = TX_NULL;
/* Disable interrupts. */
TX_DISABLE
/* Temporarily disable preemption. This will keep other threads from creating and deleting threads. */
_tx_thread_preempt_disable++;
/* Restore interrupts. */
TX_RESTORE
/* Process relative to the object type. */
switch(object_type)
{
/* Determine if a thread object is requested. */
case TXM_THREAD_OBJECT:
{
/* Loop to find the first matching thread. */
i = 0;
thread_ptr = _tx_thread_created_ptr;
while (i < _tx_thread_created_count)
{
/* Do we have a match? */
if (_txm_module_manager_object_name_compare(search_name, search_name_length, thread_ptr -> tx_thread_name))
{
/* Yes, we found it - return the necessary info! */
*object_ptr = (VOID *) thread_ptr;
/* Set the the status to success! */
status = TX_SUCCESS;
break;
}
/* Increment the counter. */
i++;
/* Move to next thread. */
thread_ptr = thread_ptr -> tx_thread_created_next;
}
break;
}
/* Determine if a timer object is requested. */
case TXM_TIMER_OBJECT:
{
/* Loop to find the first matching timer. */
i = 0;
timer_ptr = _tx_timer_created_ptr;
while (i < _tx_timer_created_count)
{
/* Do we have a match? */
if (_txm_module_manager_object_name_compare(search_name, search_name_length, timer_ptr -> tx_timer_name))
{
/* Yes, we found it - return the necessary info! */
*object_ptr = (VOID *) timer_ptr;
/* Set the the status to success! */
status = TX_SUCCESS;
break;
}
/* Increment the counter. */
i++;
/* Move to next timer. */
timer_ptr = timer_ptr -> tx_timer_created_next;
}
break;
}
/* Determine if a queue object is requested. */
case TXM_QUEUE_OBJECT:
{
/* Loop to find the first matching queue. */
i = 0;
queue_ptr = _tx_queue_created_ptr;
while (i < _tx_queue_created_count)
{
/* Do we have a match? */
if (_txm_module_manager_object_name_compare(search_name, search_name_length, queue_ptr -> tx_queue_name))
{
/* Yes, we found it - return the necessary info! */
*object_ptr = (VOID *) queue_ptr;
/* Set the the status to success! */
status = TX_SUCCESS;
break;
}
/* Increment the counter. */
i++;
/* Move to next queue. */
queue_ptr = queue_ptr -> tx_queue_created_next;
}
break;
}
/* Determine if a event flags object is requested. */
case TXM_EVENT_FLAGS_OBJECT:
{
/* Loop to find the first matching event flags group. */
i = 0;
events_ptr = _tx_event_flags_created_ptr;
while (i < _tx_event_flags_created_count)
{
/* Do we have a match? */
if (_txm_module_manager_object_name_compare(search_name, search_name_length, events_ptr -> tx_event_flags_group_name))
{
/* Yes, we found it - return the necessary info! */
*object_ptr = (VOID *) events_ptr;
/* Set the the status to success! */
status = TX_SUCCESS;
break;
}
/* Increment the counter. */
i++;
/* Move to next event flags group. */
events_ptr = events_ptr -> tx_event_flags_group_created_next;
}
break;
}
/* Determine if a semaphore object is requested. */
case TXM_SEMAPHORE_OBJECT:
{
/* Loop to find the first matching semaphore. */
i = 0;
semaphore_ptr = _tx_semaphore_created_ptr;
while (i < _tx_semaphore_created_count)
{
/* Do we have a match? */
if (_txm_module_manager_object_name_compare(search_name, search_name_length, semaphore_ptr -> tx_semaphore_name))
{
/* Yes, we found it - return the necessary info! */
*object_ptr = (VOID *) semaphore_ptr;
/* Set the the status to success! */
status = TX_SUCCESS;
break;
}
/* Increment the counter. */
i++;
/* Move to next semaphore. */
semaphore_ptr = semaphore_ptr -> tx_semaphore_created_next;
}
break;
}
/* Determine if a mutex object is requested. */
case TXM_MUTEX_OBJECT:
{
/* Loop to find the first matching mutex. */
i = 0;
mutex_ptr = _tx_mutex_created_ptr;
while (i < _tx_mutex_created_count)
{
/* Do we have a match? */
if (_txm_module_manager_object_name_compare(search_name, search_name_length, mutex_ptr -> tx_mutex_name))
{
/* Yes, we found it - return the necessary info! */
*object_ptr = (VOID *) mutex_ptr;
/* Set the the status to success! */
status = TX_SUCCESS;
break;
}
/* Increment the counter. */
i++;
/* Move to next mutex. */
mutex_ptr = mutex_ptr -> tx_mutex_created_next;
}
break;
}
/* Determine if a block pool object is requested. */
case TXM_BLOCK_POOL_OBJECT:
{
/* Get the module instance. */
module_instance = _tx_thread_current_ptr -> tx_thread_module_instance_ptr;
/* Is a module making this request? */
if (module_instance != TX_NULL)
{
/* Is memory protection enabled? */
if (module_instance -> txm_module_instance_property_flags & TXM_MODULE_MEMORY_PROTECTION)
{
/* Modules with memory protection can only access block pools they created. */
status = TXM_MODULE_INVALID;
break;
}
}
/* Loop to find the first matching block pool. */
i = 0;
block_pool_ptr = _tx_block_pool_created_ptr;
while (i < _tx_block_pool_created_count)
{
/* Do we have a match? */
if (_txm_module_manager_object_name_compare(search_name, search_name_length, block_pool_ptr -> tx_block_pool_name))
{
/* Yes, we found it - return the necessary info! */
*object_ptr = (VOID *) block_pool_ptr;
/* Set the the status to success! */
status = TX_SUCCESS;
break;
}
/* Increment the counter. */
i++;
/* Move to next block pool. */
block_pool_ptr = block_pool_ptr -> tx_block_pool_created_next;
}
break;
}
/* Determine if a byte pool object is requested. */
case TXM_BYTE_POOL_OBJECT:
{
/* Get the module instance. */
module_instance = _tx_thread_current_ptr -> tx_thread_module_instance_ptr;
/* Is a module making this request? */
if (module_instance != TX_NULL)
{
/* Is memory protection enabled? */
if (module_instance -> txm_module_instance_property_flags & TXM_MODULE_MEMORY_PROTECTION)
{
/* Modules with memory protection can only access block pools they created. */
status = TXM_MODULE_INVALID;
break;
}
}
/* Loop to find the first matching byte pool. */
i = 0;
byte_pool_ptr = _tx_byte_pool_created_ptr;
while (i < _tx_byte_pool_created_count)
{
/* Do we have a match? */
if (_txm_module_manager_object_name_compare(search_name, search_name_length, byte_pool_ptr -> tx_byte_pool_name))
{
/* Yes, we found it - return the necessary info! */
*object_ptr = (VOID *) byte_pool_ptr;
/* Set the the status to success! */
status = TX_SUCCESS;
break;
}
/* Increment the counter. */
i++;
/* Move to next byte pool. */
byte_pool_ptr = byte_pool_ptr -> tx_byte_pool_created_next;
}
break;
}
default:
/* Invalid object ID. */
status = TX_OPTION_ERROR;
/* External Object pointer get. */
#ifdef TXM_MODULE_ENABLE_NETX
/* Determine if there is a NetX object get request. */
if ((object_type >= TXM_NETX_OBJECTS_START) && (object_type < TXM_NETX_OBJECTS_END))
{
/* Call the NetX module object get function. */
status = _txm_module_manager_netx_object_pointer_get(object_type, search_name, search_name_length, object_ptr);
}
#endif
#ifdef TXM_MODULE_ENABLE_NETXDUO
/* Determine if there is a NetX Duo object get request. */
if ((object_type >= TXM_NETXDUO_OBJECTS_START) && (object_type < TXM_NETXDUO_OBJECTS_END))
{
/* Call the NetX Duo module object get function. */
status = _txm_module_manager_netxduo_object_pointer_get(object_type, search_name, search_name_length, object_ptr);
}
#endif
#ifdef TXM_MODULE_ENABLE_FILEX
/* Determine if there is a FileX object get request. */
if ((object_type >= TXM_FILEX_OBJECTS_START) && (object_type < TXM_FILEX_OBJECTS_END))
{
/* Call the FileX module object get function. */
status = _txm_module_manager_filex_object_pointer_get(object_type, search_name, search_name_length, object_ptr);
}
#endif
#ifdef TXM_MODULE_ENABLE_GUIX
/* Determine if there is a GUIX object get request. */
if ((object_type >= TXM_GUIX_OBJECTS_START) && (object_type < TXM_GUIX_OBJECTS_END))
{
/* Call the GUIX module object get function. */
status = _txm_module_manager_guix_object_pointer_get(object_type, search_name, search_name_length, object_ptr);
}
#endif
#ifdef TXM_MODULE_ENABLE_USBX
/* Determine if there is a USBX object get request. */
if ((object_type >= TXM_USBX_OBJECTS_START) && (object_type < TXM_USBX_OBJECTS_END))
{
/* Call the USBX object get function. */
status = _txm_module_manager_usbx_object_pointer_get(object_type, search_name, search_name_length, object_ptr);
}
#endif
break;
}
/* Disable interrupts. */
TX_DISABLE
/* Enable preemption again. */
_tx_thread_preempt_disable--;
/* Restore interrupts. */
TX_RESTORE
/* Check for preemption. */
_tx_thread_system_preempt_check();
/* Return success. */
return(status);
}

View File

@@ -0,0 +1,82 @@
/**************************************************************************/
/* */
/* 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 */
/** */
/** Module Manager */
/** */
/**************************************************************************/
/**************************************************************************/
#define TX_SOURCE_CODE
#include "tx_api.h"
#include "txm_module.h"
#include "tx_byte_pool.h"
/**************************************************************************/
/* */
/* FUNCTION RELEASE */
/* */
/* txm_module_manager_object_pool_create PORTABLE C */
/* 6.0.1 */
/* AUTHOR */
/* */
/* Scott Larson, Microsoft Corporation */
/* */
/* DESCRIPTION */
/* */
/* This function creates an object pool for the module manager, */
/* which is used by modules to allocate system resources outside */
/* the memory area of the module. This is especially useful in */
/* memory protection. */
/* */
/* INPUT */
/* */
/* object_memory Object memory address */
/* object_memory_size Size in bytes of memory area */
/* */
/* OUTPUT */
/* */
/* status Completion status */
/* */
/* CALLS */
/* */
/* _tx_byte_pool_create Create module memory byte pool */
/* */
/* CALLED BY */
/* */
/* Application code */
/* */
/* RELEASE HISTORY */
/* */
/* DATE NAME DESCRIPTION */
/* */
/* 06-30-2020 Scott Larson Initial Version 6.0.1 */
/* */
/**************************************************************************/
UINT _txm_module_manager_object_pool_create(VOID *object_memory, ULONG object_memory_size)
{
/* Create a byte pool for allocating RAM areas for modules. */
_tx_byte_pool_create(&_txm_module_manager_object_pool, "Module Manager Object Pool", object_memory, object_memory_size);
/* Indicate the module manager object pool has been created. */
_txm_module_manager_object_pool_created = TX_TRUE;
/* Return success. */
return(TX_SUCCESS);
}

View File

@@ -0,0 +1,106 @@
/**************************************************************************/
/* */
/* 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 */
/** */
/** Module Manager */
/** */
/**************************************************************************/
/**************************************************************************/
#define TX_SOURCE_CODE
#include "txm_module.h"
/**************************************************************************/
/* */
/* FUNCTION RELEASE */
/* */
/* _txm_module_manager_properties_get PORTABLE C */
/* 6.0.1 */
/* AUTHOR */
/* */
/* Scott Larson, Microsoft Corporation */
/* */
/* DESCRIPTION */
/* */
/* This function returns the properties of the specified module so they*/
/* may be checked before executing the module. */
/* */
/* INPUT */
/* */
/* module_instance Module instance pointer */
/* */
/* OUTPUT */
/* */
/* status Completion status */
/* */
/* CALLS */
/* */
/* None */
/* */
/* CALLED BY */
/* */
/* Application code */
/* */
/* RELEASE HISTORY */
/* */
/* DATE NAME DESCRIPTION */
/* */
/* 06-30-2020 Scott Larson Initial Version 6.0.1 */
/* */
/**************************************************************************/
UINT _txm_module_manager_properties_get(TXM_MODULE_INSTANCE *module_instance, ULONG *module_properties_ptr)
{
/* Determine if the module manager has not been initialized yet. */
if (_txm_module_manager_ready != TX_TRUE)
{
/* Module manager has not been initialized. */
return(TX_NOT_AVAILABLE);
}
/* Determine if the module is valid. */
if (module_instance == TX_NULL)
{
/* Invalid module pointer. */
return(TX_PTR_ERROR);
}
/* Check the module ID. */
if (module_instance -> txm_module_instance_id != TXM_MODULE_ID)
{
/* Invalid module pointer. */
return(TX_PTR_ERROR);
}
/* Check for non-null buffer. */
if (module_properties_ptr == TX_NULL)
{
/* Invalid buffer pointer. */
return(TX_PTR_ERROR);
}
/* Simply return the property bitmap. */
*module_properties_ptr = module_instance -> txm_module_instance_property_flags;
/* Return success. */
return(TX_SUCCESS);
}

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 */
/** */
/** Module Manager */
/** */
/**************************************************************************/
/**************************************************************************/
#define TX_SOURCE_CODE
#include "tx_api.h"
#include "tx_queue.h"
#include "tx_thread.h"
#include "txm_module.h"
#ifndef TX_DISABLE_NOTIFY_CALLBACKS
/**************************************************************************/
/* */
/* FUNCTION RELEASE */
/* */
/* _txm_module_manager_queue_notify_trampoline PORTABLE C */
/* 6.0.1 */
/* AUTHOR */
/* */
/* Scott Larson, Microsoft Corporation */
/* */
/* DESCRIPTION */
/* */
/* This function processes the queue notification call from ThreadX. */
/* */
/* INPUT */
/* */
/* queue_ptr Queue pointer */
/* */
/* OUTPUT */
/* */
/* None */
/* */
/* CALLS */
/* */
/* _txm_module_manager_callback_request Send module callback request */
/* */
/* CALLED BY */
/* */
/* ThreadX */
/* */
/* RELEASE HISTORY */
/* */
/* DATE NAME DESCRIPTION */
/* */
/* 06-30-2020 Scott Larson Initial Version 6.0.1 */
/* */
/**************************************************************************/
VOID _txm_module_manager_queue_notify_trampoline(TX_QUEUE *queue_ptr)
{
TX_INTERRUPT_SAVE_AREA
TXM_MODULE_INSTANCE *module_instance;
TXM_MODULE_CALLBACK_MESSAGE callback_message;
TX_QUEUE *module_callback_queue;
/* We now know the callback is for a module. */
/* Disable interrupts. */
TX_DISABLE
/* Pickup the module instance pointer. */
module_instance = (TXM_MODULE_INSTANCE *) queue_ptr -> tx_queue_module_instance;
/* Determine if this module is still valid. */
if ((module_instance) && (module_instance -> txm_module_instance_id == TXM_MODULE_ID) &&
(module_instance -> txm_module_instance_state == TXM_MODULE_STARTED))
{
/* Yes, the module is still valid. */
/* Pickup the module's callback message queue. */
module_callback_queue = &(module_instance -> txm_module_instance_callback_request_queue);
/* Build the queue notification message. */
callback_message.txm_module_callback_message_type = TXM_QUEUE_SEND_CALLBACK;
callback_message.txm_module_callback_message_activation_count = 1;
callback_message.txm_module_callback_message_application_function = (VOID (*)(VOID)) queue_ptr -> tx_queue_send_module_notify;
callback_message.txm_module_callback_message_param_1 = (ALIGN_TYPE) queue_ptr;
callback_message.txm_module_callback_message_param_2 = 0;
callback_message.txm_module_callback_message_param_3 = 0;
callback_message.txm_module_callback_message_param_4 = 0;
callback_message.txm_module_callback_message_param_5 = 0;
callback_message.txm_module_callback_message_param_6 = 0;
callback_message.txm_module_callback_message_param_7 = 0;
callback_message.txm_module_callback_message_param_8 = 0;
callback_message.txm_module_callback_message_reserved1 = 0;
callback_message.txm_module_callback_message_reserved2 = 0;
/* Restore interrupts. */
TX_RESTORE
/* Call the general processing that will place the callback on the
module's callback request queue. */
_txm_module_manager_callback_request(module_callback_queue, &callback_message);
}
else
{
/* Module no longer valid. */
/* Error, increment the error counter and return. */
_txm_module_manager_callback_error_count++;
/* Restore interrupts. */
TX_RESTORE
}
}
#endif

View File

@@ -0,0 +1,131 @@
/**************************************************************************/
/* */
/* 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 */
/** */
/** Module Manager */
/** */
/**************************************************************************/
/**************************************************************************/
#define TX_SOURCE_CODE
#include "tx_api.h"
#include "tx_queue.h"
#include "tx_thread.h"
#include "txm_module.h"
#ifndef TX_DISABLE_NOTIFY_CALLBACKS
/**************************************************************************/
/* */
/* FUNCTION RELEASE */
/* */
/* _txm_module_manager_semaphore_notify_trampoline PORTABLE C */
/* 6.0.1 */
/* AUTHOR */
/* */
/* Scott Larson, Microsoft Corporation */
/* */
/* DESCRIPTION */
/* */
/* This function processes the semaphore put notification call from */
/* ThreadX. */
/* */
/* INPUT */
/* */
/* semaphore_ptr Semaphore pointer */
/* */
/* OUTPUT */
/* */
/* None */
/* */
/* CALLS */
/* */
/* _txm_module_manager_callback_request Send module callback request */
/* */
/* CALLED BY */
/* */
/* ThreadX */
/* */
/* RELEASE HISTORY */
/* */
/* DATE NAME DESCRIPTION */
/* */
/* 06-30-2020 Scott Larson Initial Version 6.0.1 */
/* */
/**************************************************************************/
VOID _txm_module_manager_semaphore_notify_trampoline(TX_SEMAPHORE *semaphore_ptr)
{
TX_INTERRUPT_SAVE_AREA
TXM_MODULE_INSTANCE *module_instance;
TXM_MODULE_CALLBACK_MESSAGE callback_message;
TX_QUEUE *module_callback_queue;
/* We now know the callback is for a module. */
/* Disable interrupts. */
TX_DISABLE
/* Pickup the module instance pointer. */
module_instance = (TXM_MODULE_INSTANCE *) semaphore_ptr -> tx_semaphore_module_instance;
/* Determine if this module is still valid. */
if ((module_instance) && (module_instance -> txm_module_instance_id == TXM_MODULE_ID) &&
(module_instance -> txm_module_instance_state == TXM_MODULE_STARTED))
{
/* Yes, the module is still valid. */
/* Pickup the module's callback message queue. */
module_callback_queue = &(module_instance -> txm_module_instance_callback_request_queue);
/* Build the queue notification message. */
callback_message.txm_module_callback_message_type = TXM_SEMAPHORE_PUT_CALLBACK;
callback_message.txm_module_callback_message_activation_count = 1;
callback_message.txm_module_callback_message_application_function = (VOID (*)(VOID)) semaphore_ptr -> tx_semaphore_put_module_notify;
callback_message.txm_module_callback_message_param_1 = (ALIGN_TYPE) semaphore_ptr;
callback_message.txm_module_callback_message_param_2 = 0;
callback_message.txm_module_callback_message_param_3 = 0;
callback_message.txm_module_callback_message_param_4 = 0;
callback_message.txm_module_callback_message_param_5 = 0;
callback_message.txm_module_callback_message_param_6 = 0;
callback_message.txm_module_callback_message_param_7 = 0;
callback_message.txm_module_callback_message_param_8 = 0;
callback_message.txm_module_callback_message_reserved1 = 0;
callback_message.txm_module_callback_message_reserved2 = 0;
/* Restore interrupts. */
TX_RESTORE
/* Call the general processing that will place the callback on the
module's callback request queue. */
_txm_module_manager_callback_request(module_callback_queue, &callback_message);
}
else
{
/* Module no longer valid. */
/* Error, increment the error counter and return. */
_txm_module_manager_callback_error_count++;
/* Restore interrupts. */
TX_RESTORE
}
}
#endif

View File

@@ -0,0 +1,226 @@
/**************************************************************************/
/* */
/* 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 */
/** */
/** Module Manager */
/** */
/**************************************************************************/
/**************************************************************************/
#define TX_SOURCE_CODE
#include "tx_api.h"
#include "tx_mutex.h"
#include "tx_queue.h"
#include "tx_thread.h"
#include "txm_module.h"
/**************************************************************************/
/* */
/* FUNCTION RELEASE */
/* */
/* _txm_module_manager_start PORTABLE C */
/* 6.0.1 */
/* AUTHOR */
/* */
/* Scott Larson, Microsoft Corporation */
/* */
/* DESCRIPTION */
/* */
/* This function starts execution of the specified module. */
/* */
/* INPUT */
/* */
/* module_instance Module instance pointer */
/* */
/* OUTPUT */
/* */
/* status Completion status */
/* */
/* CALLS */
/* */
/* _txm_module_manager_name_build Build module:thread name */
/* _txm_module_manager_thread_create Module thread create */
/* _tx_mutex_get Get protection mutex */
/* _tx_mutex_put Release protection mutex */
/* _tx_queue_create Create module callback queue */
/* _tx_queue_delete Delete module callback queue */
/* _tx_thread_resume Resume start thread */
/* */
/* CALLED BY */
/* */
/* Application code */
/* */
/* RELEASE HISTORY */
/* */
/* DATE NAME DESCRIPTION */
/* */
/* 06-30-2020 Scott Larson Initial Version 6.0.1 */
/* */
/**************************************************************************/
UINT _txm_module_manager_start(TXM_MODULE_INSTANCE *module_instance)
{
UINT status;
/* Determine if the module manager has not been initialized yet. */
if (_txm_module_manager_ready != TX_TRUE)
{
/* Module manager has not been initialized. */
return(TX_NOT_AVAILABLE);
}
/* Determine if the module is valid. */
if (module_instance == TX_NULL)
{
/* Invalid module pointer. */
return(TX_PTR_ERROR);
}
/* Get module manager protection mutex. */
_tx_mutex_get(&_txm_module_manager_mutex, TX_WAIT_FOREVER);
/* Determine if the module instance is valid. */
if (module_instance -> txm_module_instance_id != TXM_MODULE_ID)
{
/* Release the protection mutex. */
_tx_mutex_put(&_txm_module_manager_mutex);
/* Invalid module pointer. */
return(TX_PTR_ERROR);
}
/* Determine if the module instance is in the loaded state. */
if ((module_instance -> txm_module_instance_state != TXM_MODULE_LOADED) && (module_instance -> txm_module_instance_state != TXM_MODULE_STOPPED))
{
/* Release the protection mutex. */
_tx_mutex_put(&_txm_module_manager_mutex);
/* Return error if the module is not ready. */
return(TX_START_ERROR);
}
/* Check the priorities of the start/stop and callback request threads. */
if (module_instance -> txm_module_instance_start_stop_priority < module_instance -> txm_module_instance_maximum_priority ||
module_instance -> txm_module_instance_callback_priority < module_instance -> txm_module_instance_maximum_priority)
{
/* Release the protection mutex. */
_tx_mutex_put(&_txm_module_manager_mutex);
/* At least one thread has an invalid priority. */
return(TX_PRIORITY_ERROR);
}
/* Create the module's callback request queue. */
status = _tx_queue_create(&(module_instance -> txm_module_instance_callback_request_queue), "Module Callback Request Queue", (sizeof(TXM_MODULE_CALLBACK_MESSAGE)/sizeof(ULONG)),
module_instance -> txm_module_instance_callback_request_queue_area, sizeof(module_instance -> txm_module_instance_callback_request_queue_area));
/* Determine if there was an error. */
if (status)
{
/* Release the protection mutex. */
_tx_mutex_put(&_txm_module_manager_mutex);
/* Return error if the module is not ready. */
return(TX_START_ERROR);
}
/* Create the module start thread. */
status = _txm_module_manager_thread_create(&(module_instance -> txm_module_instance_start_stop_thread),
"Module Start Thread",
module_instance -> txm_module_instance_shell_entry_function,
module_instance -> txm_module_instance_start_thread_entry,
module_instance -> txm_module_instance_application_module_id,
module_instance -> txm_module_instance_start_stop_stack_start_address,
module_instance -> txm_module_instance_start_stop_stack_size,
(UINT) module_instance -> txm_module_instance_start_stop_priority,
(UINT) module_instance -> txm_module_instance_start_stop_priority,
TXM_MODULE_TIME_SLICE,
TX_DONT_START,
sizeof(TX_THREAD),
module_instance);
/* Determine if the thread create was successful. */
if (status != TX_SUCCESS)
{
/* Delete the callback notification queue. */
_tx_queue_delete(&(module_instance -> txm_module_instance_callback_request_queue));
/* Release the protection mutex. */
_tx_mutex_put(&_txm_module_manager_mutex);
/* Return the error status. */
return(status);
}
/* Create the module callback thread. */
status = _txm_module_manager_thread_create(&(module_instance -> txm_module_instance_callback_request_thread),
"Module Callback Request Thread",
module_instance -> txm_module_instance_shell_entry_function,
module_instance -> txm_module_instance_callback_request_thread_entry,
module_instance -> txm_module_instance_application_module_id,
module_instance -> txm_module_instance_callback_stack_start_address,
module_instance -> txm_module_instance_callback_stack_size,
(UINT) module_instance -> txm_module_instance_callback_priority,
(UINT) module_instance -> txm_module_instance_callback_priority,
TX_NO_TIME_SLICE,
TX_DONT_START,
sizeof(TX_THREAD),
module_instance);
/* Determine if the thread create was successful. */
if (status != TX_SUCCESS)
{
/* Terminate the start thread. */
_tx_thread_terminate(&(module_instance -> txm_module_instance_start_stop_thread));
/* Delete the start thread. */
_tx_thread_delete(&(module_instance -> txm_module_instance_start_stop_thread));
/* Delete the callback notification queue. */
_tx_queue_delete(&(module_instance -> txm_module_instance_callback_request_queue));
/* Release the protection mutex. */
_tx_mutex_put(&_txm_module_manager_mutex);
/* Return the error status. */
return(status);
}
/* Set the module state to started. */
module_instance -> txm_module_instance_state = TXM_MODULE_STARTED;
/* Release the protection mutex. */
_tx_mutex_put(&_txm_module_manager_mutex);
/* Resume the module's start thread. */
_tx_thread_resume(&(module_instance -> txm_module_instance_start_stop_thread));
/* Return success. */
return(TX_SUCCESS);
}

View File

@@ -0,0 +1,571 @@
/**************************************************************************/
/* */
/* 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 */
/** */
/** Module Manager */
/** */
/**************************************************************************/
/**************************************************************************/
#define TX_SOURCE_CODE
#include "tx_api.h"
#include "tx_initialize.h"
#include "tx_thread.h"
#include "tx_timer.h"
#include "tx_queue.h"
#include "tx_event_flags.h"
#include "tx_semaphore.h"
#include "tx_mutex.h"
#include "tx_block_pool.h"
#include "tx_byte_pool.h"
#include "txm_module.h"
#include "txm_module_manager_util.h"
#ifdef TXM_MODULE_ENABLE_FILEX
extern UINT _txm_module_manager_filex_stop(TXM_MODULE_INSTANCE *module_instance);
#endif
#ifdef TXM_MODULE_ENABLE_NETX
extern UINT _txm_module_manager_netx_stop(TXM_MODULE_INSTANCE *module_instance);
#endif
#ifdef TXM_MODULE_ENABLE_NETXDUO
extern UINT _txm_module_manager_netxduo_stop(TXM_MODULE_INSTANCE *module_instance);
#endif
#ifdef TXM_MODULE_ENABLE_GUIX
extern UINT _txm_module_manager_guix_stop(TXM_MODULE_INSTANCE *module_instance);
#endif
#ifdef TXM_MODULE_ENABLE_USBX
extern UINT _txm_module_manager_usbx_stop(TXM_MODULE_INSTANCE *module_instance);
#endif
/**************************************************************************/
/* */
/* FUNCTION RELEASE */
/* */
/* _txm_module_manager_stop PORTABLE C */
/* 6.0.1 */
/* AUTHOR */
/* */
/* Scott Larson, Microsoft Corporation */
/* */
/* DESCRIPTION */
/* */
/* This function stops execution of the specified module. */
/* */
/* INPUT */
/* */
/* module_instance Module instance pointer */
/* */
/* OUTPUT */
/* */
/* status Completion status */
/* */
/* CALLS */
/* */
/* _tx_block_pool_delete Block pool delete */
/* _tx_byte_pool_delete Byte pool delete */
/* _tx_event_flags_delete Event flags delete */
/* _tx_mutex_delete Mutex delete */
/* _tx_mutex_get Get protection mutex */
/* _tx_mutex_put Release protection mutex */
/* _tx_queue_delete Queue delete */
/* _tx_semaphore_delete Semaphore delete */
/* _tx_thread_delete Thread delete */
/* _tx_thread_sleep Thread sleep */
/* _tx_thread_system_preempt_check Check for preemption */
/* _tx_thread_terminate Thread terminate */
/* _tx_timer_delete Timer delete */
/* _txm_module_manager_callback_deactivate */
/* Deactivate callback */
/* _txm_module_manager_object_search Search for object in module's */
/* allocated object list */
/* _txm_module_manager_thread_create Module thread create */
/* [_txm_module_manager_*_stop] Optional external component */
/* stop functions */
/* */
/* CALLED BY */
/* */
/* Application code */
/* */
/* RELEASE HISTORY */
/* */
/* DATE NAME DESCRIPTION */
/* */
/* 06-30-2020 Scott Larson Initial Version 6.0.1 */
/* */
/**************************************************************************/
UINT _txm_module_manager_stop(TXM_MODULE_INSTANCE *module_instance)
{
TX_INTERRUPT_SAVE_AREA
TX_THREAD *thread_ptr, *next_thread_ptr;
TX_TIMER *timer_ptr, *next_timer_ptr;
TX_QUEUE *queue_ptr, *next_queue_ptr;
TX_EVENT_FLAGS_GROUP *events_ptr, *next_events_ptr;
TX_SEMAPHORE *semaphore_ptr, *next_semaphore_ptr;
TX_MUTEX *mutex_ptr, *next_mutex_ptr;
TX_BLOCK_POOL *block_pool_ptr, *next_block_pool_ptr;
TX_BYTE_POOL *byte_pool_ptr, *next_byte_pool_ptr;
UCHAR created_by_module;
ULONG i;
TXM_MODULE_ALLOCATED_OBJECT *object_ptr;
/* Pickup thread pointer. */
TX_THREAD_GET_CURRENT(thread_ptr)
/* Determine if this is a legal request. */
/* Is there a current thread? */
if (thread_ptr == TX_NULL)
{
/* Illegal caller of this service. */
return(TX_CALLER_ERROR);
}
/* Is the caller an ISR or Initialization? */
if (TX_THREAD_GET_SYSTEM_STATE() != 0)
{
/* Illegal caller of this service. */
return(TX_CALLER_ERROR);
}
#ifndef TX_TIMER_PROCESS_IN_ISR
/* Check for invalid caller of this function. First check for a calling thread. */
if (thread_ptr == &_tx_timer_thread)
{
/* Invalid caller of this function, return appropriate error code. */
return(TX_CALLER_ERROR);
}
#endif
/* Determine if the module manager has not been initialized yet. */
if (_txm_module_manager_ready != TX_TRUE)
{
/* Module manager has not been initialized. */
return(TX_NOT_AVAILABLE);
}
/* Determine if the module is valid. */
if (module_instance == TX_NULL)
{
/* Invalid module pointer. */
return(TX_PTR_ERROR);
}
/* Get module manager protection mutex. */
_tx_mutex_get(&_txm_module_manager_mutex, TX_WAIT_FOREVER);
/* Determine if the module instance is valid. */
if (module_instance -> txm_module_instance_id != TXM_MODULE_ID)
{
/* Release the protection mutex. */
_tx_mutex_put(&_txm_module_manager_mutex);
/* Invalid module pointer. */
return(TX_PTR_ERROR);
}
/* Determine if the module instance is in the loaded state. */
if (module_instance -> txm_module_instance_state != TXM_MODULE_STARTED)
{
/* Release the protection mutex. */
_tx_mutex_put(&_txm_module_manager_mutex);
/* Return error if the module is not ready. */
return(TX_START_ERROR);
}
/* Set the module state to indicate the module is stopping. */
module_instance -> txm_module_instance_state = TXM_MODULE_STOPPING;
/* This thread was previously used as the start thread. So first, make sure it is terminated and deleted before doing anything else. */
_tx_thread_terminate(&(module_instance -> txm_module_instance_start_stop_thread));
_tx_thread_delete(&(module_instance -> txm_module_instance_start_stop_thread));
/* Determine if there is a module stop function. */
if (module_instance -> txm_module_instance_stop_thread_entry)
{
/* Yes, there is a stop function. Build a thread for executing the module stop function. */
/* Create the module stop thread. */
_txm_module_manager_thread_create(&(module_instance -> txm_module_instance_start_stop_thread),
"Module Stop Thread",
module_instance -> txm_module_instance_shell_entry_function,
module_instance -> txm_module_instance_stop_thread_entry,
module_instance -> txm_module_instance_application_module_id,
module_instance -> txm_module_instance_start_stop_stack_start_address,
module_instance -> txm_module_instance_start_stop_stack_size,
(UINT) module_instance -> txm_module_instance_start_stop_priority,
(UINT) module_instance -> txm_module_instance_start_stop_priority,
TXM_MODULE_TIME_SLICE,
TX_AUTO_START,
sizeof(TX_THREAD),
module_instance);
/* Wait for the stop thread to complete. */
i = 0;
while ((i < TXM_MODULE_TIMEOUT) && (module_instance -> txm_module_instance_start_stop_thread.tx_thread_state != TX_COMPLETED))
{
/* Sleep to let the module stop thread run. */
_tx_thread_sleep(1);
/* Increment the counter. */
i++;
}
/* At this point, we need to terminate and delete the stop thread. */
_tx_thread_terminate(&(module_instance -> txm_module_instance_start_stop_thread));
_tx_thread_delete(&(module_instance -> txm_module_instance_start_stop_thread));
}
/* Delete the module's callback thread and queue for the callback thread. */
_tx_thread_terminate(&(module_instance -> txm_module_instance_callback_request_thread));
_tx_thread_delete(&(module_instance -> txm_module_instance_callback_request_thread));
_tx_queue_delete(&(module_instance -> txm_module_instance_callback_request_queue));
/* Disable interrupts. */
TX_DISABLE
/* Temporarily disable preemption. This will keep other threads from creating and deleting threads. */
_tx_thread_preempt_disable++;
/* Restore interrupts. */
TX_RESTORE
/* Determine if any external component stop functions have been registered and
if so, call them to cleanup any module objects in that component. */
#ifdef TXM_MODULE_ENABLE_FILEX
/* Call the FileX stop function. */
_txm_module_manager_filex_stop(module_instance);
#endif
#ifdef TXM_MODULE_ENABLE_NETX
/* Call the NetX stop function. */
_txm_module_manager_netx_stop(module_instance);
#endif
#ifdef TXM_MODULE_ENABLE_NETXDUO
/* Call the NetX Duo stop function. */
_txm_module_manager_netxduo_stop(module_instance);
#endif
#ifdef TXM_MODULE_ENABLE_GUIX
/* Call the GUIX stop function. */
_txm_module_manager_guix_stop(module_instance);
#endif
#ifdef TXM_MODULE_ENABLE_USBX
/* Call the USBX stop function. */
_txm_module_manager_usbx_stop(module_instance);
#endif
/* Loop to delete any and all threads created by the module. */
i = _tx_thread_created_count;
thread_ptr = _tx_thread_created_ptr;
while (i--)
{
/* Pickup the next thread pointer. */
next_thread_ptr = thread_ptr -> tx_thread_created_next;
/* Determine if the thread control block is inside the module. */
if ( (((CHAR *) thread_ptr) >= ((CHAR *) module_instance -> txm_module_instance_data_start)) &&
(((CHAR *) thread_ptr) < ((CHAR *) module_instance -> txm_module_instance_data_end)))
{
/* Terminate and delete this thread, since it is part of this module. */
_tx_thread_terminate(thread_ptr);
_tx_thread_delete(thread_ptr);
}
/* Is this thread part of the module? */
else if (thread_ptr -> tx_thread_module_instance_ptr == module_instance)
{
/* Terminate and delete this thread, since it is part of this module. */
_tx_thread_terminate(thread_ptr);
_tx_thread_delete(thread_ptr);
}
/* Move to next thread. */
thread_ptr = next_thread_ptr;
}
/* Loop to delete any and all timers created by the module. */
i = _tx_timer_created_count;
timer_ptr = _tx_timer_created_ptr;
while (i--)
{
/* Pickup the next timer pointer. */
next_timer_ptr = timer_ptr -> tx_timer_created_next;
/* Check if this module created this timer. */
created_by_module = _txm_module_manager_created_object_check(module_instance, (VOID *) timer_ptr);
if (created_by_module == TX_TRUE)
{
/* Delete this timer, since it is part of this module. */
_tx_timer_delete(timer_ptr);
}
/* Move to next timer. */
timer_ptr = next_timer_ptr;
}
/* Loop to delete any and all queues created by the module. */
i = _tx_queue_created_count;
queue_ptr = _tx_queue_created_ptr;
while (i--)
{
/* Pickup the next queue pointer. */
next_queue_ptr = queue_ptr -> tx_queue_created_next;
#ifndef TX_DISABLE_NOTIFY_CALLBACKS
/* Determine if the queue callback function is associated with this module. */
if ((queue_ptr -> tx_queue_module_instance == module_instance) &&
(queue_ptr -> tx_queue_send_notify == _txm_module_manager_queue_notify_trampoline))
{
/* Clear the callback notification for this queue since it is no longer valid. */
queue_ptr -> tx_queue_send_notify = TX_NULL;
}
#endif
/* Check if this module created this queue. */
created_by_module = _txm_module_manager_created_object_check(module_instance, (VOID *) queue_ptr);
if (created_by_module == TX_TRUE)
{
/* Delete this queue, since it is part of this module. */
_tx_queue_delete(queue_ptr);
}
/* Move to next queue. */
queue_ptr = next_queue_ptr;
}
/* Loop to delete any and all event flag groups created by the module. */
i = _tx_event_flags_created_count;
events_ptr = _tx_event_flags_created_ptr;
while (i--)
{
/* Pickup the next event flags group pointer. */
next_events_ptr = events_ptr -> tx_event_flags_group_created_next;
#ifndef TX_DISABLE_NOTIFY_CALLBACKS
/* Determine if the event flags callback function is associated with this module. */
if ((events_ptr -> tx_event_flags_group_module_instance == module_instance) &&
(events_ptr -> tx_event_flags_group_set_notify == _txm_module_manager_event_flags_notify_trampoline))
{
/* Clear the callback notification for this event flag group since it is no longer valid. */
events_ptr -> tx_event_flags_group_set_notify = TX_NULL;
}
#endif
/* Check if this module created this event flags. */
created_by_module = _txm_module_manager_created_object_check(module_instance, (VOID *) events_ptr);
if (created_by_module == TX_TRUE)
{
/* Delete this event flags group, since it is part of this module. */
_tx_event_flags_delete(events_ptr);
}
/* Move to next event flags group. */
events_ptr = next_events_ptr;
}
/* Loop to delete any and all semaphores created by the module. */
i = _tx_semaphore_created_count;
semaphore_ptr = _tx_semaphore_created_ptr;
while (i--)
{
/* Pickup the next semaphore pointer. */
next_semaphore_ptr = semaphore_ptr -> tx_semaphore_created_next;
#ifndef TX_DISABLE_NOTIFY_CALLBACKS
/* Determine if the semaphore callback function is associated with this module. */
if ((semaphore_ptr -> tx_semaphore_module_instance == module_instance) &&
(semaphore_ptr -> tx_semaphore_put_notify == _txm_module_manager_semaphore_notify_trampoline))
{
/* Clear the callback notification for this semaphore since it is no longer valid. */
semaphore_ptr -> tx_semaphore_put_notify = TX_NULL;
}
#endif
/* Check if this module created this semaphore. */
created_by_module = _txm_module_manager_created_object_check(module_instance, (VOID *) semaphore_ptr);
if (created_by_module == TX_TRUE)
{
/* Delete this semaphore, since it is part of this module. */
_tx_semaphore_delete(semaphore_ptr);
}
/* Move to next semaphore. */
semaphore_ptr = next_semaphore_ptr;
}
/* Loop to delete any and all mutexes created by the module. */
i = _tx_mutex_created_count;
mutex_ptr = _tx_mutex_created_ptr;
while (i--)
{
/* Pickup the next mutex pointer. */
next_mutex_ptr = mutex_ptr -> tx_mutex_created_next;
/* Check if this module created this mutex. */
created_by_module = _txm_module_manager_created_object_check(module_instance, (VOID *) mutex_ptr);
if (created_by_module == TX_TRUE)
{
/* Delete this mutex, since it is part of this module. */
_tx_mutex_delete(mutex_ptr);
}
/* Move to next mutex. */
mutex_ptr = next_mutex_ptr;
}
/* Loop to delete any and all block pools created by the module. */
i = _tx_block_pool_created_count;
block_pool_ptr = _tx_block_pool_created_ptr;
while (i--)
{
/* Pickup the next block pool pointer. */
next_block_pool_ptr = block_pool_ptr -> tx_block_pool_created_next;
/* Check if this module created this block pool. */
created_by_module = _txm_module_manager_created_object_check(module_instance, (VOID *) block_pool_ptr);
if (created_by_module == TX_TRUE)
{
/* Delete this block pool, since it is part of this module. */
_tx_block_pool_delete(block_pool_ptr);
}
/* Move to next block pool. */
block_pool_ptr = next_block_pool_ptr;
}
/* Loop to delete any and all byte pools created by the module. */
i = _tx_byte_pool_created_count;
byte_pool_ptr = _tx_byte_pool_created_ptr;
while (i--)
{
/* Pickup the next byte pool pointer. */
next_byte_pool_ptr = byte_pool_ptr -> tx_byte_pool_created_next;
/* Check if this module created this byte pool. */
created_by_module = _txm_module_manager_created_object_check(module_instance, (VOID *) byte_pool_ptr);
if (created_by_module == TX_TRUE)
{
/* Delete this byte pool, since it is part of this module. */
_tx_byte_pool_delete(byte_pool_ptr);
}
/* Move to next byte pool. */
byte_pool_ptr = next_byte_pool_ptr;
}
#ifdef TX_ENABLE_EVENT_TRACE
/* Has trace been enabled? */
if (_tx_trace_buffer_current_ptr != TX_NULL)
{
/* Is the trace buffer located inside the module? */
if ((ULONG) _tx_trace_header_ptr -> tx_trace_header_buffer_start_pointer >= (ULONG) module_instance -> txm_module_instance_data_start &&
(ULONG) _tx_trace_header_ptr -> tx_trace_header_buffer_start_pointer < (ULONG) module_instance -> txm_module_instance_data_end)
{
_tx_trace_disable();
}
}
#endif
/* Delete the allocated objects for this module. */
while (module_instance -> txm_module_instance_object_list_count--)
{
/* Pickup the current object pointer. */
object_ptr = module_instance -> txm_module_instance_object_list_head;
/* Move the head pointer forward. */
module_instance -> txm_module_instance_object_list_head = object_ptr -> txm_module_allocated_object_next;
/* Release the object. */
_tx_byte_release((VOID *) object_ptr);
}
/* Set the allocated list head pointer to NULL. */
module_instance -> txm_module_instance_object_list_head = TX_NULL;
/* Disable interrupts. */
TX_DISABLE
/* Enable preemption again. */
_tx_thread_preempt_disable--;
/* Set the module state to indicate the module is stopped. */
module_instance -> txm_module_instance_state = TXM_MODULE_STOPPED;
/* Restore interrupts. */
TX_RESTORE
/* Release the protection mutex. */
_tx_mutex_put(&_txm_module_manager_mutex);
/* Check for preemption. */
_tx_thread_system_preempt_check();
/* Return success. */
return(TX_SUCCESS);
}

View File

@@ -0,0 +1,585 @@
/**************************************************************************/
/* */
/* 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 */
/** */
/** Module Manager */
/** */
/**************************************************************************/
/**************************************************************************/
#define TX_SOURCE_CODE
#include "tx_api.h"
#include "tx_trace.h"
#include "tx_initialize.h"
#include "tx_thread.h"
#include "tx_timer.h"
#include "txm_module.h"
/**************************************************************************/
/* */
/* FUNCTION RELEASE */
/* */
/* _txm_module_manager_thread_create PORTABLE C */
/* 6.0.1 */
/* AUTHOR */
/* */
/* Scott Larson, Microsoft Corporation */
/* */
/* DESCRIPTION */
/* */
/* This function creates a thread and places it on the list of created */
/* threads. */
/* */
/* INPUT */
/* */
/* thread_ptr Thread control block pointer */
/* name Pointer to thread name string */
/* shell_function Shell function of the thread */
/* entry_function Entry function of the thread */
/* entry_input 32-bit input value to thread */
/* stack_start Pointer to start of stack */
/* stack_size Stack size in bytes */
/* priority Priority of thread */
/* (default 0-31) */
/* preempt_threshold Preemption threshold */
/* time_slice Thread time-slice value */
/* auto_start Automatic start selection */
/* */
/* OUTPUT */
/* */
/* status Completion status */
/* */
/* CALLS */
/* */
/* _txm_module_manager_thread_stack_build Build initial thread stack */
/* _tx_thread_system_resume Resume automatic start thread */
/* _tx_thread_system_ni_resume Noninterruptable resume thread*/
/* _tx_thread_system_preempt_check Check for preemption */
/* */
/* CALLED BY */
/* */
/* _txm_module_manager_start Initiate module's start thread*/
/* _txm_module_manager_stop Initiate module's stop thread */
/* _txm_module_manager_kernel_dispatch Kernel dispatch function */
/* */
/* RELEASE HISTORY */
/* */
/* DATE NAME DESCRIPTION */
/* */
/* 06-30-2020 Scott Larson Initial Version 6.0.1 */
/* */
/**************************************************************************/
UINT _txm_module_manager_thread_create(TX_THREAD *thread_ptr, CHAR *name, VOID (*shell_function)(TX_THREAD *, TXM_MODULE_INSTANCE *),
VOID (*entry_function)(ULONG), ULONG entry_input,
VOID *stack_start, ULONG stack_size, UINT priority, UINT preempt_threshold,
ULONG time_slice, UINT auto_start, UINT thread_control_block_size, TXM_MODULE_INSTANCE *module_instance)
{
TX_INTERRUPT_SAVE_AREA
TX_THREAD *next_thread;
TX_THREAD *previous_thread;
#ifndef TX_DISABLE_PREEMPTION_THRESHOLD
TX_THREAD *saved_thread_ptr;
UINT saved_threshold = 0;
#endif
#ifdef TX_ENABLE_STACK_CHECKING
ULONG new_stack_start;
#endif
TXM_MODULE_THREAD_ENTRY_INFO *thread_entry_info;
VOID *stack_end;
ULONG i;
#ifndef TX_TIMER_PROCESS_IN_ISR
TX_THREAD *current_thread;
#endif
#if TXM_MODULE_MEMORY_PROTECTION
ULONG status;
#endif
/* First, check for an invalid thread pointer. */
if (thread_ptr == TX_NULL)
{
/* Thread pointer is invalid, return appropriate error code. */
return(TX_THREAD_ERROR);
}
/* Now check for invalid thread control block size. */
else if (thread_control_block_size != (sizeof(TX_THREAD)))
{
/* Thread pointer is invalid, return appropriate error code. */
return(TX_THREAD_ERROR);
}
/* Disable interrupts. */
TX_DISABLE
/* Increment the preempt disable flag. */
_tx_thread_preempt_disable++;
/* Restore interrupts. */
TX_RESTORE
/* Next see if it is already in the created list. */
next_thread = _tx_thread_created_ptr;
stack_end = (VOID *) (((UCHAR *) ((VOID *) stack_start)) + (stack_size - 1));
for (i = 0; i < _tx_thread_created_count; i++)
{
/* Determine if this thread matches the thread in the list. */
if (thread_ptr == next_thread)
{
break;
}
/* Check the stack pointer to see if it overlaps with this thread's stack. */
/*lint -e{946} suppress pointer comparison, since this is necessary. */
if (((UCHAR *) ((VOID *) stack_start)) >= ((UCHAR *) ((VOID *) next_thread -> tx_thread_stack_start)))
{
/*lint -e{946} suppress pointer comparison, since this is necessary. */
if (((UCHAR *) ((VOID *) stack_start)) < ((UCHAR *) ((VOID *) next_thread -> tx_thread_stack_end)))
{
/* This stack overlaps with an existing thread, clear the stack pointer to
force a stack error below. */
stack_start = TX_NULL;
break;
}
}
/* Check the end of the stack to see if it is inside this thread's stack area as well. */
/*lint -e{946} suppress pointer comparison, since this is necessary. */
if (((UCHAR *) ((VOID *) stack_end)) >= ((UCHAR *) ((VOID *) next_thread -> tx_thread_stack_start)))
{
/*lint -e{946} suppress pointer comparison, since this is necessary. */
if (((UCHAR *) ((VOID *) stack_end)) < ((UCHAR *) ((VOID *) next_thread -> tx_thread_stack_end)))
{
/* This stack overlaps with an existing thread, clear the stack pointer to
force a stack error below. */
stack_start = TX_NULL;
break;
}
}
/* Move to the next thread. */
next_thread = next_thread -> tx_thread_created_next;
}
/* Disable interrupts. */
TX_DISABLE
/* Decrement the preempt disable flag. */
_tx_thread_preempt_disable--;
/* Restore interrupts. */
TX_RESTORE
/* Check for preemption. */
_tx_thread_system_preempt_check();
/* At this point, check to see if there is a duplicate thread. */
if (thread_ptr == next_thread)
{
/* Thread is already created, return appropriate error code. */
return(TX_THREAD_ERROR);
}
/* Check for invalid starting address of stack. */
if (stack_start == TX_NULL)
{
/* Invalid stack or entry point, return appropriate error code. */
return(TX_PTR_ERROR);
}
/* Check for invalid thread entry point. */
if (entry_function == TX_NULL)
{
/* Invalid stack or entry point, return appropriate error code. */
return(TX_PTR_ERROR);
}
/* Check the stack size. */
if (stack_size < TX_MINIMUM_STACK)
{
/* Stack is not big enough, return appropriate error code. */
return(TX_SIZE_ERROR);
}
/* Check the priority specified. */
if (priority >= TX_MAX_PRIORITIES)
{
/* Invalid priority selected, return appropriate error code. */
return(TX_PRIORITY_ERROR);
}
/* Check preemption threshold. */
if (preempt_threshold > priority)
{
/* Invalid preempt threshold, return appropriate error code. */
return(TX_THRESH_ERROR);
}
/* Check the start selection. */
if (auto_start > TX_AUTO_START)
{
/* Invalid auto start selection, return appropriate error code. */
return(TX_START_ERROR);
}
#ifndef TX_TIMER_PROCESS_IN_ISR
/* Pickup thread pointer. */
TX_THREAD_GET_CURRENT(current_thread)
/* Check for invalid caller of this function. First check for a calling thread. */
if (current_thread == &_tx_timer_thread)
{
/* Invalid caller of this function, return appropriate error code. */
return(TX_CALLER_ERROR);
}
#endif
/* Check for interrupt call. */
if (TX_THREAD_GET_SYSTEM_STATE() != 0)
{
/* Now, make sure the call is from an interrupt and not initialization. */
if (TX_THREAD_GET_SYSTEM_STATE() < TX_INITIALIZE_IN_PROGRESS)
{
/* Invalid caller of this function, return appropriate error code. */
return(TX_CALLER_ERROR);
}
}
#ifndef TX_DISABLE_STACK_FILLING
/* Set the thread stack to a pattern prior to creating the initial
stack frame. This pattern is used by the stack checking routines
to see how much has been used. */
TX_MEMSET(stack_start, ((UCHAR) TX_STACK_FILL), stack_size);
#endif
#ifdef TX_ENABLE_STACK_CHECKING
/* Ensure that there are two ULONG of 0xEF patterns at the top and
bottom of the thread's stack. This will be used to check for stack
overflow conditions during run-time. */
stack_size = ((stack_size/sizeof(ULONG)) * sizeof(ULONG)) - sizeof(ULONG);
/* Ensure the starting stack address is evenly aligned. */
new_stack_start = ((((ULONG) stack_start) + (sizeof(ULONG) - 1) ) & (~(sizeof(ULONG) - 1)));
/* Determine if the starting stack address is different. */
if (new_stack_start != ((ULONG) stack_start))
{
/* Yes, subtract another ULONG from the size to avoid going past the stack area. */
stack_size = stack_size - sizeof(ULONG);
}
/* Update the starting stack pointer. */
stack_start = (VOID *) new_stack_start;
#endif
/* Allocate the thread entry information at the top of thread's stack - Leaving one
ULONG worth of 0xEF pattern between the actual stack and the entry info structure. */
stack_size = stack_size - (sizeof(TXM_MODULE_THREAD_ENTRY_INFO) + (3*sizeof(ULONG)));
/* Prepare the thread control block prior to placing it on the created
list. */
/* Initialize thread control block to all zeros. */
TX_MEMSET(thread_ptr, 0, sizeof(TX_THREAD));
#if TXM_MODULE_MEMORY_PROTECTION
/* If this is a memory protected module, allocate a kernel stack. */
if((module_instance -> txm_module_instance_property_flags) & TXM_MODULE_MEMORY_PROTECTION)
{
/* Allocate kernel stack space. */
status = _txm_module_manager_object_allocate((VOID **) &(thread_ptr -> tx_thread_module_kernel_stack_start), TXM_MODULE_KERNEL_STACK_SIZE, module_instance);
if(status)
{
return(status);
}
#ifndef TX_DISABLE_STACK_FILLING
/* Set the thread stack to a pattern prior to creating the initial
stack frame. This pattern is used by the stack checking routines
to see how much has been used. */
TX_MEMSET(thread_ptr -> tx_thread_module_kernel_stack_start, ((UCHAR) TX_STACK_FILL), TXM_MODULE_KERNEL_STACK_SIZE);
#endif
/* Align kernel stack pointer. */
thread_ptr -> tx_thread_module_kernel_stack_end = (VOID *) (((ALIGN_TYPE)(thread_ptr -> tx_thread_module_kernel_stack_start) + TXM_MODULE_KERNEL_STACK_SIZE) & ~0x07);
/* Set kernel stack size. */
thread_ptr -> tx_thread_module_kernel_stack_size = TXM_MODULE_KERNEL_STACK_SIZE;
}
/* Place the stack parameters into the thread's control block. */
thread_ptr -> tx_thread_module_stack_start = stack_start;
thread_ptr -> tx_thread_module_stack_size = stack_size;
#endif
/* Place the supplied parameters into the thread's control block. */
thread_ptr -> tx_thread_name = name;
thread_ptr -> tx_thread_entry = entry_function;
thread_ptr -> tx_thread_entry_parameter = entry_input;
thread_ptr -> tx_thread_stack_start = stack_start;
thread_ptr -> tx_thread_stack_size = stack_size;
thread_ptr -> tx_thread_stack_end = (VOID *) (((UCHAR *) stack_start) + (stack_size-1));
#if TXM_MODULE_MEMORY_PROTECTION
thread_ptr -> tx_thread_module_stack_end = thread_ptr -> tx_thread_stack_end;
#endif
thread_ptr -> tx_thread_priority = priority;
thread_ptr -> tx_thread_user_priority = priority;
thread_ptr -> tx_thread_time_slice = time_slice;
thread_ptr -> tx_thread_new_time_slice = time_slice;
thread_ptr -> tx_thread_inherit_priority = TX_MAX_PRIORITIES;
#ifndef TX_DISABLE_PREEMPTION_THRESHOLD
/* Preemption-threshold is enabled, setup accordingly. */
thread_ptr -> tx_thread_preempt_threshold = preempt_threshold;
thread_ptr -> tx_thread_user_preempt_threshold = preempt_threshold;
#else
/* Preemption-threshold is disabled, determine if preemption-threshold was required. */
if (priority != preempt_threshold)
{
/* Preemption-threshold specified. Since specific preemption-threshold is not supported,
disable all preemption. */
thread_ptr -> tx_thread_preempt_threshold = 0;
thread_ptr -> tx_thread_user_preempt_threshold = 0;
}
else
{
/* Preemption-threshold is not specified, just setup with the priority. */
thread_ptr -> tx_thread_preempt_threshold = priority;
thread_ptr -> tx_thread_user_preempt_threshold = priority;
}
#endif
/* Now fill in the values that are required for thread initialization. */
thread_ptr -> tx_thread_state = TX_SUSPENDED;
/* Setup the necessary fields in the thread timer block. */
TX_THREAD_CREATE_TIMEOUT_SETUP(thread_ptr)
/* Setup pointer to the thread entry information structure, which will live at the top of each
module thread's stack. This will allow the module thread entry function to avoid direct
access to the actual thread control block. */
thread_entry_info = (TXM_MODULE_THREAD_ENTRY_INFO *) (((UCHAR *) thread_ptr -> tx_thread_stack_end) + (2*sizeof(ULONG)) + 1);
thread_entry_info = (TXM_MODULE_THREAD_ENTRY_INFO *) (((ALIGN_TYPE)(thread_entry_info)) & (~0x3));
/* Build the thread entry information structure. */
thread_entry_info -> txm_module_thread_entry_info_thread = thread_ptr;
thread_entry_info -> txm_module_thread_entry_info_module = module_instance;
thread_entry_info -> txm_module_thread_entry_info_data_base_address = module_instance -> txm_module_instance_module_data_base_address;
thread_entry_info -> txm_module_thread_entry_info_code_base_address = module_instance -> txm_module_instance_code_start;
thread_entry_info -> txm_module_thread_entry_info_entry = thread_ptr -> tx_thread_entry;
thread_entry_info -> txm_module_thread_entry_info_parameter = thread_ptr -> tx_thread_entry_parameter;
thread_entry_info -> txm_module_thread_entry_info_callback_request_queue = &(module_instance -> txm_module_instance_callback_request_queue);
thread_entry_info -> txm_module_thread_entry_info_callback_request_thread = &(module_instance -> txm_module_instance_callback_request_thread);
/* Populate thread control block with some stock information from the module. */
TXM_MODULE_MANAGER_THREAD_SETUP(thread_ptr, module_instance)
#ifndef TX_DISABLE_NOTIFY_CALLBACKS
thread_entry_info -> txm_module_thread_entry_info_exit_notify = thread_ptr -> tx_thread_entry_exit_notify;
#else
thread_entry_info -> txm_module_thread_entry_info_exit_notify = TX_NULL;
#endif
if (thread_ptr -> tx_thread_entry == module_instance -> txm_module_instance_start_thread_entry)
thread_entry_info -> txm_module_thread_entry_info_start_thread = TX_TRUE;
else
thread_entry_info -> txm_module_thread_entry_info_start_thread = TX_FALSE;
/* Place pointers to the thread info and module instance in the thread control block. */
thread_ptr -> tx_thread_module_instance_ptr = (VOID *) module_instance;
thread_ptr -> tx_thread_module_entry_info_ptr = (VOID *) thread_entry_info;
/* Place the thread entry information pointer in the thread control block so it can be picked up
in the following stack build function. This is supplied to the module's shell entry function
to avoid direct access to the actual thread control block. Note that this is overwritten
with the actual stack pointer at the end of stack build. */
thread_ptr -> tx_thread_stack_ptr = (VOID *) thread_entry_info;
/* Call the target specific stack frame building routine to build the
thread's initial stack and to setup the actual stack pointer in the
control block. */
_txm_module_manager_thread_stack_build(thread_ptr, shell_function);
#ifdef TX_ENABLE_STACK_CHECKING
/* Setup the highest usage stack pointer. */
thread_ptr -> tx_thread_stack_highest_ptr = thread_ptr -> tx_thread_stack_ptr;
#endif
/* Prepare to make this thread a member of the created thread list. */
TX_DISABLE
/* Load the thread ID field in the thread control block. */
thread_ptr -> tx_thread_id = TX_THREAD_ID;
/* Place the thread on the list of created threads. First,
check for an empty list. */
if (_tx_thread_created_count++ == 0)
{
/* The created thread list is empty. Add thread to empty list. */
_tx_thread_created_ptr = thread_ptr;
thread_ptr -> tx_thread_created_next = thread_ptr;
thread_ptr -> tx_thread_created_previous = thread_ptr;
}
else
{
/* This list is not NULL, add to the end of the list. */
next_thread = _tx_thread_created_ptr;
previous_thread = next_thread -> tx_thread_created_previous;
/* Place the new thread in the list. */
next_thread -> tx_thread_created_previous = thread_ptr;
previous_thread -> tx_thread_created_next = thread_ptr;
/* Setup this thread's created links. */
thread_ptr -> tx_thread_created_previous = previous_thread;
thread_ptr -> tx_thread_created_next = next_thread;
}
/* If trace is enabled, register this object. */
TX_TRACE_OBJECT_REGISTER(TX_TRACE_OBJECT_TYPE_THREAD, thread_ptr, name, stack_start, stack_size)
/* If trace is enabled, insert this event into the trace buffer. */
TX_TRACE_IN_LINE_INSERT(TX_TRACE_THREAD_CREATE, thread_ptr, priority, stack_start, stack_size, TX_TRACE_THREAD_EVENTS)
/* Register thread in the thread array structure. */
TX_EL_THREAD_REGISTER(thread_ptr)
/* Log this kernel call. */
TX_EL_THREAD_CREATE_INSERT
/* Determine if an automatic start was requested. If so, call the resume
thread function and then check for a preemption condition. */
if (auto_start == TX_AUTO_START)
{
#ifndef TX_DISABLE_PREEMPTION_THRESHOLD
/* Determine if the create call is being called from initialization. */
if (TX_THREAD_GET_SYSTEM_STATE() >= TX_INITIALIZE_IN_PROGRESS)
{
/* Yes, this create call was made from initialization. */
/* Pickup the current thread execute pointer, which corresponds to the
highest priority thread ready to execute. Interrupt lockout is
not required, since interrupts are assumed to be disabled during
initialization. */
saved_thread_ptr = _tx_thread_execute_ptr;
/* Determine if there is thread ready for execution. */
if (saved_thread_ptr != TX_NULL)
{
/* Yes, a thread is ready for execution when initialization completes. */
/* Save the current preemption-threshold. */
saved_threshold = saved_thread_ptr -> tx_thread_preempt_threshold;
/* For initialization, temporarily set the preemption-threshold to the
priority level to make sure the highest-priority thread runs once
initialization is complete. */
saved_thread_ptr -> tx_thread_preempt_threshold = saved_thread_ptr -> tx_thread_priority;
}
}
else
{
/* Simply set the saved thread pointer to NULL. */
saved_thread_ptr = TX_NULL;
}
#endif
#ifdef TX_NOT_INTERRUPTABLE
/* Perform any additional activities for tool or user purpose. */
TX_THREAD_CREATE_EXTENSION(thread_ptr)
/* Resume the thread! */
_tx_thread_system_ni_resume(thread_ptr);
/* Restore previous interrupt posture. */
TX_RESTORE
#else
/* Temporarily disable preemption. */
_tx_thread_preempt_disable++;
/* Restore previous interrupt posture. */
TX_RESTORE
/* Perform any additional activities for tool or user purpose. */
TX_THREAD_CREATE_EXTENSION(thread_ptr)
/* Call the resume thread function to make this thread ready. */
_tx_thread_system_resume(thread_ptr);
#endif
#ifndef TX_DISABLE_PREEMPTION_THRESHOLD
/* Determine if the thread's preemption-threshold needs to be restored. */
if (saved_thread_ptr != TX_NULL)
{
/* Yes, restore the previous highest-priority thread's preemption-threshold. This
can only happen if this routine is called from initialization. */
saved_thread_ptr -> tx_thread_preempt_threshold = saved_threshold;
}
#endif
/* Interrupts are already restored, simply return success. */
return(TX_SUCCESS);
}
/* Restore interrupts. */
TX_RESTORE
/* Return success. */
return(TX_SUCCESS);
}

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 */
/** */
/** Module Manager */
/** */
/**************************************************************************/
/**************************************************************************/
#define TX_SOURCE_CODE
#include "tx_api.h"
#include "tx_queue.h"
#include "tx_thread.h"
#include "txm_module.h"
#ifndef TX_DISABLE_NOTIFY_CALLBACKS
/**************************************************************************/
/* */
/* FUNCTION RELEASE */
/* */
/* _txm_module_manager_thread_notify_trampoline PORTABLE C */
/* 6.0.1 */
/* AUTHOR */
/* */
/* Scott Larson, Microsoft Corporation */
/* */
/* DESCRIPTION */
/* */
/* This function processes the thread entry/exit notification call */
/* from ThreadX. */
/* */
/* INPUT */
/* */
/* thread_ptr Thread pointer */
/* type Entry or exit type */
/* */
/* OUTPUT */
/* */
/* None */
/* */
/* CALLS */
/* */
/* _txm_module_manager_callback_request Send module callback request */
/* */
/* CALLED BY */
/* */
/* ThreadX */
/* */
/* RELEASE HISTORY */
/* */
/* DATE NAME DESCRIPTION */
/* */
/* 06-30-2020 Scott Larson Initial Version 6.0.1 */
/* */
/**************************************************************************/
VOID _txm_module_manager_thread_notify_trampoline(TX_THREAD *thread_ptr, UINT type)
{
TX_INTERRUPT_SAVE_AREA
TXM_MODULE_INSTANCE *module_instance;
TXM_MODULE_CALLBACK_MESSAGE callback_message;
TX_QUEUE *module_callback_queue;
TXM_MODULE_THREAD_ENTRY_INFO *thread_info;
/* We now know the callback is for a module. */
/* Disable interrupts. */
TX_DISABLE
/* Determine if the thread is valid. */
if ((thread_ptr) && (thread_ptr -> tx_thread_id == TX_THREAD_ID))
{
/* Pickup the module instance pointer. */
module_instance = (TXM_MODULE_INSTANCE *) thread_ptr -> tx_thread_module_instance_ptr;
/* Pickup the module's thread pointer. */
thread_info = (TXM_MODULE_THREAD_ENTRY_INFO *) thread_ptr -> tx_thread_module_entry_info_ptr;
/* Determine if this module is still valid. */
if ((module_instance) && (module_instance -> txm_module_instance_id == TXM_MODULE_ID) &&
(module_instance -> txm_module_instance_state == TXM_MODULE_STARTED))
{
/* Yes, the module is still valid. */
/* Pickup the module's callback message queue. */
module_callback_queue = &(module_instance -> txm_module_instance_callback_request_queue);
/* Build the queue notification message. */
callback_message.txm_module_callback_message_type = TXM_THREAD_ENTRY_EXIT_CALLBACK;
callback_message.txm_module_callback_message_activation_count = 1;
callback_message.txm_module_callback_message_application_function = (VOID (*)(VOID)) thread_info -> txm_module_thread_entry_info_exit_notify;
callback_message.txm_module_callback_message_param_1 = (ALIGN_TYPE) thread_ptr;
callback_message.txm_module_callback_message_param_2 = (ALIGN_TYPE) type;
callback_message.txm_module_callback_message_param_3 = 0;
callback_message.txm_module_callback_message_param_4 = 0;
callback_message.txm_module_callback_message_param_5 = 0;
callback_message.txm_module_callback_message_param_6 = 0;
callback_message.txm_module_callback_message_param_7 = 0;
callback_message.txm_module_callback_message_param_8 = 0;
callback_message.txm_module_callback_message_reserved1 = 0;
callback_message.txm_module_callback_message_reserved2 = 0;
/* Restore interrupts. */
TX_RESTORE
/* Call the general processing that will place the callback on the
module's callback request queue. */
_txm_module_manager_callback_request(module_callback_queue, &callback_message);
}
else
{
/* Module no longer valid. */
/* Error, increment the error counter and return. */
_txm_module_manager_callback_error_count++;
/* Restore interrupts. */
TX_RESTORE
}
}
else
{
/* Thread pointer is not valid. */
/* Error, increment the error counter and return. */
_txm_module_manager_callback_error_count++;
/* Restore interrupts. */
TX_RESTORE
}
}
#endif

View File

@@ -0,0 +1,180 @@
/**************************************************************************/
/* */
/* 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 */
/** */
/** Module Manager */
/** */
/**************************************************************************/
/**************************************************************************/
#define TX_SOURCE_CODE
#include "tx_api.h"
#include "tx_trace.h"
#include "tx_thread.h"
#include "txm_module.h"
/**************************************************************************/
/* */
/* FUNCTION RELEASE */
/* */
/* _txm_module_manager_thread_reset PORTABLE C */
/* 6.0.1 */
/* AUTHOR */
/* */
/* Scott Larson, Microsoft Corporation */
/* */
/* DESCRIPTION */
/* */
/* This function prepares the thread to run again from the entry */
/* point specified during thread creation. The application must */
/* call tx_thread_resume after this call completes for the thread */
/* to actually run. */
/* */
/* INPUT */
/* */
/* thread_ptr Pointer to thread to reset */
/* */
/* OUTPUT */
/* */
/* status Service return status */
/* */
/* CALLS */
/* */
/* _txm_module_manager_thread_stack_build Build initial thread */
/* stack */
/* */
/* CALLED BY */
/* */
/* _txm_module_manager_kernel_dispatch Kernel dispatch function */
/* */
/* RELEASE HISTORY */
/* */
/* DATE NAME DESCRIPTION */
/* */
/* 06-30-2020 Scott Larson Initial Version 6.0.1 */
/* */
/**************************************************************************/
UINT _txm_module_manager_thread_reset(TX_THREAD *thread_ptr)
{
TX_INTERRUPT_SAVE_AREA
TX_THREAD *current_thread;
UINT status;
TXM_MODULE_INSTANCE *module_instance;
TXM_MODULE_THREAD_ENTRY_INFO *thread_entry_info;
/* Default a successful completion status. */
status = TX_SUCCESS;
/* Disable interrupts. */
TX_DISABLE
/* Pickup thread pointer. */
TX_THREAD_GET_CURRENT(current_thread)
/* Check for a call from the current thread, which is not allowed! */
if (current_thread == thread_ptr)
{
/* Restore interrupts. */
TX_RESTORE
/* Thread not completed or terminated - return an error! */
status = TX_NOT_DONE;
}
else
{
/* Check for proper status of this thread to reset. */
if (thread_ptr -> tx_thread_state != TX_COMPLETED)
{
/* Now check for terminated state. */
if (thread_ptr -> tx_thread_state != TX_TERMINATED)
{
/* Thread not completed or terminated - return an error! */
status = TX_NOT_DONE;
}
}
}
/* Is the request valid? */
if (status == TX_SUCCESS)
{
/* Modify the thread status to prevent additional reset calls. */
thread_ptr -> tx_thread_state = TX_NOT_DONE;
/* Get the module instance. */
module_instance = thread_ptr -> tx_thread_module_instance_ptr;
/* Execute Port-Specific completion processing. If needed, it is typically defined in txm_module_port.h. */
TXM_MODULE_MANAGER_THREAD_RESET_PORT_COMPLETION(thread_ptr, module_instance)
/* Restore interrupts. */
TX_RESTORE
#ifndef TX_DISABLE_STACK_FILLING
/* Set the thread stack to a pattern prior to creating the initial
stack frame. This pattern is used by the stack checking routines
to see how much has been used. */
TX_MEMSET(thread_ptr -> tx_thread_stack_start, ((UCHAR) TX_STACK_FILL), thread_ptr -> tx_thread_stack_size);
#endif
/* Setup pointer to the thread entry information structure, which will live at the top of each
module thread's stack. This will allow the module thread entry function to avoid direct
access to the actual thread control block. */
thread_entry_info = (TXM_MODULE_THREAD_ENTRY_INFO *) (((UCHAR *) thread_ptr -> tx_thread_stack_end) + (2*sizeof(ULONG)) + 1);
thread_entry_info = (TXM_MODULE_THREAD_ENTRY_INFO *) (((ALIGN_TYPE)(thread_entry_info)) & (~0x3));
/* Place the thread entry information pointer in the thread control block so it can be picked up
in the following stack build function. This is supplied to the module's shell entry function
to avoid direct access to the actual thread control block. Note that this is overwritten
with the actual stack pointer at the end of stack build. */
thread_ptr -> tx_thread_stack_ptr = (VOID *) thread_entry_info;
/* Call the target specific stack frame building routine to build the
thread's initial stack and to setup the actual stack pointer in the
control block. */
_txm_module_manager_thread_stack_build(thread_ptr, module_instance -> txm_module_instance_shell_entry_function);
/* Disable interrupts. */
TX_DISABLE
/* Finally, move into a suspended state to allow for the thread to be resumed. */
thread_ptr -> tx_thread_state = TX_SUSPENDED;
/* If trace is enabled, insert this event into the trace buffer. */
TX_TRACE_IN_LINE_INSERT(TX_TRACE_THREAD_RESET, thread_ptr, thread_ptr -> tx_thread_state, 0, 0, TX_TRACE_THREAD_EVENTS)
/* Log this kernel call. */
TX_EL_THREAD_RESET_INSERT
/* Log the thread status change. */
TX_EL_THREAD_STATUS_CHANGE_INSERT(thread_ptr, TX_SUSPENDED)
}
/* Restore interrupts. */
TX_RESTORE
/* Return completion status to caller. */
return(status);
}

View File

@@ -0,0 +1,141 @@
/**************************************************************************/
/* */
/* 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 */
/** */
/** Module Manager */
/** */
/**************************************************************************/
/**************************************************************************/
#define TX_SOURCE_CODE
#include "tx_api.h"
#include "tx_thread.h"
#include "tx_timer.h"
#include "txm_module.h"
/**************************************************************************/
/* */
/* FUNCTION RELEASE */
/* */
/* _txm_module_manager_timer_notify_trampoline PORTABLE C */
/* 6.0.1 */
/* AUTHOR */
/* */
/* Scott Larson, Microsoft Corporation */
/* */
/* DESCRIPTION */
/* */
/* This function processes the timer expirations from ThreadX. */
/* */
/* INPUT */
/* */
/* id Timer ID */
/* */
/* OUTPUT */
/* */
/* None */
/* */
/* CALLS */
/* */
/* _txm_module_manager_callback_request Send module callback request */
/* */
/* CALLED BY */
/* */
/* ThreadX */
/* */
/* RELEASE HISTORY */
/* */
/* DATE NAME DESCRIPTION */
/* */
/* 06-30-2020 Scott Larson Initial Version 6.0.1 */
/* */
/**************************************************************************/
VOID _txm_module_manager_timer_notify_trampoline(ULONG id)
{
TX_INTERRUPT_SAVE_AREA
TXM_MODULE_INSTANCE *module_instance;
TXM_MODULE_CALLBACK_MESSAGE callback_message;
TX_QUEUE *module_callback_queue;
TX_TIMER *timer_ptr;
CHAR *internal_ptr;
/* We now know the callback is for a module. */
/* Disable interrupts. */
TX_DISABLE
/* Our expired timer pointer points to the internal timer,
* we need to get to the full timer pointer. */
/* Pickup the current internal timer pointer. */
internal_ptr = (CHAR *) _tx_timer_expired_timer_ptr;
/* Get the timer pointer from the internal pointer. */
TX_USER_TIMER_POINTER_GET((TX_TIMER_INTERNAL *) internal_ptr, timer_ptr);
/* Pickup the module instance pointer. */
module_instance = (TXM_MODULE_INSTANCE *) timer_ptr -> tx_timer_module_instance;
/* Determine if this module is still valid. */
if ((module_instance) && (module_instance -> txm_module_instance_id == TXM_MODULE_ID) &&
(module_instance -> txm_module_instance_state == TXM_MODULE_STARTED))
{
/* Yes, the module is still valid. */
/* Pickup the module's callback message queue. */
module_callback_queue = &(module_instance -> txm_module_instance_callback_request_queue);
/* Build the queue notification message. */
callback_message.txm_module_callback_message_type = TXM_TIMER_CALLBACK;
callback_message.txm_module_callback_message_activation_count = 1;
callback_message.txm_module_callback_message_application_function = (VOID (*)(VOID)) timer_ptr -> tx_timer_module_expiration_function;
callback_message.txm_module_callback_message_param_1 = (ULONG) id;
callback_message.txm_module_callback_message_param_2 = 0;
callback_message.txm_module_callback_message_param_3 = 0;
callback_message.txm_module_callback_message_param_4 = 0;
callback_message.txm_module_callback_message_param_5 = 0;
callback_message.txm_module_callback_message_param_6 = 0;
callback_message.txm_module_callback_message_param_7 = 0;
callback_message.txm_module_callback_message_param_8 = 0;
callback_message.txm_module_callback_message_reserved1 = 0;
callback_message.txm_module_callback_message_reserved2 = 0;
/* Restore interrupts. */
TX_RESTORE
/* Call the general processing that will place the callback on the
module's callback request queue. */
_txm_module_manager_callback_request(module_callback_queue, &callback_message);
}
else
{
/* Module no longer valid. */
/* Error, increment the error counter and return. */
_txm_module_manager_callback_error_count++;
/* Restore interrupts. */
TX_RESTORE
}
}

View File

@@ -0,0 +1,197 @@
/**************************************************************************/
/* */
/* 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 */
/** */
/** Module Manager */
/** */
/**************************************************************************/
/**************************************************************************/
#define TX_SOURCE_CODE
#include "tx_api.h"
#include "tx_byte_pool.h"
#include "tx_initialize.h"
#include "tx_mutex.h"
#include "tx_thread.h"
#include "txm_module.h"
/**************************************************************************/
/* */
/* FUNCTION RELEASE */
/* */
/* _txm_module_manager_unload PORTABLE C */
/* 6.0.1 */
/* AUTHOR */
/* */
/* Scott Larson, Microsoft Corporation */
/* */
/* DESCRIPTION */
/* */
/* This function unloads a previously loaded module. */
/* */
/* INPUT */
/* */
/* module_instance Module instance pointer */
/* */
/* OUTPUT */
/* */
/* status Completion status */
/* */
/* CALLS */
/* */
/* _tx_byte_release Release data area */
/* _tx_mutex_get Get protection mutex */
/* _tx_mutex_put Release protection mutex */
/* */
/* CALLED BY */
/* */
/* Application code */
/* */
/* RELEASE HISTORY */
/* */
/* DATE NAME DESCRIPTION */
/* */
/* 06-30-2020 Scott Larson Initial Version 6.0.1 */
/* */
/**************************************************************************/
UINT _txm_module_manager_unload(TXM_MODULE_INSTANCE *module_instance)
{
TX_INTERRUPT_SAVE_AREA
TXM_MODULE_INSTANCE *next_module, *previous_module;
CHAR *memory_ptr;
/* Check for interrupt call. */
if (TX_THREAD_GET_SYSTEM_STATE() != 0)
{
/* Now, make sure the call is from an interrupt and not initialization. */
if (TX_THREAD_GET_SYSTEM_STATE() < TX_INITIALIZE_IN_PROGRESS)
{
/* Invalid caller of this function, return appropriate error code. */
return(TX_CALLER_ERROR);
}
}
/* Determine if the module manager has not been initialized yet. */
if (_txm_module_manager_ready != TX_TRUE)
{
/* Module manager has not been initialized. */
return(TX_NOT_AVAILABLE);
}
/* Determine if the module is valid. */
if (module_instance == TX_NULL)
{
/* Invalid module pointer. */
return(TX_PTR_ERROR);
}
/* Get module manager protection mutex. */
_tx_mutex_get(&_txm_module_manager_mutex, TX_WAIT_FOREVER);
/* Determine if the module is already valid. */
if (module_instance -> txm_module_instance_id != TXM_MODULE_ID)
{
/* Release the protection mutex. */
_tx_mutex_put(&_txm_module_manager_mutex);
/* Invalid module pointer. */
return(TX_PTR_ERROR);
}
/* Determine if the module instance is in the state. */
if ((module_instance -> txm_module_instance_state != TXM_MODULE_LOADED) && (module_instance -> txm_module_instance_state != TXM_MODULE_STOPPED))
{
/* Release the protection mutex. */
_tx_mutex_put(&_txm_module_manager_mutex);
/* Return error if the module is not ready. */
return(TX_NOT_DONE);
}
/* Pickup the module data memory allocation address. */
memory_ptr = module_instance -> txm_module_instance_data_allocation_ptr;
/* Release the module's data memory. */
_tx_byte_release(memory_ptr);
/* Determine if there was memory allocated for the code. */
if (module_instance -> txm_module_instance_code_allocation_ptr)
{
/* Yes, release the module's code memory. */
memory_ptr = module_instance -> txm_module_instance_code_allocation_ptr;
/* Release the module's data memory. */
_tx_byte_release(memory_ptr);
}
/* Temporarily disable interrupts. */
TX_DISABLE
/* Clear some of the module information. */
module_instance -> txm_module_instance_id = 0;
module_instance -> txm_module_instance_state = TXM_MODULE_UNLOADED;
/* Call port-specific unload function. */
TXM_MODULE_MANAGER_MODULE_UNLOAD(module_instance);
/* Remove the module from the linked list of loaded modules. */
/* See if the module is the only one on the list. */
if ((--_txm_module_manger_loaded_count) == 0)
{
/* Only created module, just set the created list to NULL. */
_txm_module_manager_loaded_list_ptr = TX_NULL;
}
else
{
/* Otherwise, not the only created module, link-up the neighbors. */
next_module = module_instance -> txm_module_instance_loaded_next;
previous_module = module_instance -> txm_module_instance_loaded_previous;
next_module -> txm_module_instance_loaded_previous = previous_module;
previous_module -> txm_module_instance_loaded_next = next_module;
/* See if we have to update the created list head pointer. */
if (_txm_module_manager_loaded_list_ptr == module_instance)
{
/* Yes, move the head pointer to the next link. */
_txm_module_manager_loaded_list_ptr = next_module;
}
}
/* Restore interrupts. */
TX_RESTORE
/* Release the protection mutex. */
_tx_mutex_put(&_txm_module_manager_mutex);
/* Return success. */
return(TX_SUCCESS);
}

View File

@@ -0,0 +1,417 @@
/**************************************************************************/
/* */
/* 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 */
/** */
/** Module Manager */
/** */
/**************************************************************************/
/**************************************************************************/
/* Include necessary system files. */
#define TX_SOURCE_CODE
#include "txm_module.h"
#include "txm_module_manager_util.h"
/**************************************************************************/
/* */
/* FUNCTION RELEASE */
/* */
/* _txm_module_manager_object_memory_check PORTABLE C */
/* 6.0.1 */
/* AUTHOR */
/* */
/* Scott Larson, Microsoft Corporation */
/* */
/* DESCRIPTION */
/* */
/* This function checks if the object is inside a module's object pool */
/* or, if it's a privileged module, inside the module's data area. */
/* */
/* INPUT */
/* */
/* module_instance Module instance that the object */
/* belongs to */
/* object_ptr Pointer to object to check */
/* object_size Size of the object to check */
/* */
/* OUTPUT */
/* */
/* status Whether the object resides in a */
/* valid location */
/* */
/* CALLS */
/* */
/* None */
/* */
/* CALLED BY */
/* */
/* _txm_module_manager_kernel_dispatch Kernel dispatch function */
/* */
/* RELEASE HISTORY */
/* */
/* DATE NAME DESCRIPTION */
/* */
/* 06-30-2020 Scott Larson Initial Version 6.0.1 */
/* */
/**************************************************************************/
UINT _txm_module_manager_object_memory_check(TXM_MODULE_INSTANCE *module_instance, ALIGN_TYPE object_ptr, ULONG object_size)
{
/* Is the object pointer from the module manager's object pool? */
if ((_txm_module_manager_object_pool_created == TX_TRUE) &&
(object_ptr >= (ALIGN_TYPE) _txm_module_manager_object_pool.tx_byte_pool_start) &&
((object_ptr+object_size) <= (ALIGN_TYPE) (_txm_module_manager_object_pool.tx_byte_pool_start + _txm_module_manager_object_pool.tx_byte_pool_size)))
{
/* Object is from manager object pool. */
return(TX_SUCCESS);
}
/* If memory protection is not required, check if object is in module data. */
else if (!(module_instance -> txm_module_instance_property_flags & TXM_MODULE_MEMORY_PROTECTION))
{
if ((object_ptr >= (ALIGN_TYPE) module_instance -> txm_module_instance_data_start) &&
((object_ptr+object_size) <= (ALIGN_TYPE) module_instance -> txm_module_instance_data_end))
{
/* Object is from the local module memory. */
return(TX_SUCCESS);
}
}
/* Object is from invalid memory. */
return(TXM_MODULE_INVALID_MEMORY);
}
/**************************************************************************/
/* */
/* FUNCTION RELEASE */
/* */
/* _txm_module_manager_created_object_check PORTABLE C */
/* 6.0.1 */
/* AUTHOR */
/* */
/* Scott Larson, Microsoft Corporation */
/* */
/* DESCRIPTION */
/* */
/* This functions checks if the specified object was created by the */
/* specified module */
/* */
/* INPUT */
/* */
/* module_instance The module instance to check */
/* object_ptr The object to check */
/* */
/* OUTPUT */
/* */
/* status Whether the module created the */
/* object */
/* */
/* CALLS */
/* */
/* None */
/* */
/* CALLED BY */
/* */
/* txm_module_manager*_stop Module manager stop functions */
/* */
/* RELEASE HISTORY */
/* */
/* DATE NAME DESCRIPTION */
/* */
/* 06-30-2020 Scott Larson Initial Version 6.0.1 */
/* */
/**************************************************************************/
UCHAR _txm_module_manager_created_object_check(TXM_MODULE_INSTANCE *module_instance, VOID *object_ptr)
{
TXM_MODULE_ALLOCATED_OBJECT *allocated_object_ptr;
/* Determine if the socket control block is inside the module. */
if ( (((CHAR *) object_ptr) >= ((CHAR *) module_instance -> txm_module_instance_data_start)) &&
(((CHAR *) object_ptr) < ((CHAR *) module_instance -> txm_module_instance_data_end)))
{
return TX_TRUE;
}
/* Determine if this object control block was allocated by this module instance. */
else if (_txm_module_manager_object_pool_created)
{
/* Determine if the current object is from the pool of dynamically allocated objects. */
if ((((UCHAR *) object_ptr) >= _txm_module_manager_object_pool.tx_byte_pool_start) &&
(((UCHAR *) object_ptr) < (_txm_module_manager_object_pool.tx_byte_pool_start + _txm_module_manager_object_pool.tx_byte_pool_size)))
{
/* Pickup object pointer. */
allocated_object_ptr = (TXM_MODULE_ALLOCATED_OBJECT *) object_ptr;
/* Move back to get the header information. */
allocated_object_ptr--;
/* Now determine if this object belongs to this module. */
if (allocated_object_ptr -> txm_module_allocated_object_module_instance == module_instance)
{
return TX_TRUE;
}
}
}
return TX_FALSE;
}
/**************************************************************************/
/* */
/* FUNCTION RELEASE */
/* */
/* _txm_module_manager_object_size_check PORTABLE C */
/* 6.0.1 */
/* AUTHOR */
/* */
/* Scott Larson, Microsoft Corporation */
/* */
/* DESCRIPTION */
/* */
/* This function checks if the specified object's size matches what is */
/* inside the object pool. */
/* */
/* INPUT */
/* */
/* object_ptr Pointer to object to check */
/* object_size Size of the object to check */
/* */
/* OUTPUT */
/* */
/* status Whether the object's size matches */
/* what's inside the object pool */
/* */
/* CALLS */
/* */
/* None */
/* */
/* CALLED BY */
/* */
/* _txm_module_manager_kernel_dispatch Kernel dispatch function */
/* */
/* RELEASE HISTORY */
/* */
/* DATE NAME DESCRIPTION */
/* */
/* 06-30-2020 Scott Larson Initial Version 6.0.1 */
/* */
/**************************************************************************/
UINT _txm_module_manager_object_size_check(ALIGN_TYPE object_ptr, ULONG object_size)
{
TXM_MODULE_ALLOCATED_OBJECT *module_allocated_object_ptr;
UINT return_value;
/* Pickup the allocated object pointer. */
module_allocated_object_ptr = ((TXM_MODULE_ALLOCATED_OBJECT *) object_ptr) - 1;
/* Does the allocated memory match the expected object size? */
if (module_allocated_object_ptr -> txm_module_object_size == object_size)
return_value = TX_SUCCESS;
else
return_value = TXM_MODULE_INVALID_MEMORY;
return(return_value);
}
/**************************************************************************/
/* */
/* FUNCTION RELEASE */
/* */
/* _txm_module_manager_name_compare PORTABLE C */
/* 6.0.1 */
/* AUTHOR */
/* */
/* Scott Larson, Microsoft Corporation */
/* */
/* DESCRIPTION */
/* */
/* This function compares the specified object names. */
/* */
/* INPUT */
/* */
/* search_name String pointer to the object's */
/* name being searched for */
/* search_name_length Length of search_name */
/* object_name String pointer to an object's name*/
/* to compare the search name to */
/* */
/* OUTPUT */
/* */
/* status Whether the names are equal */
/* */
/* CALLS */
/* */
/* None */
/* */
/* CALLED BY */
/* */
/* *_object_pointer_get Kernel dispatch function */
/* */
/* RELEASE HISTORY */
/* */
/* DATE NAME DESCRIPTION */
/* */
/* 06-30-2020 Scott Larson Initial Version 6.0.1 */
/* */
/**************************************************************************/
UINT _txm_module_manager_object_name_compare(CHAR *search_name, UINT search_name_length, CHAR *object_name)
{
CHAR search_name_char;
CHAR object_name_char;
/* Is the object name null? Note that the search name has already been checked
by the caller. */
if (object_name == TX_NULL)
{
/* The strings can't match. */
return(TX_FALSE);
}
/* Loop through the names. */
while (1)
{
/* Get the current characters from each name. */
search_name_char = *search_name;
object_name_char = *object_name;
/* Check for match. */
if (search_name_char == object_name_char)
{
/* Are they null-terminators? */
if (search_name_char == '\0')
{
/* The strings match. */
return(TX_TRUE);
}
}
else
{
/* The strings don't match. */
return(TX_FALSE);
}
/* Are we at the end of the search name? */
if (search_name_length == 0)
{
/* The strings don't match. */
return(TX_FALSE);
}
/* Move to next character. */
search_name++;
object_name++;
search_name_length--;
}
}
/**************************************************************************/
/* */
/* FUNCTION RELEASE */
/* */
/* _txm_module_manager_util_code_allocation_size_and_alignment_get */
/* PORTABLE C */
/* 6.0.1 */
/* AUTHOR */
/* */
/* Scott Larson, Microsoft Corporation */
/* */
/* DESCRIPTION */
/* */
/* This function returns the required alignment and allocation size */
/* for a module's code area. */
/* */
/* INPUT */
/* */
/* module_preamble Preamble of module to return code */
/* values for */
/* code_alignment_dest Address to return code alignment */
/* code_allocation_size_desk Address to return code allocation */
/* size */
/* */
/* OUTPUT */
/* */
/* status Success if no math overflow */
/* occurred during calculation */
/* */
/* CALLS */
/* */
/* None */
/* */
/* CALLED BY */
/* */
/* txm_module_manager_*_load Module load functions */
/* */
/* RELEASE HISTORY */
/* */
/* DATE NAME DESCRIPTION */
/* */
/* 06-30-2020 Scott Larson Initial Version 6.0.1 */
/* */
/**************************************************************************/
UINT _txm_module_manager_util_code_allocation_size_and_alignment_get(TXM_MODULE_PREAMBLE *module_preamble,
ULONG *code_alignment_dest, ULONG *code_allocation_size_dest)
{
ULONG code_size;
ULONG code_alignment;
ULONG data_size_ignored;
ULONG data_alignment_ignored;
/* Pickup the module code size. */
code_size = module_preamble -> txm_module_preamble_code_size;
/* Adjust the size of the module elements to be aligned to the default alignment. */
TXM_MODULE_MANAGER_UTIL_MATH_ADD_ULONG(code_size, TXM_MODULE_CODE_ALIGNMENT, code_size);
code_size = ((code_size - 1)/TXM_MODULE_CODE_ALIGNMENT) * TXM_MODULE_CODE_ALIGNMENT;
/* Setup the default code and data alignments. */
code_alignment = (ULONG) TXM_MODULE_CODE_ALIGNMENT;
/* Get the port-specific alignment for the code size. Note we only want code so we pass 'null' values for data. */
data_size_ignored = 1;
data_alignment_ignored = 1;
TXM_MODULE_MANAGER_ALIGNMENT_ADJUST(module_preamble, code_size, code_alignment, data_size_ignored, data_alignment_ignored)
/* Calculate the code memory allocation size. */
TXM_MODULE_MANAGER_UTIL_MATH_ADD_ULONG(code_size, code_alignment, *code_allocation_size_dest);
/* Write the alignment result into the caller's destination address. */
*code_alignment_dest = code_alignment;
/* Return success. */
return(TX_SUCCESS);
}