1 /*************************************************************************** 2 * Copyright (c) 2024 Microsoft Corporation 3 * 4 * This program and the accompanying materials are made available under the 5 * terms of the MIT License which is available at 6 * https://opensource.org/licenses/MIT. 7 * 8 * SPDX-License-Identifier: MIT 9 **************************************************************************/ 10 11 12 /**************************************************************************/ 13 /**************************************************************************/ 14 /** */ 15 /** ThreadX Component */ 16 /** */ 17 /** Module */ 18 /** */ 19 /**************************************************************************/ 20 /**************************************************************************/ 21 22 23 /**************************************************************************/ 24 /* */ 25 /* APPLICATION INTERFACE DEFINITION RELEASE */ 26 /* */ 27 /* txm_module_port.h RXv2/IAR */ 28 /* 6.1.10 */ 29 /* AUTHOR */ 30 /* */ 31 /* Scott Larson, Microsoft Corporation */ 32 /* */ 33 /* DESCRIPTION */ 34 /* */ 35 /* This file defines the basic module constants, interface structures, */ 36 /* and function prototypes. */ 37 /* */ 38 /* RELEASE HISTORY */ 39 /* */ 40 /* DATE NAME DESCRIPTION */ 41 /* */ 42 /* 01-31-2022 Scott Larson Initial Version 6.1.10 */ 43 /* */ 44 /**************************************************************************/ 45 46 #ifndef TXM_MODULE_PORT_H 47 #define TXM_MODULE_PORT_H 48 49 /* Determine if the optional Modules user define file should be used. */ 50 51 #ifdef TXM_MODULE_INCLUDE_USER_DEFINE_FILE 52 53 54 /* Yes, include the user defines in txm_module_user.h. The defines in this file may 55 alternately be defined on the command line. */ 56 57 #include "txm_module_user.h" 58 #endif 59 60 /* It is assumed that the base ThreadX tx_port.h file has been modified to add the 61 following extensions to the ThreadX thread control block (this code should replace 62 the corresponding macro define in tx_port.h): 63 64 #define TX_THREAD_EXTENSION_2 VOID *tx_thread_module_instance_ptr; \ 65 VOID *tx_thread_module_entry_info_ptr; \ 66 ULONG tx_thread_module_current_user_mode; \ 67 ULONG tx_thread_module_user_mode; \ 68 VOID *tx_thread_module_kernel_stack_start; \ 69 VOID *tx_thread_module_kernel_stack_end; \ 70 ULONG tx_thread_module_kernel_stack_size; \ 71 VOID *tx_thread_module_stack_ptr; \ 72 VOID *tx_thread_module_stack_start; \ 73 VOID *tx_thread_module_stack_end; \ 74 ULONG tx_thread_module_stack_size; \ 75 VOID *tx_thread_module_reserved; \ 76 VOID *tx_thread_iar_tls_pointer; 77 78 The following extensions must also be defined in tx_port.h: 79 80 #define TX_EVENT_FLAGS_GROUP_EXTENSION VOID *tx_event_flags_group_module_instance; \ 81 VOID (*tx_event_flags_group_set_module_notify)(struct TX_EVENT_FLAGS_GROUP_STRUCT *group_ptr); 82 83 #define TX_QUEUE_EXTENSION VOID *tx_queue_module_instance; \ 84 VOID (*tx_queue_send_module_notify)(struct TX_QUEUE_STRUCT *queue_ptr); 85 86 #define TX_SEMAPHORE_EXTENSION VOID *tx_semaphore_module_instance; \ 87 VOID (*tx_semaphore_put_module_notify)(struct TX_SEMAPHORE_STRUCT *semaphore_ptr); 88 89 #define TX_TIMER_EXTENSION VOID *tx_timer_module_instance; \ 90 VOID (*tx_timer_module_expiration_function)(ULONG id); 91 */ 92 93 #define TXM_MODULE_THREAD_ENTRY_INFO_USER_EXTENSION 94 95 /* Define constants specific to the tools the module can be built with for this particular modules port. */ 96 97 #define TXM_MODULE_IAR_COMPILER 0x00000000 98 #define TXM_MODULE_RVDS_COMPILER 0x01000000 99 #define TXM_MODULE_GNU_COMPILER 0x02000000 100 #define TXM_MODULE_COMPILER_MASK 0xFF000000 101 #define TXM_MODULE_OPTIONS_MASK 0x000000FF 102 103 104 /* Define the properties for this particular module port. */ 105 106 #define TXM_MODULE_MEMORY_PROTECTION_ENABLED 107 #ifdef TXM_MODULE_MEMORY_PROTECTION_ENABLED 108 #define TXM_MODULE_REQUIRE_ALLOCATED_OBJECT_MEMORY 109 #else 110 #define TXM_MODULE_REQUIRE_LOCAL_OBJECT_MEMORY 111 #endif 112 113 #define TXM_MODULE_USER_MODE 0x00000001 114 #define TXM_MODULE_MEMORY_PROTECTION 0x00000002 115 #define TXM_MODULE_SHARED_EXTERNAL_MEMORY_ACCESS 0x00000004 116 117 /* Define the kernel stack size for a module thread. */ 118 #ifndef TXM_MODULE_KERNEL_STACK_SIZE 119 #define TXM_MODULE_KERNEL_STACK_SIZE 512 120 #endif 121 122 123 /* Define the supported options for this module. */ 124 125 #define TXM_MODULE_MANAGER_SUPPORTED_OPTIONS (TXM_MODULE_USER_MODE | TXM_MODULE_MEMORY_PROTECTION | TXM_MODULE_SHARED_EXTERNAL_MEMORY_ACCESS) 126 #define TXM_MODULE_MANAGER_REQUIRED_OPTIONS 0 127 128 129 /* Define offset adjustments according to the compiler used to build the module. */ 130 131 #define TXM_MODULE_IAR_SHELL_ADJUST 24 132 #define TXM_MODULE_IAR_START_ADJUST 28 133 #define TXM_MODULE_IAR_STOP_ADJUST 32 134 #define TXM_MODULE_IAR_CALLBACK_ADJUST 44 135 136 #define TXM_MODULE_RVDS_SHELL_ADJUST 0 137 #define TXM_MODULE_RVDS_START_ADJUST 0 138 #define TXM_MODULE_RVDS_STOP_ADJUST 0 139 #define TXM_MODULE_RVDS_CALLBACK_ADJUST 0 140 141 #define TXM_MODULE_GNU_SHELL_ADJUST 24 142 #define TXM_MODULE_GNU_START_ADJUST 28 143 #define TXM_MODULE_GNU_STOP_ADJUST 32 144 #define TXM_MODULE_GNU_CALLBACK_ADJUST 44 145 146 147 /* Define other module port-specific constants. */ 148 149 /* Define INLINE_DECLARE to inline for IAR compiler. */ 150 151 #define INLINE_DECLARE inline 152 153 /* Define the data area alignment mask, must be a power of 2. */ 154 155 #ifndef TXM_MODULE_DATA_ALIGNMENT 156 #define TXM_MODULE_DATA_ALIGNMENT 16 157 #endif 158 159 160 /* Define the code area alignment mask, must be a power of 2. */ 161 162 #ifndef TXM_MODULE_CODE_ALIGNMENT 163 #define TXM_MODULE_CODE_ALIGNMENT 16 164 #endif 165 166 167 /* Define the number of MPU entries assigned to the code and data sections. */ 168 169 #define TXM_MODULE_MANAGER_CODE_MPU_ENTRIES 2 170 #define TXM_MODULE_MANAGER_DATA_MPU_ENTRIES 1 171 172 /* Total MPU entries available. */ 173 #define TXM_MODULE_MANAGER_RX_MPU_ENTRIES 8 174 #define TXM_MODULE_MANAGER_REGISTERS_PER_MPU_ENTRY 2 175 #define TXM_MODULE_MANAGER_MPU_TABLE_SIZE (TXM_MODULE_MANAGER_RX_MPU_ENTRIES * TXM_MODULE_MANAGER_REGISTERS_PER_MPU_ENTRY) 176 177 /* Shared memory MPU index. */ 178 #define TXM_MODULE_MANAGER_SHARED_MPU_INDEX 6 179 180 /* Addresses of MPU registers for trampoline protection. */ 181 #define RSPAGE0 (*(ULONG *) 0x00086400) 182 #define REPAGE0 (*(ULONG *) 0x00086404) 183 184 /* Shared memory region attributes. */ 185 #define TXM_MODULE_MANAGER_SHARED_ATTRIBUTE_EXECUTE 1 186 #define TXM_MODULE_MANAGER_SHARED_ATTRIBUTE_WRITE 2 187 #define TXM_MODULE_MANAGER_SHARED_ATTRIBUTE_READ 4 188 189 #define TXM_MODULE_MANAGER_ATTRIBUTE_EXECUTE_MPU_BIT (TXM_MODULE_MANAGER_SHARED_ATTRIBUTE_EXECUTE << 1) 190 #define TXM_MODULE_MANAGER_ATTRIBUTE_WRITE_MPU_BIT (TXM_MODULE_MANAGER_SHARED_ATTRIBUTE_WRITE << 1) 191 #define TXM_MODULE_MANAGER_ATTRIBUTE_READ_MPU_BIT (TXM_MODULE_MANAGER_SHARED_ATTRIBUTE_READ << 1) 192 193 /* Define the port-extensions to the module manager instance structure. */ 194 195 #define TXM_MODULE_MANAGER_PORT_EXTENSION \ 196 ULONG txm_module_instance_mpu_registers[TXM_MODULE_MANAGER_MPU_TABLE_SIZE]; \ 197 ULONG txm_module_instance_shared_memory_address; \ 198 ULONG txm_module_instance_shared_memory_length; 199 200 201 /* Define the memory fault information structure that is populated when a memory fault occurs. */ 202 203 204 typedef struct TXM_MODULE_MANAGER_MEMORY_FAULT_INFO_STRUCT 205 { 206 TX_THREAD *txm_module_manager_memory_fault_info_thread_ptr; 207 VOID *txm_module_manager_memory_fault_info_code_location; 208 ULONG txm_module_manager_memory_fault_info_mpests; 209 ULONG txm_module_manager_memory_fault_info_mpdea; 210 ULONG txm_module_manager_memory_fault_info_mhiti; 211 ULONG txm_module_manager_memory_fault_info_mhitd; 212 ULONG txm_module_manager_memory_fault_info_psw; 213 ULONG txm_module_manager_memory_fault_info_sp; 214 ULONG txm_module_manager_memory_fault_info_r1; 215 ULONG txm_module_manager_memory_fault_info_r2; 216 ULONG txm_module_manager_memory_fault_info_r3; 217 ULONG txm_module_manager_memory_fault_info_r4; 218 ULONG txm_module_manager_memory_fault_info_r5; 219 ULONG txm_module_manager_memory_fault_info_r6; 220 ULONG txm_module_manager_memory_fault_info_r7; 221 ULONG txm_module_manager_memory_fault_info_r8; 222 ULONG txm_module_manager_memory_fault_info_r9; 223 ULONG txm_module_manager_memory_fault_info_r10; 224 ULONG txm_module_manager_memory_fault_info_r11; 225 ULONG txm_module_manager_memory_fault_info_r12; 226 ULONG txm_module_manager_memory_fault_info_r13; 227 ULONG txm_module_manager_memory_fault_info_r14; 228 ULONG txm_module_manager_memory_fault_info_r15; 229 } TXM_MODULE_MANAGER_MEMORY_FAULT_INFO; 230 231 232 #define TXM_MODULE_MANAGER_FAULT_INFO \ 233 TXM_MODULE_MANAGER_MEMORY_FAULT_INFO _txm_module_manager_memory_fault_info; 234 235 /* Define the macro to check the stack available in dispatch. */ 236 //#define TXM_MODULE_MANAGER_CHECK_STACK_AVAILABLE \ 237 // ULONG stack_available; \ 238 // __asm("MOV SP, %0" : "=r"(stack_available)); \ 239 // stack_available -= (ULONG)_tx_thread_current_ptr->tx_thread_stack_start; \ 240 // if((stack_available < TXM_MODULE_MINIMUM_STACK_AVAILABLE) || \ 241 // (stack_available > _tx_thread_current_ptr->tx_thread_stack_size)) \ 242 // { \ 243 // return(TX_SIZE_ERROR); \ 244 // } 245 246 /* Define the macro to check the module version ID. */ 247 248 #define TXM_MODULE_MANAGER_CHECK_PROPERTIES(properties) \ 249 if ((properties & _txm_module_manager_properties_supported) != (properties & ~((ULONG) TXM_MODULE_COMPILER_MASK))) \ 250 { \ 251 _tx_mutex_put(&_txm_module_manager_mutex); \ 252 return(TXM_MODULE_INVALID_PROPERTIES); \ 253 } \ 254 if ((_txm_module_manager_properties_required & properties) != _txm_module_manager_properties_required) \ 255 { \ 256 _tx_mutex_put(&_txm_module_manager_mutex); \ 257 return(TXM_MODULE_INVALID_PROPERTIES); \ 258 } 259 260 261 /* Define the macro to check the code alignment. */ 262 263 #define TXM_MODULE_MANAGER_CHECK_CODE_ALIGNMENT(module_location, code_alignment) \ 264 { \ 265 ULONG temp; \ 266 temp = (ULONG) module_location; \ 267 temp = temp & (code_alignment - 1); \ 268 if (temp) \ 269 { \ 270 _tx_mutex_put(&_txm_module_manager_mutex); \ 271 return(TXM_MODULE_ALIGNMENT_ERROR); \ 272 } \ 273 } 274 275 276 /* Define the macro to adjust the alignment and size for code/data areas. */ 277 278 #define TXM_MODULE_MANAGER_ALIGNMENT_ADJUST(module_preamble, code_size, code_alignment, data_size, data_alignment) _txm_module_manager_alignment_adjust(module_preamble, &code_size, &code_alignment, &data_size, &data_alignment); 279 280 281 /* Define the macro to adjust the symbols in the module preamble. */ 282 283 #define TXM_MODULE_MANAGER_CALCULATE_ADJUSTMENTS(properties, shell_function_adjust, start_function_adjust, stop_function_adjust, callback_function_adjust) \ 284 if ((properties & TXM_MODULE_COMPILER_MASK) == TXM_MODULE_IAR_COMPILER) \ 285 { \ 286 shell_function_adjust = TXM_MODULE_IAR_SHELL_ADJUST; \ 287 start_function_adjust = TXM_MODULE_IAR_START_ADJUST - (ULONG)(module_instance -> txm_module_instance_code_start); \ 288 stop_function_adjust = TXM_MODULE_IAR_STOP_ADJUST - (ULONG)(module_instance -> txm_module_instance_code_start); \ 289 callback_function_adjust = TXM_MODULE_IAR_CALLBACK_ADJUST - (ULONG)(module_instance -> txm_module_instance_code_start); \ 290 } \ 291 else if ((properties & TXM_MODULE_COMPILER_MASK) == TXM_MODULE_RVDS_COMPILER) \ 292 { \ 293 shell_function_adjust = TXM_MODULE_RVDS_SHELL_ADJUST; \ 294 start_function_adjust = TXM_MODULE_RVDS_START_ADJUST; \ 295 stop_function_adjust = TXM_MODULE_RVDS_STOP_ADJUST; \ 296 callback_function_adjust = TXM_MODULE_RVDS_CALLBACK_ADJUST; \ 297 } \ 298 else \ 299 { \ 300 shell_function_adjust = TXM_MODULE_GNU_SHELL_ADJUST; \ 301 start_function_adjust = TXM_MODULE_GNU_START_ADJUST; \ 302 stop_function_adjust = TXM_MODULE_GNU_STOP_ADJUST; \ 303 callback_function_adjust = TXM_MODULE_GNU_CALLBACK_ADJUST; \ 304 } 305 306 307 /* Define the macro to populate the thread control block with module port-specific information. 308 Check if the module is in user mode and set up txm_module_thread_entry_info_kernel_call_dispatcher accordingly. 309 */ 310 #define TXM_MODULE_MANAGER_THREAD_SETUP(thread_ptr, module_instance) \ 311 thread_ptr -> tx_thread_module_current_user_mode = module_instance -> txm_module_instance_property_flags & TXM_MODULE_USER_MODE; \ 312 thread_ptr -> tx_thread_module_user_mode = module_instance -> txm_module_instance_property_flags & TXM_MODULE_USER_MODE; \ 313 if (thread_ptr -> tx_thread_module_user_mode) \ 314 { \ 315 *(ULONG*)&(thread_entry_info -> txm_module_thread_entry_info_kernel_call_dispatcher) = \ 316 (ULONG)_txm_module_manager_user_mode_entry - (ULONG)module_instance -> txm_module_instance_code_start; \ 317 } \ 318 else \ 319 { \ 320 *(ULONG*)&(thread_entry_info -> txm_module_thread_entry_info_kernel_call_dispatcher) = \ 321 (ULONG)_txm_module_manager_kernel_dispatch - (ULONG)module_instance -> txm_module_instance_code_start; \ 322 } 323 324 /* Define the macro to populate the module control block with module port-specific information. 325 If memory protection is enabled, set up the MPU registers. 326 */ 327 #define TXM_MODULE_MANAGER_MODULE_SETUP(module_instance) \ 328 if (module_instance -> txm_module_instance_property_flags & TXM_MODULE_USER_MODE) \ 329 { \ 330 if (module_instance -> txm_module_instance_property_flags & TXM_MODULE_MEMORY_PROTECTION) \ 331 { \ 332 _txm_module_manager_setup_mpu_registers(module_instance); \ 333 } \ 334 } \ 335 else \ 336 { \ 337 /* Do nothing. */ \ 338 } 339 340 /* Define the macro to perform port-specific functions when unloading the module. */ 341 /* Nothing needs to be done for this port. */ 342 #define TXM_MODULE_MANAGER_MODULE_UNLOAD(module_instance) 343 344 345 /* Define the macro to perform port-specific functions when passing pointer to kernel. */ 346 /* Determine if the pointer is within the module's data or shared memory. */ 347 //#define TXM_MODULE_MANAGER_CHECK_DATA_POINTER(module_instance, pointer) \ 348 // if ((pointer < (ULONG) module_instance -> txm_module_instance_data_start) || \ 349 // ((pointer+sizeof(pointer)) > (ULONG) module_instance -> txm_module_instance_data_end)) \ 350 // { \ 351 // if((pointer < module_instance -> txm_module_instance_shared_memory_address) || \ 352 // ((pointer+sizeof(pointer)) > module_instance -> txm_module_instance_shared_memory_address \ 353 // + module_instance -> txm_module_instance_shared_memory_length)) \ 354 // { \ 355 // return(TXM_MODULE_INVALID_MEMORY); \ 356 // } \ 357 // } 358 359 /* Define the macro to perform port-specific functions when passing function pointer to kernel. */ 360 /* Determine if the pointer is within the module's code memory. */ 361 //#define TXM_MODULE_MANAGER_CHECK_FUNCTION_POINTER(module_instance, pointer) \ 362 // if (((pointer < sizeof(TXM_MODULE_PREAMBLE)) || \ 363 // ((pointer+sizeof(pointer)) > ((ULONG) module_instance -> txm_module_instance_code_end - \ 364 // (ULONG) module_instance -> txm_module_instance_code_start))) \ 365 // && (pointer != (ULONG) TX_NULL)) \ 366 // { \ 367 // return(TX_PTR_ERROR); \ 368 // } 369 370 /* Define macro to make sure object is inside the module's data. */ 371 #define TXM_MODULE_MANAGER_CHECK_INSIDE_DATA(module_instance, obj_ptr, obj_size) \ 372 /* Check for overflow. */ \ 373 (((obj_ptr) < ((obj_ptr) + (obj_size))) && \ 374 /* Check if it's inside module data. */ \ 375 ((((obj_ptr) >= (ALIGN_TYPE) module_instance -> txm_module_instance_data_start) && \ 376 (((obj_ptr) + (obj_size)) <= ((ALIGN_TYPE) module_instance -> txm_module_instance_data_end + 1))) || \ 377 /* Check if it's inside shared memory. */ \ 378 (((obj_ptr) >= (ALIGN_TYPE) module_instance -> txm_module_instance_shared_memory_address) && \ 379 (((obj_ptr) + (obj_size)) <= (ALIGN_TYPE) (module_instance -> txm_module_instance_shared_memory_address + module_instance -> txm_module_instance_shared_memory_length))))) 380 381 382 /* Define some internal prototypes to this module port. */ 383 384 #ifndef TX_SOURCE_CODE 385 #define txm_module_manager_memory_fault_notify _txm_module_manager_memory_fault_notify 386 #endif 387 388 389 #define TXM_MODULE_MANAGER_ADDITIONAL_PROTOTYPES \ 390 VOID _txm_module_manager_alignment_adjust(TXM_MODULE_PREAMBLE *module_preamble, ULONG *code_size, ULONG *code_alignment, ULONG *data_size, ULONG *data_alignment); \ 391 VOID _txm_module_manager_memory_fault_handler(VOID); \ 392 UINT _txm_module_manager_memory_fault_notify(VOID (*notify_function)(TX_THREAD *, TXM_MODULE_INSTANCE *)); \ 393 VOID _txm_module_manager_setup_mpu_registers(TXM_MODULE_INSTANCE *module_instance); 394 395 396 #define TXM_MODULE_MANAGER_VERSION_ID \ 397 CHAR _txm_module_manager_version_id[] = \ 398 "Copyright (c) 2024 Microsoft Corporation. * ThreadX Module RXv2/IAR Version 6.4.1 *"; 399 400 #endif 401