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