1 Microsoft's Azure RTOS ThreadX for Cortex-A5
2
3 Using the Green Hills Software Tools
4
51. Open the ThreadX Project Workspace
6
7In order to build the ThreadX library and the ThreadX demonstration first load
8the Azure RTOS Workspace azure_rtos_workspace.gpj, which is located inside the
9"example_build" directory.
10
11
122. Building the ThreadX run-time Library
13
14Building the ThreadX library is easy; simply select the MULTI project file
15tx.gpj and then select the build button. You should now observe the
16compilation and assembly of the ThreadX library. This project build produces
17the ThreadX library file tx.a.
18
19
203. Demonstration System
21
22The ThreadX demonstration is designed to execute under the MULTI environment
23on the Green Hills Cortex-A5 simulator. The instructions that follow describe
24how to get the ThreadX evaluation running under the MULTI Cortex-A5 simulation
25environment.
26
27Building the demonstration is easy; simply select the MULTI project file
28sample_threadx.gpj. At this point, select the "Project Build" button and observe
29the compilation, assembly, and linkage of the ThreadX demonstration application.
30
31After the demonstration is built, invoke the MULTI ARM simulator by selecting
32the simulator connection from within the sample_threadx.con connection file.
33Once connected to the simulator, select the "Debug" button. You should now
34observe the main function of sample_threadx.c.
35
36At this point, you should setup a simulated timer interrupt for ThreadX
37by entering "timer 9999 irq" in the "target" window of the debugger.
38
39You are now ready to execute the ThreadX demonstration system. Select
40breakpoints and data watches to observe the execution of the sample_threadx.c
41application.
42
43
444. EventAnalyzer Demonstration
45
46To build a demonstration system that also logs events for the MULTI EventAnalyzer,
47perform the same steps as the regular demo, except build the ThreadX library with
48txe.gpj file and use the sample_threadx_el.gpj build file to build the demonstration.
49The resulting image will log all system events, which can then be displayed by the
50MULTI EventAnalyzer.
51
52
535. System Initialization
54
55The system entry point using the Green Hills tools is at the label _start.
56This is defined within the crt0.arm file supplied by Green Hills. In addition,
57this is where all static and global preset C variable initialization
58processing is called from.
59
60After the Green Hills startup function returns, ThreadX initialization is
61called. The main initialization function is _tx_initialize_low_level and
62is located in the file tx_initialize_low_level.arm. This function is responsible
63for setting up various system data structures, interrupt vectors, and the
64periodic timer interrupt source of ThreadX.
65
66In addition, _tx_initialize_low_level determines where the first available
67RAM memory address is located. This address is supplied to tx_application_define.
68
69By default, the first available RAM memory address is assumed to start at the
70beginning of the ThreadX section .free_mem. If changes are made to the
71sample_threadx.ld file, the .free_mem section should remain the last allocated
72section in the main RAM area. The starting address of this section is passed
73to tx_application_define.
74
75
766. User defines
77
78The following defines and their associated action are as follows:
79
80 Define Meaning
81
82 TX_ENABLE_IRQ_NESTING If defined, this brings in special IRQ
83 interrupt nesting logic into the ThreadX
84 library. This define should be applied
85 to the entire ThreadX library.
86
87 TX_ENABLE_FIQ_NESTING If defined, this brings in special FIQ
88 interrupt nesting logic into the ThreadX
89 library. This define should be applied
90 to the entire ThreadX library and the
91 define TX_ENABLE_FIQ_SUPPORT should also
92 be defined.
93
94 TX_ENABLE_FIQ_SUPPORT If defined, this brings in FIQ context
95 save and restore logic necessary for
96 applications to call ThreadX services from
97 FIQ interrupt handlers. This define
98 should be applied to the entire ThreadX
99 library.
100
101
102 TX_DISABLE_ERROR_CHECKING If defined before tx_api.h is included,
103 this define causes basic ThreadX error
104 checking to be disabled. Please see
105 Chapter 4 in the "ThreadX User Guide"
106 for more details.
107
108 TX_ENABLE_EVENT_LOGGING This define enables event logging for any
109 or all of the ThreadX source code. If this
110 option is used anywhere, the tx_initialize_high_level.c
111 file must be compiled with it as well, since this
112 is where the event log is initialized.
113
114 TX_NO_EVENT_INFO This is a sub-option for event logging.
115 If this is enabled, only basic information
116 is saved in the log.
117
118 TX_ENABLE_EVENT_FILTERS This is also a sub-option for event-logging.
119 If this is enabled, run-time filtering logic
120 is added to the event logging code.
121
122 TX_MAX_PRIORITIES Defines the priority levels for ThreadX.
123 Legal values range from 32 through
124 1024 (inclusive) and MUST be evenly divisible
125 by 32. Increasing the number of priority levels
126 supported increases the RAM usage by 128 bytes
127 for every group of 32 priorities. However, there
128 is only a negligible effect on performance. By
129 default, this value is set to 32 priority levels.
130
131 TX_MINIMUM_STACK Defines the minimum stack size (in bytes). It is
132 used for error checking when threads are created.
133 The default value is port-specific and is found
134 in tx_port.h.
135
136 TX_TIMER_THREAD_STACK_SIZE Defines the stack size (in bytes) of the internal
137 ThreadX timer thread. This thread processes all
138 thread sleep requests as well as all service call
139 timeouts. In addition, all application timer callback
140 routines are invoked from this context. The default
141 value is port-specific and is found in tx_port.h.
142
143 TX_TIMER_THREAD_PRIORITY Defines the priority of the internal ThreadX timer
144 thread. The default value is priority 0 - the highest
145 priority in ThreadX. The default value is defined
146 in tx_port.h.
147
148 TX_TIMER_PROCESS_IN_ISR Defined, this option eliminates the internal system
149 timer thread for ThreadX. This results in improved
150 performance on timer events and smaller RAM requirements
151 because the timer stack and control block are no
152 longer needed. However, using this option moves all
153 the timer expiration processing to the timer ISR level.
154 By default, this option is not defined.
155
156 TX_REACTIVATE_INLINE Defined, this option performs reactivation of ThreadX
157 timers in-line instead of using a function call. This
158 improves performance but slightly increases code size.
159 By default, this option is not defined.
160
161 TX_DISABLE_STACK_FILLING Defined, placing the 0xEF value in each byte of each
162 thread's stack is disabled. By default, this option is
163 not defined.
164
165 TX_ENABLE_STACK_CHECKING Defined, this option enables ThreadX run-time stack checking,
166 which includes analysis of how much stack has been used and
167 examination of data pattern "fences" before and after the
168 stack area. If a stack error is detected, the registered
169 application stack error handler is called. This option does
170 result in slightly increased overhead and code size. Please
171 review the tx_thread_stack_error_notify API for more information.
172 By default, this option is not defined.
173
174 TX_DISABLE_PREEMPTION_THRESHOLD Defined, this option disables the preemption-threshold feature
175 and slightly reduces code size and improves performance. Of course,
176 the preemption-threshold capabilities are no longer available.
177 By default, this option is not defined.
178
179 TX_DISABLE_REDUNDANT_CLEARING Defined, this option removes the logic for initializing ThreadX
180 global C data structures to zero. This should only be used if
181 the compiler's initialization code sets all un-initialized
182 C global data to zero. Using this option slightly reduces
183 code size and improves performance during initialization.
184 By default, this option is not defined.
185
186 TX_DISABLE_NOTIFY_CALLBACKS Defined, this option disables the notify callbacks for various
187 ThreadX objects. Using this option slightly reduces code size
188 and improves performance.
189
190 TX_BLOCK_POOL_ENABLE_PERFORMANCE_INFO Defined, this option enables the gathering of performance
191 information on block pools. By default, this option is
192 not defined.
193
194 TX_BYTE_POOL_ENABLE_PERFORMANCE_INFO Defined, this option enables the gathering of performance
195 information on byte pools. By default, this option is
196 not defined.
197
198 TX_EVENT_FLAGS_ENABLE_PERFORMANCE_INFO Defined, this option enables the gathering of performance
199 information on event flags groups. By default, this option
200 is not defined.
201
202 TX_MUTEX_ENABLE_PERFORMANCE_INFO Defined, this option enables the gathering of performance
203 information on mutexes. By default, this option is
204 not defined.
205
206 TX_QUEUE_ENABLE_PERFORMANCE_INFO Defined, this option enables the gathering of performance
207 information on queues. By default, this option is
208 not defined.
209
210 TX_SEMAPHORE_ENABLE_PERFORMANCE_INFO Defined, this option enables the gathering of performance
211 information on semaphores. By default, this option is
212 not defined.
213
214 TX_THREAD_ENABLE_PERFORMANCE_INFO Defined, this option enables the gathering of performance
215 information on threads. By default, this option is
216 not defined.
217
218 TX_TIMER_ENABLE_PERFORMANCE_INFO Defined, this option enables the gathering of performance
219 information on timers. By default, this option is
220 not defined.
221
222
223
2247. Register Usage and Stack Frames
225
226The Green Hills compiler assumes that registers r0-r3 (a1-a4) and r12 (ip)
227are scratch registers for each function. All other registers used by a C
228function must be preserved by the function. ThreadX takes advantage of this
229in situations where a context switch happens as a result of making a ThreadX
230service call (which is itself a C function). In such cases, the saved
231context of a thread is only the non-scratch registers.
232
233The following defines the saved context stack frames for context switches
234that occur as a result of interrupt handling or from thread-level API calls.
235All suspended threads have one of these two types of stack frames. The top
236of the suspended thread's stack is pointed to by tx_thread_stack_ptr in the
237associated thread control block TX_THREAD.
238
239
240
241 Offset Interrupted Stack Frame Non-Interrupt Stack Frame
242
243 0x00 1 0
244 0x04 CPSR CPSR
245 0x08 r0 (a1) r4 (v1)
246 0x0C r1 (a2) r5 (v2)
247 0x10 r2 (a3) r6 (v3)
248 0x14 r3 (a4) r7 (v4)
249 0x18 r4 (v1) r8 (v5)
250 0x1C r5 (v2) r9 (v6)
251 0x20 r6 (v3) r10 (v7)
252 0x24 r7 (v4) r11 (fp)
253 0x28 r8 (v5) r14 (lr)
254 0x2C r9 (v6)
255 0x30 r10 (v7)
256 0x34 r11 (fp)
257 0x38 r12 (ip)
258 0x3C r14 (lr)
259 0x40 PC
260
261
2628. Improving Performance
263
264The distribution version of ThreadX is built without any compiler
265optimizations. This makes it easy to debug because you can trace or set
266breakpoints inside of ThreadX itself. Of course, this costs some
267performance. To make ThreadX run faster, you can change the tx.gpj project
268to disable debug information and enable the desired optimizations.
269
270In addition, you can eliminate the ThreadX basic API error checking by
271compiling your application code with the symbol TX_DISABLE_ERROR_CHECKING
272defined before tx_api.h is included.
273
274
2759. Interrupt Handling
276
277ThreadX provides complete and high-performance interrupt handling for Cortex-A5
278targets. There are a certain set of requirements that are defined in the
279following sub-sections:
280
281
2829.1 Vector Area
283
284The Cortex-A5 vectors start at address zero. The demonstration system reset.arm
285file contains the reset section (which contains all the ARM vectors) and is
286typically loaded at address zero. On actual hardware platforms, this section
287might have to be copied to address 0.
288
2899.2 IRQ ISRs
290
291ThreadX fully manages standard and vectored IRQ interrupts. ThreadX also supports nested
292IRQ interrupts. The following sub-sections define the IRQ capabilities.
293
294
2959.2.1 Standard IRQ ISRs
296
297The standard ARM IRQ mechanism has a single interrupt vector at address 0x18. This IRQ
298interrupt is managed by the __tx_irq_handler code in tx_initialize_low_level. The following
299is the default IRQ handler defined in tx_initialize_low_level.arm:
300
301
302 .globl __tx_irq_handler
303 .globl __tx_irq_processing_return
304__tx_irq_handler:
305
306 /* Jump to context save to save system context. */
307 B _tx_thread_context_save
308__tx_irq_processing_return:
309
310 /* At this point execution is still in the IRQ mode. The CPSR, point of
311 interrupt, and all C scratch registers are available for use. Note
312 that IRQ interrupts are still disabled upon return from the context
313 save function. */
314
315 /* Application ISR call(s) go here! */
316
317 /* Jump to context restore to restore system context. */
318 B _tx_thread_context_restore
319
320
3219.2.2 Vectored IRQ ISRs
322
323The vectored ARM IRQ mechanism has multiple interrupt vectors at addresses specified
324by the particular implementation. The following is an example IRQ handler defined in
325tx_initialize_low_level.arm:
326
327 .globl __tx_irq_example_handler
328__tx_irq_example_handler:
329
330 /* Call context save to save system context. */
331
332 STMDB sp!, {r0-r3} # Save some scratch registers
333 MRS r0, SPSR # Pickup saved SPSR
334 SUB lr, lr, #4 # Adjust point of interrupt
335 STMDB sp!, {r0, r10, r12, lr} # Store other scratch registers
336 BL _tx_thread_vectored_context_save # Call the vectored IRQ context save
337
338 /* At this point execution is still in the IRQ mode. The CPSR, point of
339 interrupt, and all C scratch registers are available for use. Note
340 that IRQ interrupts are still disabled upon return from the context
341 save function. */
342
343 /* Application ISR call goes here! */
344
345 /* Jump to context restore to restore system context. */
346 B _tx_thread_context_restore
347
348
3499.2.3 Nested IRQ Support
350
351By default, nested IRQ interrupt support is not enabled. To enable nested
352IRQ support, the entire library should be built with TX_ENABLE_IRQ_NESTING
353defined. With this defined, two new IRQ interrupt management services are
354available, namely _tx_thread_irq_nesting_start and _tx_thread_irq_nesting_end.
355These function should be called between the IRQ context save and restore
356calls.
357
358Execution between the calls to _tx_thread_irq_nesting_start and
359_tx_thread_irq_nesting_end is enabled for IRQ nesting. This is achieved
360by switching from IRQ mode to SYS mode and enabling IRQ interrupts.
361The SYS mode stack is used during the SYS mode operation, which was
362setup in tx_initialize_low_level.arm. When nested IRQ interrupts are no
363longer required, calling the _tx_thread_irq_nesting_end service disables nesting
364by disabling IRQ interrupts and switching back to IRQ mode in preparation for
365the IRQ context restore service.
366
367The following is an example of enabling IRQ nested interrupts in the
368typical IRQ handler:
369
370 .globl __tx_irq_handler
371 .globl __tx_irq_processing_return
372__tx_irq_handler:
373
374 /* Jump to context save to save system context. */
375 B _tx_thread_context_save
376__tx_irq_processing_return:
377
378 /* Enable nested IRQ interrupts. NOTE: Since this service returns
379 with IRQ interrupts enabled, all IRQ interrupt sources must be
380 cleared prior to calling this service. */
381 BL _tx_thread_irq_nesting_start
382
383 /* Application ISR call(s) go here! */
384
385 /* Disable nested IRQ interrupts. The mode is switched back to
386 IRQ mode and IRQ interrupts are disable upon return. */
387 BL _tx_thread_irq_nesting_end
388
389 /* Jump to context restore to restore system context. */
390 B _tx_thread_context_restore
391
392
3939.3 FIQ Interrupts
394
395By default, Cortex-A5 FIQ interrupts are left completely enabled by ThreadX.
396Of course, this means that the application is fully responsible for
397saving/restoring any registers used in the FIQ ISR processing. In addition,
398no ThreadX service calls are allowed from the default FIQ ISRs. The default
399FIQ interrupt shell is located in tx_initialize_low_level.arm.
400
4019.3.1 Managed FIQ Interrupts
402
403Full ThreadX management of FIQ interrupts is provided if the ThreadX sources
404are built with the TX_ENABLE_FIQ_SUPPORT defined. If the library is built
405this way, the FIQ interrupt handlers are very similar to the IRQ interrupt
406handlers defined previously. The following is default FIQ handler
407defined in tx_initialize_low_level.arm:
408
409
410 .globl __tx_fiq_handler
411 .globl __tx_fiq_processing_return
412__tx_fiq_handler:
413
414 /* Jump to fiq context save to save system context. */
415 B _tx_thread_fiq_context_save
416__tx_fiq_processing_return:
417
418 /* At this point execution is still in the FIQ mode. The CPSR, point of
419 interrupt, and all C scratch registers are available for use. */
420
421 /* Application FIQ handlers can be called here! */
422
423 /* Jump to fiq context restore to restore system context. */
424 B _tx_thread_fiq_context_restore
425
426
4279.3.1.1 Nested FIQ Support
428
429By default, nested FIQ interrupt support is not enabled. To enable nested
430FIQ support, the entire library should be built with TX_ENABLE_FIQ_NESTING
431defined. With this defined, two new FIQ interrupt management services are
432available, namely _tx_thread_fiq_nesting_start and _tx_thread_fiq_nesting_end.
433These function should be called between the FIQ context save and restore
434calls.
435
436Execution between the calls to _tx_thread_fiq_nesting_start and
437_tx_thread_fiq_nesting_end is enabled for FIQ nesting. This is achieved
438by switching from FIQ mode to SYS mode and enabling FIQ interrupts.
439The SYS mode stack is used during the SYS mode operation, which was
440setup in tx_initialize_low_level.arm. When nested FIQ interrupts are no longer
441required, calling the _tx_thread_fiq_nesting_end service disables nesting by
442disabling FIQ interrupts and switching back to FIQ mode in preparation for the FIQ
443context restore service.
444
445The following is an example of enabling FIQ nested interrupts in the
446typical FIQ handler:
447
448
449 .globl __tx_fiq_handler
450 .globl __tx_fiq_processing_return
451__tx_fiq_handler:
452
453 /* Jump to fiq context save to save system context. */
454 B _tx_thread_fiq_context_save
455__tx_fiq_processing_return:
456
457 /* At this point execution is still in the FIQ mode. The CPSR, point of
458 interrupt, and all C scratch registers are available for use. */
459
460 /* Enable nested FIQ interrupts. NOTE: Since this service returns
461 with FIQ interrupts enabled, all FIQ interrupt sources must be
462 cleared prior to calling this service. */
463 BL _tx_thread_fiq_nesting_start
464
465 /* Application FIQ handlers can be called here! */
466
467 /* Disable nested FIQ interrupts. The mode is switched back to
468 FIQ mode and FIQ interrupts are disable upon return. */
469 BL _tx_thread_fiq_nesting_end
470
471 /* Jump to fiq context restore to restore system context. */
472 B _tx_thread_fiq_context_restore
473
474
475
47610. ThreadX Timer Interrupt
477
478ThreadX requires a periodic interrupt source to manage all time-slicing,
479thread sleeps, timeouts, and application timers. Without such a timer
480interrupt source, these services are not functional. However, all other
481ThreadX services are operational without a periodic timer source.
482
483To add the timer interrupt processing, simply make a call to
484_tx_timer_interrupt in the IRQ processing. An example of this can be
485found in the file tx_initialize_low_level.arm.
486
487
48811. Thumb/Cortex-A5 Mixed Mode
489
490By default, ThreadX is setup for running in Cortex-A5 32-bit mode. This is
491also true for the demonstration system. It is possible to build any
492ThreadX file and/or the application in Thumb mode. The only exception
493to this is the file tx_thread_shell_entry.c. This file must always be
494built in 32-bit mode.
495
496
49712. VFP Support
498
499By default, VFP support is disabled for each thread. If saving the context of the VFP registers
500is needed, the following API call must be made from the context of the application thread - before
501the VFP usage:
502
503void tx_thread_vfp_enable(void);
504
505After this API is called in the application, VFP registers will be saved/restored for this thread if it
506is preempted via an interrupt. All other suspension of the this thread will not require the VFP registers
507to be saved/restored.
508
509To disable VFP register context saving, simply call the following API:
510
511void tx_thread_vfp_disable(void);
512
513
51413. Revision History
515
516For generic code revision information, please refer to the readme_threadx_generic.txt
517file, which is included in your distribution. The following details the revision
518information associated with this specific port of ThreadX:
519
52004-02-2021 Release 6.1.6 changes:
521 tx_port.h Updated macro definition
522
52305/19/2020 Initial ThreadX version of Cortex-A5/Green Hills port.
524
525
526Copyright(c) 1996-2020 Microsoft Corporation
527
528
529https://azure.com/rtos
530
531