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 /** Thread-Metric Component */
16 /** */
17 /** Porting Layer (ThreadX Example) */
18 /** */
19 /**************************************************************************/
20 /**************************************************************************/
21
22
23 /* Turn off ThreadX error checking. */
24
25 #ifndef TX_DISABLE_ERROR_CHECKING
26 #define TX_DISABLE_ERROR_CHECKING
27 #endif
28
29
30 /* For smallest size, the ThreadX library and application code should be built
31 with the following options defined (easiest to add in tx_port.h):
32
33 #define TX_ENABLE_EXECUTION_CHANGE_NOTIFY
34 #define TX_DISABLE_PREEMPTION_THRESHOLD
35 #define TX_DISABLE_NOTIFY_CALLBACKS
36 #define TX_DISABLE_REDUNDANT_CLEARING
37 #define TX_DISABLE_STACK_FILLING
38 #define TX_NOT_INTERRUPTABLE
39 #define TX_TIMER_PROCESS_IN_ISR
40
41 For the fastest performance, these additional options should also be used:
42
43 #define TX_REACTIVATE_INLINE
44 #define TX_INLINE_THREAD_RESUME_SUSPEND
45
46 */
47
48
49
50 /* Include necessary files. */
51
52 #include "tx_api.h"
53 #include "tm_api.h"
54
55
56 /* Define ThreadX mapping constants. */
57
58 #define TM_THREADX_MAX_THREADS 10
59 #define TM_THREADX_MAX_QUEUES 1
60 #define TM_THREADX_MAX_SEMAPHORES 1
61 #define TM_THREADX_MAX_MEMORY_POOLS 1
62
63
64 /* Define the default ThreadX stack size. */
65
66 #define TM_THREADX_THREAD_STACK_SIZE 2096
67
68
69 /* Define the default ThreadX queue size. */
70
71 #define TM_THREADX_QUEUE_SIZE 200
72
73
74 /* Define the default ThreadX memory pool size. */
75
76 #define TM_THREADX_MEMORY_POOL_SIZE 2048
77
78
79 /* Define the number of timer interrupt ticks per second. */
80
81 #define TM_THREADX_TICKS_PER_SECOND 100
82
83
84 /* Define ThreadX data structures. */
85
86 TX_THREAD tm_thread_array[TM_THREADX_MAX_THREADS];
87 TX_QUEUE tm_queue_array[TM_THREADX_MAX_QUEUES];
88 TX_SEMAPHORE tm_semaphore_array[TM_THREADX_MAX_SEMAPHORES];
89 TX_BLOCK_POOL tm_block_pool_array[TM_THREADX_MAX_MEMORY_POOLS];
90
91
92 /* Define ThreadX object data areas. */
93
94 unsigned char tm_thread_stack_area[TM_THREADX_MAX_THREADS*TM_THREADX_THREAD_STACK_SIZE];
95 unsigned char tm_queue_memory_area[TM_THREADX_MAX_QUEUES*TM_THREADX_QUEUE_SIZE];
96 unsigned char tm_pool_memory_area[TM_THREADX_MAX_MEMORY_POOLS*TM_THREADX_MEMORY_POOL_SIZE];
97
98
99 /* Define array to remember the test entry function. */
100
101 void *tm_thread_entry_functions[TM_THREADX_MAX_THREADS];
102
103
104 /* Remember the test initialization function. */
105
106 void (*tm_initialization_function)(void);
107
108
109 /* Define our shell entry function to match ThreadX. */
110
111 VOID tm_thread_entry(ULONG thread_input);
112
113
114 /* This function called from main performs basic RTOS initialization,
115 calls the test initialization function, and then starts the RTOS function. */
tm_initialize(void (* test_initialization_function)(void))116 void tm_initialize(void (*test_initialization_function)(void))
117 {
118
119 /* Save the test initialization function. */
120 tm_initialization_function = test_initialization_function;
121
122 /* Call the previously defined initialization function. */
123 (tm_initialization_function)();
124 }
125
126
127 /* This function takes a thread ID and priority and attempts to create the
128 file in the underlying RTOS. Valid priorities range from 1 through 31,
129 where 1 is the highest priority and 31 is the lowest. If successful,
130 the function should return TM_SUCCESS. Otherwise, TM_ERROR should be returned. */
tm_thread_create(int thread_id,int priority,void (* entry_function)(void))131 int tm_thread_create(int thread_id, int priority, void (*entry_function)(void))
132 {
133
134 UINT status;
135
136 /* Remember the actual thread entry. */
137 tm_thread_entry_functions[thread_id] = (void *) entry_function;
138
139 /* Create the thread under ThreadX. */
140 status = tx_thread_create(&tm_thread_array[thread_id], "Thread-Metric test", tm_thread_entry, (ULONG) thread_id,
141 &tm_thread_stack_area[thread_id*TM_THREADX_THREAD_STACK_SIZE], TM_THREADX_THREAD_STACK_SIZE,
142 (UINT) priority, (UINT) priority, TX_NO_TIME_SLICE, TX_DONT_START);
143
144 /* Determine if the thread create was successful. */
145 if (status == TX_SUCCESS)
146 return(TM_SUCCESS);
147 else
148 return(TM_ERROR);
149 }
150
151
152 /* This function resumes the specified thread. If successful, the function should
153 return TM_SUCCESS. Otherwise, TM_ERROR should be returned. */
tm_thread_resume(int thread_id)154 int tm_thread_resume(int thread_id)
155 {
156
157 UINT status;
158
159
160 /* Attempt to resume the thread. */
161 status = tx_thread_resume(&tm_thread_array[thread_id]);
162
163 /* Determine if the thread resume was successful. */
164 if (status == TX_SUCCESS)
165 return(TM_SUCCESS);
166 else
167 return(TM_ERROR);
168 }
169
170
171 /* This function suspends the specified thread. If successful, the function should
172 return TM_SUCCESS. Otherwise, TM_ERROR should be returned. */
tm_thread_suspend(int thread_id)173 int tm_thread_suspend(int thread_id)
174 {
175
176 UINT status;
177
178
179 /* Attempt to suspend the thread. */
180 status = tx_thread_suspend(&tm_thread_array[thread_id]);
181
182 /* Determine if the thread suspend was successful. */
183 if (status == TX_SUCCESS)
184 return(TM_SUCCESS);
185 else
186 return(TM_ERROR);
187 }
188
189
190 /* This function relinquishes to other ready threads at the same
191 priority. */
tm_thread_relinquish(void)192 void tm_thread_relinquish(void)
193 {
194
195 /* Relinquish to other threads at the same priority. */
196 tx_thread_relinquish();
197 }
198
199
200 /* This function suspends the specified thread for the specified number
201 of seconds. If successful, the function should return TM_SUCCESS.
202 Otherwise, TM_ERROR should be returned. */
tm_thread_sleep(int seconds)203 void tm_thread_sleep(int seconds)
204 {
205
206 /* Attempt to sleep. */
207 tx_thread_sleep(((UINT) seconds)*TM_THREADX_TICKS_PER_SECOND);
208 }
209
210
211 /* This function creates the specified queue. If successful, the function should
212 return TM_SUCCESS. Otherwise, TM_ERROR should be returned. */
tm_queue_create(int queue_id)213 int tm_queue_create(int queue_id)
214 {
215
216 UINT status;
217
218
219 /* Create the specified queue with 16-byte messages. */
220 status = tx_queue_create(&tm_queue_array[queue_id], "Thread-Metric test", TX_4_ULONG,
221 &tm_queue_memory_area[queue_id*TM_THREADX_QUEUE_SIZE], TM_THREADX_QUEUE_SIZE);
222
223 /* Determine if the queue create was successful. */
224 if (status == TX_SUCCESS)
225 return(TM_SUCCESS);
226 else
227 return(TM_ERROR);
228 }
229
230
231 /* This function sends a 16-byte message to the specified queue. If successful,
232 the function should return TM_SUCCESS. Otherwise, TM_ERROR should be returned. */
tm_queue_send(int queue_id,unsigned long * message_ptr)233 int tm_queue_send(int queue_id, unsigned long *message_ptr)
234 {
235
236 UINT status;
237
238
239 /* Send the 16-byte message to the specified queue. */
240 status = tx_queue_send(&tm_queue_array[queue_id], message_ptr, TX_NO_WAIT);
241
242 /* Determine if the queue send was successful. */
243 if (status == TX_SUCCESS)
244 return(TM_SUCCESS);
245 else
246 return(TM_ERROR);
247 }
248
249
250 /* This function receives a 16-byte message from the specified queue. If successful,
251 the function should return TM_SUCCESS. Otherwise, TM_ERROR should be returned. */
tm_queue_receive(int queue_id,unsigned long * message_ptr)252 int tm_queue_receive(int queue_id, unsigned long *message_ptr)
253 {
254
255 UINT status;
256
257
258 /* Receive a 16-byte message from the specified queue. */
259 status = tx_queue_receive(&tm_queue_array[queue_id], message_ptr, TX_NO_WAIT);
260
261 /* Determine if the queue receive was successful. */
262 if (status == TX_SUCCESS)
263 return(TM_SUCCESS);
264 else
265 return(TM_ERROR);
266 }
267
268
269 /* This function creates the specified semaphore. If successful, the function should
270 return TM_SUCCESS. Otherwise, TM_ERROR should be returned. */
tm_semaphore_create(int semaphore_id)271 int tm_semaphore_create(int semaphore_id)
272 {
273
274 UINT status;
275
276
277 /* Create semaphore. */
278 status = tx_semaphore_create(&tm_semaphore_array[semaphore_id], "Thread-Metric test", 1);
279
280 /* Determine if the semaphore create was successful. */
281 if (status == TX_SUCCESS)
282 return(TM_SUCCESS);
283 else
284 return(TM_ERROR);
285 }
286
287
288 /* This function gets the specified semaphore. If successful, the function should
289 return TM_SUCCESS. Otherwise, TM_ERROR should be returned. */
tm_semaphore_get(int semaphore_id)290 int tm_semaphore_get(int semaphore_id)
291 {
292
293 UINT status;
294
295
296 /* Get the semaphore. */
297 status = tx_semaphore_get(&tm_semaphore_array[semaphore_id], TX_NO_WAIT);
298
299 /* Determine if the semaphore get was successful. */
300 if (status == TX_SUCCESS)
301 return(TM_SUCCESS);
302 else
303 return(TM_ERROR);
304 }
305
306
307 /* This function puts the specified semaphore. If successful, the function should
308 return TM_SUCCESS. Otherwise, TM_ERROR should be returned. */
tm_semaphore_put(int semaphore_id)309 int tm_semaphore_put(int semaphore_id)
310 {
311
312 UINT status;
313
314
315 /* Put the semaphore. */
316 status = tx_semaphore_put(&tm_semaphore_array[semaphore_id]);
317
318 /* Determine if the semaphore put was successful. */
319 if (status == TX_SUCCESS)
320 return(TM_SUCCESS);
321 else
322 return(TM_ERROR);
323 }
324
325
326 /* This function creates the specified memory pool that can support one or more
327 allocations of 128 bytes. If successful, the function should
328 return TM_SUCCESS. Otherwise, TM_ERROR should be returned. */
tm_memory_pool_create(int pool_id)329 int tm_memory_pool_create(int pool_id)
330 {
331
332 UINT status;
333
334
335 /* Create the memory pool. */
336 status = tx_block_pool_create(&tm_block_pool_array[pool_id], "Thread-Metric test", 128, &tm_pool_memory_area[pool_id*TM_THREADX_MEMORY_POOL_SIZE], TM_THREADX_MEMORY_POOL_SIZE);
337
338 /* Determine if the block pool memory was successful. */
339 if (status == TX_SUCCESS)
340 return(TM_SUCCESS);
341 else
342 return(TM_ERROR);
343 }
344
345
346 /* This function allocates a 128 byte block from the specified memory pool.
347 If successful, the function should return TM_SUCCESS. Otherwise, TM_ERROR
348 should be returned. */
tm_memory_pool_allocate(int pool_id,unsigned char ** memory_ptr)349 int tm_memory_pool_allocate(int pool_id, unsigned char **memory_ptr)
350 {
351
352 UINT status;
353
354
355 /* Allocate a 128-byte block from the specified memory pool. */
356 status = tx_block_allocate(&tm_block_pool_array[pool_id], (void **) memory_ptr, TX_NO_WAIT);
357
358 /* Determine if the block pool allocate was successful. */
359 if (status == TX_SUCCESS)
360 return(TM_SUCCESS);
361 else
362 return(TM_ERROR);
363 }
364
365
366 /* This function releases a previously allocated 128 byte block from the specified
367 memory pool. If successful, the function should return TM_SUCCESS. Otherwise, TM_ERROR
368 should be returned. */
tm_memory_pool_deallocate(int pool_id,unsigned char * memory_ptr)369 int tm_memory_pool_deallocate(int pool_id, unsigned char *memory_ptr)
370 {
371
372 UINT status;
373
374
375 /* Release the 128-byte block back to the specified memory pool. */
376 status = tx_block_release((void *) memory_ptr);
377
378 /* Determine if the block pool release was successful. */
379 if (status == TX_SUCCESS)
380 return(TM_SUCCESS);
381 else
382 return(TM_ERROR);
383 }
384
385
386 /* This is the ThreadX thread entry. It is going to call the Thread-Metric
387 entry function saved earlier. */
tm_thread_entry(ULONG thread_input)388 VOID tm_thread_entry(ULONG thread_input)
389 {
390
391 void (*entry_function)(void);
392
393
394 /* Pickup the entry function from the saved array. */
395 entry_function = (void (*)(void)) tm_thread_entry_functions[thread_input];
396
397 /* Call the entry function. */
398 (entry_function)();
399 }
400
401
402