1 Microsoft's Azure RTOS ThreadX for ARM9
2
3 Thumb & 32-bit Mode
4
5 Using ARM Compiler 5 (AC5)
6
71. Building the ThreadX run-time Library
8
9First make sure you are in the "example_build" directory. Also, make sure that
10you have setup your path and other environment variables necessary for the ARM
11AC5 development environment. At this point you may run the build_threadx.bat
12batch file. This will build the ThreadX run-time environment in the
13"example_build" directory.
14
15You should observe assembly and compilation of a series of ThreadX source
16files. At the end of the batch file, they are all combined into the
17run-time library file: tx.a. This file must be linked with your
18application in order to use ThreadX.
19
20
212. Demonstration System
22
23The ThreadX demonstration is designed to execute under the ARM
24Windows-based simulator.
25
26Building the demonstration is easy; simply execute the build_threadx_demo.bat
27batch file while inside the "example_build" directory.
28
29You should observe the compilation of sample_threadx.c (which is the demonstration
30application) and linking with tx.a. The resulting file sample_threadx.axf
31is a binary file that can be downloaded and executed on the ARM simulator.
32
33
343. System Initialization
35
36The entry point in ThreadX for the ARM9 using AC5 tools is at label
37__main. This is defined within the AC5 compiler's startup code. In
38addition, this is where all static and global pre-set C variable
39initialization processing takes place.
40
41The ThreadX tx_initialize_low_level.s file is responsible for setting up
42various system data structures, the vector area, and a periodic timer interrupt
43source. By default, the vector area is defined to be located in the Init area,
44which is defined at the top of tx_initialize_low_level.s. This area is typically
45located at 0. In situations where this is impossible, the vectors at the beginning
46of the Init area should be copied to address 0.
47
48This is also where initialization of a periodic timer interrupt source
49should take place.
50
51In addition, _tx_initialize_low_level determines the first available
52address for use by the application, which is supplied as the sole input
53parameter to your application definition function, tx_application_define.
54
55
564. Assembler / Compiler Switches
57
58The following are compiler switches used in building the demonstration
59system:
60
61Compiler Switch Meaning
62
63 -g Specifies debug information
64 -c Specifies object code generation
65 --cpu ARM9TDMI Specifies ARM9TDMI instruction set
66 --apcs /interwork Specifies Thumb/32-bit compatibility
67
68Linker Switch Meaning
69
70 -d Specifies to retain debug information in output file
71 -o demo.axf Specifies demo output file name
72 --elf Specifies elf output file format
73 --ro Specifies that Read-Only memory starts at address 0
74 --first tx_initialize_low_level.o(Init)
75 Specifies that the first area loaded is Init
76 --remove Remove unused areas
77 --list Specifies map file name
78 --symbols Specifies symbols for map file
79 --map Creates a map file
80
81Application Defines
82
83 --PD "TX_ENABLE_FIQ_SUPPORT SETL {TRUE}" This assembler define enables FIQ
84 interrupt handling support in the
85 ThreadX assembly files. If used,
86 it should be used on all assembly
87 files and the generic C source of
88 ThreadX should be compiled with
89 TX_ENABLE_FIQ_SUPPORT defined as well.
90 --PD "TX_ENABLE_IRQ_NESTING SETL {TRUE}" This assembler define enables IRQ
91 nested support. If IRQ nested
92 interrupt support is needed, this
93 define should be applied to
94 tx_initialize_low_level.s.
95 --PD "TX_ENABLE_FIQ_NESTING SETL {TRUE}" This assembler define enables FIQ
96 nested support. If FIQ nested
97 interrupt support is needed, this
98 define should be applied to
99 tx_initialize_low_level.s. In addition,
100 IRQ nesting should also be enabled.
101 -DTX_ENABLE_FIQ_SUPPORT This compiler define enables FIQ
102 interrupt handling in the ThreadX
103 generic C source. This define
104 should also be used in conjunction
105 with the corresponding assembler
106 define.
107 -DTX_DISABLE_ERROR_CHECKING If defined before tx_api.h is included,
108 this define causes basic ThreadX error
109 checking to be disabled. Please see
110 Chapter 2 in the "ThreadX User Guide"
111 for more details.
112
113 -DTX_MAX_PRIORITIES Defines the priority levels for ThreadX.
114 Legal values range from 32 through
115 1024 (inclusive) and MUST be evenly divisible
116 by 32. Increasing the number of priority levels
117 supported increases the RAM usage by 128 bytes
118 for every group of 32 priorities. However, there
119 is only a negligible effect on performance. By
120 default, this value is set to 32 priority levels.
121
122 -DTX_MINIMUM_STACK Defines the minimum stack size (in bytes). It is
123 used for error checking when threads are created.
124 The default value is port-specific and is found
125 in tx_port.h.
126
127 -DTX_TIMER_THREAD_STACK_SIZE Defines the stack size (in bytes) of the internal
128 ThreadX timer thread. This thread processes all
129 thread sleep requests as well as all service call
130 timeouts. In addition, all application timer callback
131 routines are invoked from this context. The default
132 value is port-specific and is found in tx_port.h.
133
134 -DTX_TIMER_THREAD_PRIORITY Defines the priority of the internal ThreadX timer
135 thread. The default value is priority 0 - the highest
136 priority in ThreadX. The default value is defined
137 in tx_port.h.
138
139 -DTX_TIMER_PROCESS_IN_ISR Defined, this option eliminates the internal system
140 timer thread for ThreadX. This results in improved
141 performance on timer events and smaller RAM requirements
142 because the timer stack and control block are no
143 longer needed. However, using this option moves all
144 the timer expiration processing to the timer ISR level.
145 By default, this option is not defined.
146
147 -DTX_REACTIVATE_INLINE Defined, this option performs reactivation of ThreadX
148 timers in-line instead of using a function call. This
149 improves performance but slightly increases code size.
150 By default, this option is not defined.
151
152 -DTX_DISABLE_STACK_FILLING Defined, placing the 0xEF value in each byte of each
153 thread's stack is disabled. By default, this option is
154 not defined.
155
156 -DTX_ENABLE_STACK_CHECKING Defined, this option enables ThreadX run-time stack checking,
157 which includes analysis of how much stack has been used and
158 examination of data pattern "fences" before and after the
159 stack area. If a stack error is detected, the registered
160 application stack error handler is called. This option does
161 result in slightly increased overhead and code size. Please
162 review the tx_thread_stack_error_notify API for more information.
163 By default, this option is not defined.
164
165 -DTX_DISABLE_PREEMPTION_THRESHOLD Defined, this option disables the preemption-threshold feature
166 and slightly reduces code size and improves performance. Of course,
167 the preemption-threshold capabilities are no longer available.
168 By default, this option is not defined.
169
170 -DTX_DISABLE_REDUNDANT_CLEARING Defined, this option removes the logic for initializing ThreadX
171 global C data structures to zero. This should only be used if
172 the compiler's initialization code sets all un-initialized
173 C global data to zero. Using this option slightly reduces
174 code size and improves performance during initialization.
175 By default, this option is not defined.
176
177 -DTX_DISABLE_NOTIFY_CALLBACKS Defined, this option disables the notify callbacks for various
178 ThreadX objects. Using this option slightly reduces code size
179 and improves performance.
180
181 -DTX_BLOCK_POOL_ENABLE_PERFORMANCE_INFO Defined, this option enables the gathering of performance
182 information on block pools. By default, this option is
183 not defined.
184
185 -DTX_BYTE_POOL_ENABLE_PERFORMANCE_INFO Defined, this option enables the gathering of performance
186 information on byte pools. By default, this option is
187 not defined.
188
189 -DTX_EVENT_FLAGS_ENABLE_PERFORMANCE_INFO Defined, this option enables the gathering of performance
190 information on event flags groups. By default, this option
191 is not defined.
192
193 -DTX_MUTEX_ENABLE_PERFORMANCE_INFO Defined, this option enables the gathering of performance
194 information on mutexes. By default, this option is
195 not defined.
196
197 -DTX_QUEUE_ENABLE_PERFORMANCE_INFO Defined, this option enables the gathering of performance
198 information on queues. By default, this option is
199 not defined.
200
201 -DTX_SEMAPHORE_ENABLE_PERFORMANCE_INFO Defined, this option enables the gathering of performance
202 information on semaphores. By default, this option is
203 not defined.
204
205 -DTX_THREAD_ENABLE_PERFORMANCE_INFO Defined, this option enables the gathering of performance
206 information on threads. By default, this option is
207 not defined.
208
209 -DTX_TIMER_ENABLE_PERFORMANCE_INFO Defined, this option enables the gathering of performance
210 information on timers. By default, this option is
211 not defined.
212
213 -DTX_ENABLE_EVENT_TRACE Defined, this option enables the internal ThreadX trace
214 feature. The trace buffer is supplied at a later time
215 via an application call to tx_trace_enable.
216
217 -DTX_TRACE_TIME_SOURCE This defines the time-stamp source for event tracing.
218 This define is only pertinent if the ThreadX library is
219 built with TX_ENABLE_EVENT_TRACE defined.
220
221 -DTX_TRACE_TIME_MASK This defines the number of valid bits in the event trace
222 time-stamp source defined previously. If the time-stamp
223 source is 16-bits, this value should be 0xFFFF. Alternatively,
224 if the time-stamp source is 32-bits, this value should be
225 0xFFFFFFFF. This define is only pertinent if the ThreadX
226 library is built with TX_ENABLE_EVENT_TRACE defined.
227
228
229
2305. Register Usage and Stack Frames
231
232The AC5 compiler assumes that registers r0-r3 (a1-a4) and r12 (ip) are scratch
233registers for each function. All other registers used by a C function must
234be preserved by the function. ThreadX takes advantage of this in situations
235where a context switch happens as a result of making a ThreadX service call
236(which is itself a C function). In such cases, the saved context of a thread
237is only the non-scratch registers.
238
239The following defines the saved context stack frames for context switches
240that occur as a result of interrupt handling or from thread-level API calls.
241All suspended threads have one of these two types of stack frames. The top
242of the suspended thread's stack is pointed to by tx_thread_stack_ptr in the
243associated thread control block TX_THREAD.
244
245
246
247 Offset Interrupted Stack Frame Non-Interrupt Stack Frame
248
249 0x00 1 0
250 0x04 CPSR CPSR
251 0x08 r0 (a1) r4 (v1)
252 0x0C r1 (a2) r5 (v2)
253 0x10 r2 (a3) r6 (v3)
254 0x14 r3 (a4) r7 (v4)
255 0x18 r4 (v1) r8 (v5)
256 0x1C r5 (v2) r9 (v6)
257 0x20 r6 (v3) r10 (v7)
258 0x24 r7 (v4) r11 (fp)
259 0x28 r8 (v5) r14 (lr)
260 0x2C r9 (v6)
261 0x30 r10 (v7)
262 0x34 r11 (fp)
263 0x38 r12 (ip)
264 0x3C r14 (lr)
265 0x40 PC
266
267
2686. Improving Performance
269
270The distribution version of ThreadX is built without any compiler
271optimizations. This makes it easy to debug because you can trace or set
272breakpoints inside of ThreadX itself. Of course, this costs some
273performance. To make it run faster, you can change the build_threadx.bat file to
274remove the -g option and enable all compiler optimizations.
275
276In addition, you can eliminate the ThreadX basic API error checking by
277compiling your application code with the symbol TX_DISABLE_ERROR_CHECKING
278defined.
279
280
2817. Interrupt Handling
282
283ThreadX provides complete and high-performance interrupt handling for ARM9
284targets. There are a certain set of requirements that are defined in the
285following sub-sections:
286
287
2887.1 Vector Area
289
290The ARM9 vectors start at address zero. The demonstration system startup
291Init area contains the vectors and is loaded at address zero. On actual
292hardware platforms, this area might have to be copied to address 0.
293
294
2957.2 IRQ ISRs
296
297ThreadX fully manages standard and vectored IRQ interrupts. ThreadX also supports nested
298IRQ interrupts. The following sub-sections define the IRQ capabilities.
299
300
3017.2.1 Standard IRQ ISRs
302
303The standard ARM IRQ mechanism has a single interrupt vector at address 0x18. This IRQ
304interrupt is managed by the __tx_irq_handler code in tx_initialize_low_level. The following
305is the default IRQ handler defined in tx_initialize_low_level.s:
306
307 EXPORT __tx_irq_handler
308 EXPORT __tx_irq_processing_return
309__tx_irq_handler
310;
311; /* Jump to context save to save system context. */
312 B _tx_thread_context_save ; Jump to the context save
313__tx_irq_processing_return
314;
315; /* At this point execution is still in the IRQ mode. The CPSR, point of
316; interrupt, and all C scratch registers are available for use. Note
317; that IRQ interrupts are still disabled upon return from the context
318; save function. */
319;
320; /* Application ISR call(s) go here! */
321;
322; /* Jump to context restore to restore system context. */
323 B _tx_thread_context_restore
324
325
3267.2.2 Vectored IRQ ISRs
327
328The vectored ARM IRQ mechanism has multiple interrupt vectors at addresses specified
329by the particular implementation. The following is an example IRQ handler defined in
330tx_initialize_low_level.s:
331
332 EXPORT __tx_irq_example_handler
333__tx_irq_example_handler
334;
335; /* Call context save to save system context. */
336
337 STMDB sp!, {r0-r3} ; Save some scratch registers
338 MRS r0, SPSR ; Pickup saved SPSR
339 SUB lr, lr, #4 ; Adjust point of interrupt
340 STMDB sp!, {r0, r10, r12, lr} ; Store other scratch registers
341 BL _tx_thread_vectored_context_save ; Call the vectored IRQ context save
342;
343; /* At this point execution is still in the IRQ mode. The CPSR, point of
344; interrupt, and all C scratch registers are available for use. Note
345; that IRQ interrupts are still disabled upon return from the context
346; save function. */
347;
348; /* Application ISR call goes here! */
349;
350; /* Jump to context restore to restore system context. */
351 B _tx_thread_context_restore
352
353
3547.2.3 Nested IRQ Support
355
356By default, nested IRQ interrupt support is not enabled. To enable nested
357IRQ support, the entire library should be built with TX_ENABLE_IRQ_NESTING
358defined. With this defined, two new IRQ interrupt management services are
359available, namely _tx_thread_irq_nesting_start and _tx_thread_irq_nesting_end.
360These function should be called between the IRQ context save and restore
361calls.
362
363Execution between the calls to _tx_thread_irq_nesting_start and
364_tx_thread_irq_nesting_end is enabled for IRQ nesting. This is achieved
365by switching from IRQ mode to SYS mode and enabling IRQ interrupts.
366The SYS mode stack is used during the SYS mode operation, which was
367setup in tx_initialize_low_level.s. When nested IRQ interrupts are no longer required,
368calling the _tx_thread_irq_nesting_end service disables nesting by disabling
369IRQ interrupts and switching back to IRQ mode in preparation for the IRQ
370context restore service.
371
372The following is an example of enabling IRQ nested interrupts in a standard
373IRQ handler:
374
375 EXPORT __tx_irq_handler
376 EXPORT __tx_irq_processing_return
377__tx_irq_handler
378;
379; /* Jump to context save to save system context. */
380 B _tx_thread_context_save
381__tx_irq_processing_return
382;
383; /* Enable nested IRQ interrupts. NOTE: Since this service returns
384; with IRQ interrupts enabled, all IRQ interrupt sources must be
385; cleared prior to calling this service. */
386 BL _tx_thread_irq_nesting_start
387;
388; /* Application ISR call(s) go here! */
389;
390; /* Disable nested IRQ interrupts. The mode is switched back to
391; IRQ mode and IRQ interrupts are disable upon return. */
392 BL _tx_thread_irq_nesting_end
393;
394; /* Jump to context restore to restore system context. */
395 B _tx_thread_context_restore
396
397
3987.3 FIQ Interrupts
399
400By default, ARM9 FIQ interrupts are left alone by ThreadX. Of course, this
401means that the application is fully responsible for enabling the FIQ interrupt
402and saving/restoring any registers used in the FIQ ISR processing. To globally
403enable FIQ interrupts, the application should enable FIQ interrupts at the
404beginning of each thread or before any threads are created in tx_application_define.
405In addition, the application must ensure that no ThreadX service calls are made
406from default FIQ ISRs, which is located in tx_initialize_low_level.s.
407
408
4097.3.1 Managed FIQ Interrupts
410
411Full ThreadX management of FIQ interrupts is provided if the ThreadX sources
412are built with the TX_ENABLE_FIQ_SUPPORT defined. If the library is built
413this way, the FIQ interrupt handlers are very similar to the IRQ interrupt
414handlers defined previously. The following is default FIQ handler
415defined in tx_initialize_low_level.s:
416
417
418 EXPORT __tx_fiq_handler
419 EXPORT __tx_fiq_processing_return
420__tx_fiq_handler
421;
422; /* Jump to fiq context save to save system context. */
423 B _tx_thread_fiq_context_save
424__tx_fiq_processing_return:
425;
426; /* At this point execution is still in the FIQ mode. The CPSR, point of
427; interrupt, and all C scratch registers are available for use. */
428;
429; /* Application FIQ handlers can be called here! */
430;
431; /* Jump to fiq context restore to restore system context. */
432 B _tx_thread_fiq_context_restore
433
434
4357.3.1.1 Nested FIQ Support
436
437By default, nested FIQ interrupt support is not enabled. To enable nested
438FIQ support, the entire library should be built with TX_ENABLE_FIQ_NESTING
439defined. With this defined, two new FIQ interrupt management services are
440available, namely _tx_thread_fiq_nesting_start and _tx_thread_fiq_nesting_end.
441These function should be called between the FIQ context save and restore
442calls.
443
444Execution between the calls to _tx_thread_fiq_nesting_start and
445_tx_thread_fiq_nesting_end is enabled for FIQ nesting. This is achieved
446by switching from FIQ mode to SYS mode and enabling FIQ interrupts.
447The SYS mode stack is used during the SYS mode operation, which was
448setup in tx_initialize_low_level.s. When nested FIQ interrupts are no longer required,
449calling the _tx_thread_fiq_nesting_end service disables nesting by disabling
450FIQ interrupts and switching back to FIQ mode in preparation for the FIQ
451context restore service.
452
453The following is an example of enabling FIQ nested interrupts in the
454typical FIQ handler:
455
456
457 EXPORT __tx_fiq_handler
458 EXPORT __tx_fiq_processing_return
459__tx_fiq_handler
460;
461; /* Jump to fiq context save to save system context. */
462 B _tx_thread_fiq_context_save
463__tx_fiq_processing_return
464;
465; /* At this point execution is still in the FIQ mode. The CPSR, point of
466; interrupt, and all C scratch registers are available for use. */
467;
468; /* Enable nested FIQ interrupts. NOTE: Since this service returns
469; with FIQ interrupts enabled, all FIQ interrupt sources must be
470; cleared prior to calling this service. */
471 BL _tx_thread_fiq_nesting_start
472;
473; /* Application FIQ handlers can be called here! */
474;
475; /* Disable nested FIQ interrupts. The mode is switched back to
476; FIQ mode and FIQ interrupts are disable upon return. */
477 BL _tx_thread_fiq_nesting_end
478;
479; /* Jump to fiq context restore to restore system context. */
480 B _tx_thread_fiq_context_restore
481
482
4838. ThreadX Timer Interrupt
484
485ThreadX requires a periodic interrupt source to manage all time-slicing,
486thread sleeps, timeouts, and application timers. Without such a timer
487interrupt source, these services are not functional. However, all other
488ThreadX services are operational without a periodic timer source.
489
490To add the timer interrupt processing, simply make a call to
491_tx_timer_interrupt in the IRQ processing. An example of this can be
492found in the file tx_initialize_low_level.s in the Integrator sub-directories.
493
494
4959. Thumb/ARM9 Mixed Mode
496
497By default, ThreadX is setup for running in ARM9 32-bit mode. This is
498also true for the demonstration system. It is possible to build any
499ThreadX file and/or the application in Thumb mode. The only exception
500to this is the file tx_thread_shell_entry.c. This file must always be built
501in 32-bit mode. In addition, if any Thumb code is used the entire ThreadX source-
502both C and assembly - should be built with the "-apcs /interwork" option.
503
504
50510. Revision History
506
507For generic code revision information, please refer to the readme_threadx_generic.txt
508file, which is included in your distribution. The following details the revision
509information associated with this specific port of ThreadX:
510
51104-02-2021 Release 6.1.6 changes:
512 tx_port.h Updated macro definition
513
51409-30-2020 Initial ThreadX 6.1 version for ARM9 using AC5 tools.
515
516
517Copyright(c) 1996-2020 Microsoft Corporation
518
519
520https://azure.com/rtos
521
522