1 Microsoft's Azure RTOS ThreadX for ARM11
2
3 Thumb & 32-bit Mode
4
5 Using the IAR Tools
6
71. Building the ThreadX run-time Library
8
9Building the ThreadX library is easy. First, open the Azure RTOS workspace
10azure_rtos.eww. Next, make the TX project the "active project" in the
11IAR Embedded Workbench and select the "Make" button. You should observe
12assembly and compilation of a series of ThreadX source files. This
13results in the ThreadX run-time library file tx.a, which is needed by
14the application.
15
16
172. Demonstration System
18
19The ThreadX demonstration is designed to execute under the IAR
20Windows-based ARM11 simulator.
21
22Building the demonstration is easy; simply make the sample_threadx.ewp project
23the "active project" in the IAR Embedded Workbench and select the
24"Make" button.
25
26You should observe the compilation of sample_threadx.c (which is the demonstration
27application) and linking with tx.a. The resulting file sample_threadx.out is a
28binary file that can be downloaded and executed on IAR's ARM11 simulator.
29
30A SPECIAL NOTE: The IAR ARM simulator does simulate interrupts. In order
31for the ThreadX demonstration to run properly, a periodic IRQ interrupt must
32be setup in the IAR debugging environment. We recommend setting an IRQ
33interrupt to execute every 9999 cycles.
34
35
363. System Initialization
37
38The entry point in ThreadX for the ARM11 using IAR tools is at label
39?cstartup. This is defined within the IAR compiler's startup code. In
40addition, this is where all static and global preset C variable
41initialization processing takes place.
42
43The ThreadX tx_initialize_low_level.s file is responsible for setting up
44various system data structures, and a periodic timer interrupt source.
45By default, the vector area is defined at the top of cstartup.s, which is
46a slightly modified from the base IAR file.
47
48The _tx_initialize_low_level function inside of tx_initialize_low_level.s
49also determines the first available address for use by the application, which
50is supplied as the sole input parameter to your application definition function,
51tx_application_define. To accomplish this, a section is created in
52tx_initialize_low_level.s called FREE_MEM, which must be located after all
53other RAM sections in memory.
54
55
564. Register Usage and Stack Frames
57
58The IAR ARM compiler assumes that registers r0-r3 (a1-a4) and r12 (ip) are
59scratch registers for each function. All other registers used by a C function
60must be preserved by the function. ThreadX takes advantage of this in
61situations where a context switch happens as a result of making a ThreadX
62service call (which is itself a C function). In such cases, the saved
63context of a thread is only the non-scratch registers.
64
65The following defines the saved context stack frames for context switches
66that occur as a result of interrupt handling or from thread-level API calls.
67All suspended threads have one of these two types of stack frames. The top
68of the suspended thread's stack is pointed to by tx_thread_stack_ptr in the
69associated thread control block TX_THREAD.
70
71
72
73 Offset Interrupted Stack Frame Non-Interrupt Stack Frame
74
75 0x00 1 0
76 0x04 CPSR CPSR
77 0x08 r0 (a1) r4 (v1)
78 0x0C r1 (a2) r5 (v2)
79 0x10 r2 (a3) r6 (v3)
80 0x14 r3 (a4) r7 (v4)
81 0x18 r4 (v1) r8 (v5)
82 0x1C r5 (v2) r9 (v6)
83 0x20 r6 (v3) r10 (v7)
84 0x24 r7 (v4) r11 (fp)
85 0x28 r8 (v5) r14 (lr)
86 0x2C r9 (v6)
87 0x30 r10 (v7)
88 0x34 r11 (fp)
89 0x38 r12 (ip)
90 0x3C r14 (lr)
91 0x40 PC
92
93
945. Conditional Compilation Switches
95
96The following are conditional compilation options for building the ThreadX library
97and application:
98
99
100 TX_ENABLE_FIQ_SUPPORT This assembler/compiler define enables
101 FIQ interrupt handling support in the
102 ThreadX assembly files. If used,
103 it should be used on all assembly
104 files and the generic C source of
105 ThreadX should be compiled with
106 TX_ENABLE_FIQ_SUPPORT defined as well.
107
108 TX_ENABLE_IRQ_NESTING This assembler define enables IRQ
109 nested support. If IRQ nested
110 interrupt support is needed, this
111 define should be applied to
112 tx_initialize_low_level.s.
113
114 TX_ENABLE_FIQ_NESTING This assembler define enables FIQ
115 nested support. If FIQ nested
116 interrupt support is needed, this
117 define should be applied to
118 tx_initialize_low_level.s. In addition,
119 IRQ nesting should also be enabled.
120
121 TX_DISABLE_ERROR_CHECKING If defined before tx_api.h is included,
122 this define causes basic ThreadX error
123 checking to be disabled. Please see
124 Chapter 2 in the "ThreadX User Guide"
125 for more details.
126
127 TX_MAX_PRIORITIES Defines the priority levels for ThreadX.
128 Legal values range from 32 through
129 1024 (inclusive) and MUST be evenly divisible
130 by 32. Increasing the number of priority levels
131 supported increases the RAM usage by 128 bytes
132 for every group of 32 priorities. However, there
133 is only a negligible effect on performance. By
134 default, this value is set to 32 priority levels.
135
136 TX_MINIMUM_STACK Defines the minimum stack size (in bytes). It is
137 used for error checking when threads are created.
138 The default value is port-specific and is found
139 in tx_port.h.
140
141 TX_TIMER_THREAD_STACK_SIZE Defines the stack size (in bytes) of the internal
142 ThreadX timer thread. This thread processes all
143 thread sleep requests as well as all service call
144 timeouts. In addition, all application timer callback
145 routines are invoked from this context. The default
146 value is port-specific and is found in tx_port.h.
147
148 TX_TIMER_THREAD_PRIORITY Defines the priority of the internal ThreadX timer
149 thread. The default value is priority 0 - the highest
150 priority in ThreadX. The default value is defined
151 in tx_port.h.
152
153 TX_TIMER_PROCESS_IN_ISR Defined, this option eliminates the internal system
154 timer thread for ThreadX. This results in improved
155 performance on timer events and smaller RAM requirements
156 because the timer stack and control block are no
157 longer needed. However, using this option moves all
158 the timer expiration processing to the timer ISR level.
159 By default, this option is not defined.
160
161 TX_REACTIVATE_INLINE Defined, this option performs reactivation of ThreadX
162 timers in-line instead of using a function call. This
163 improves performance but slightly increases code size.
164 By default, this option is not defined.
165
166 TX_DISABLE_STACK_FILLING Defined, placing the 0xEF value in each byte of each
167 thread's stack is disabled. By default, this option is
168 not defined.
169
170 TX_ENABLE_STACK_CHECKING Defined, this option enables ThreadX run-time stack checking,
171 which includes analysis of how much stack has been used and
172 examination of data pattern "fences" before and after the
173 stack area. If a stack error is detected, the registered
174 application stack error handler is called. This option does
175 result in slightly increased overhead and code size. Please
176 review the tx_thread_stack_error_notify API for more information.
177 By default, this option is not defined.
178
179 TX_DISABLE_PREEMPTION_THRESHOLD Defined, this option disables the preemption-threshold feature
180 and slightly reduces code size and improves performance. Of course,
181 the preemption-threshold capabilities are no longer available.
182 By default, this option is not defined.
183
184 TX_DISABLE_REDUNDANT_CLEARING Defined, this option removes the logic for initializing ThreadX
185 global C data structures to zero. This should only be used if
186 the compiler's initialization code sets all un-initialized
187 C global data to zero. Using this option slightly reduces
188 code size and improves performance during initialization.
189 By default, this option is not defined.
190
191 TX_DISABLE_NOTIFY_CALLBACKS Defined, this option disables the notify callbacks for various
192 ThreadX objects. Using this option slightly reduces code size
193 and improves performance.
194
195 TX_BLOCK_POOL_ENABLE_PERFORMANCE_INFO Defined, this option enables the gathering of performance
196 information on block pools. By default, this option is
197 not defined.
198
199 TX_BYTE_POOL_ENABLE_PERFORMANCE_INFO Defined, this option enables the gathering of performance
200 information on byte pools. By default, this option is
201 not defined.
202
203 TX_EVENT_FLAGS_ENABLE_PERFORMANCE_INFO Defined, this option enables the gathering of performance
204 information on event flags groups. By default, this option
205 is not defined.
206
207 TX_MUTEX_ENABLE_PERFORMANCE_INFO Defined, this option enables the gathering of performance
208 information on mutexes. By default, this option is
209 not defined.
210
211 TX_QUEUE_ENABLE_PERFORMANCE_INFO Defined, this option enables the gathering of performance
212 information on queues. By default, this option is
213 not defined.
214
215 TX_SEMAPHORE_ENABLE_PERFORMANCE_INFO Defined, this option enables the gathering of performance
216 information on semaphores. By default, this option is
217 not defined.
218
219 TX_THREAD_ENABLE_PERFORMANCE_INFO Defined, this option enables the gathering of performance
220 information on threads. By default, this option is
221 not defined.
222
223 TX_TIMER_ENABLE_PERFORMANCE_INFO Defined, this option enables the gathering of performance
224 information on timers. By default, this option is
225 not defined.
226
227 TX_ENABLE_EVENT_TRACE Defined, this option enables the internal ThreadX trace
228 feature. The trace buffer is supplied at a later time
229 via an application call to tx_trace_enable.
230
231 TX_TRACE_TIME_SOURCE This defines the time-stamp source for event tracing.
232 This define is only pertinent if the ThreadX library is
233 built with TX_ENABLE_EVENT_TRACE defined.
234
235 TX_TRACE_TIME_MASK This defines the number of valid bits in the event trace
236 time-stamp source defined previously. If the time-stamp
237 source is 16-bits, this value should be 0xFFFF. Alternatively,
238 if the time-stamp source is 32-bits, this value should be
239 0xFFFFFFFF. This define is only pertinent if the ThreadX
240 library is built with TX_ENABLE_EVENT_TRACE defined.
241
242 TX_THUMB Defined, this option enables the BX LR calling return sequence
243 in assembly files, to ensure correct operation on systems that
244 use both ARM and Thumb mode. By default, this option is
245 not defined
246
247
248
249
250
2516. Improving Performance
252
253The distribution version of ThreadX is built without any compiler
254optimizations. This makes it easy to debug because you can trace or set
255breakpoints inside of ThreadX itself. Of course, this costs some
256performance. To make it run faster, you can change the ThreadX library
257project to enable various compiler optimizations.
258
259In addition, you can eliminate the ThreadX basic API error checking by
260compiling your application code with the symbol TX_DISABLE_ERROR_CHECKING
261defined.
262
263
2647. Interrupt Handling
265
266ThreadX provides complete and high-performance interrupt handling for ARM11
267targets. There are a certain set of requirements that are defined in the
268following sub-sections:
269
270
2717.1 Vector Area
272
273The ARM11 vectors start at address zero. The demonstration system startup
274cstartup.s file contains the vectors and is loaded at address zero.
275On actual hardware platforms, this area might have to be copied to address 0.
276
277
2787.2 IRQ ISRs
279
280ThreadX fully manages standard and vectored IRQ interrupts. ThreadX also supports nested
281IRQ interrupts. The following sub-sections define the IRQ capabilities.
282
283
2847.2.1 Standard IRQ ISRs
285
286The standard ARM IRQ mechanism has a single interrupt vector at address 0x18. This IRQ
287interrupt is managed by the __tx_irq_handler code in tx_initialize_low_level. The following
288is the default IRQ handler defined in tx_initialize_low_level.s:
289
290 PUBLIC __tx_irq_handler
291 PUBLIC __tx_irq_processing_return
292__tx_irq_handler
293;
294; /* Jump to context save to save system context. */
295 B _tx_thread_context_save
296__tx_irq_processing_return
297;
298; /* At this point execution is still in the IRQ mode. The CPSR, point of
299; interrupt, and all C scratch registers are available for use. Note
300; that IRQ interrupts are still disabled upon return from the context
301; save function. */
302;
303; /* Application ISR dispatch call goes here! */
304;
305; /* Jump to context restore to restore system context. */
306 B _tx_thread_context_restore
307
308
3097.2.2 Vectored IRQ ISRs
310
311The vectored ARM IRQ mechanism has multiple interrupt vectors at addresses specified
312by the particular implementation. The following is an example IRQ handler defined in
313tx_initialize_low_level.s:
314
315
316 RSEG .text:CODE:NOROOT(2)
317 PUBLIC __tx_example_vectored_irq_handler
318__tx_example_vectored_irq_handler
319;
320; /* Jump to context save to save system context. */
321 STMDB sp!, {r0-r3} ; Save some scratch registers
322 MRS r0, SPSR ; Pickup saved SPSR
323 SUB lr, lr, #4 ; Adjust point of interrupt
324 STMDB sp!, {r0, r10, r12, lr} ; Store other registers
325 BL _tx_thread_vectored_context_save
326;
327; /* At this point execution is still in the IRQ mode. The CPSR, point of
328; interrupt, and all C scratch registers are available for use. Note
329; that IRQ interrupts are still disabled upon return from the context
330; save function. */
331;
332; /* Application ISR dispatch call goes here! */
333;
334; /* Jump to context restore to restore system context. */
335 B _tx_thread_context_restore
336
337
3387.2.3 Nested IRQ Support
339
340By default, nested IRQ interrupt support is not enabled. To enable nested
341IRQ support, the entire library should be built with TX_ENABLE_IRQ_NESTING
342defined. With this defined, two new IRQ interrupt management services are
343available, namely _tx_thread_irq_nesting_start and _tx_thread_irq_nesting_end.
344These function should be called between the IRQ context save and restore
345calls.
346
347Execution between the calls to _tx_thread_irq_nesting_start and
348_tx_thread_irq_nesting_end is enabled for IRQ nesting. This is achieved
349by switching from IRQ mode to SYS mode and enabling IRQ interrupts.
350The SYS mode stack is used during the SYS mode operation, which was
351setup in tx_initialize_low_level.s. When nested IRQ interrupts are no
352longer required, calling the _tx_thread_irq_nesting_end service disables
353nesting by disabling IRQ interrupts and switching back to IRQ mode in
354preparation for the IRQ context restore service.
355
356The following is an example of enabling IRQ nested interrupts in a standard
357IRQ handler:
358
359 RSEG .text:CODE:NOROOT(2)
360 PUBLIC __tx_irq_handler
361 RSEG .text:CODE:NOROOT(2)
362 PUBLIC __tx_irq_processing_return
363__tx_irq_handler
364;
365; /* Jump to context save to save system context. */
366 B _tx_thread_context_save
367__tx_irq_processing_return
368;
369; /* At this point execution is still in the IRQ mode. The CPSR, point of
370; interrupt, and all C scratch registers are available for use. Note
371; that IRQ interrupts are still disabled upon return from the context
372; save function. */
373;
374; /* Interrupt nesting is allowed after calling _tx_thread_irq_nesting_start
375; from IRQ mode with interrupts disabled. This routine switches to the
376; system mode and returns with IRQ interrupts enabled.
377;
378; NOTE: It is very important to ensure all IRQ interrupts are cleared
379; prior to enabling nested IRQ interrupts. */
380;
381 BL _tx_thread_irq_nesting_start
382
383; /* Application ISR dispatch call goes here! */
384;
385; /* If interrupt nesting was started earlier, the end of interrupt nesting
386; service must be called before returning to _tx_thread_context_restore.
387; This routine returns in processing in IRQ mode with interrupts disabled. */
388;
389 BL _tx_thread_irq_nesting_end
390;
391; /* Jump to context restore to restore system context. */
392 B _tx_thread_context_restore
393
394
3957.3 FIQ Interrupts
396
397By default, ARM11 FIQ interrupts are left alone by ThreadX. Of course, this
398means that the application is fully responsible for enabling the FIQ interrupt
399and saving/restoring any registers used in the FIQ ISR processing. To globally
400enable FIQ interrupts, the application should enable FIQ interrupts at the
401beginning of each thread or before any threads are created in tx_application_define.
402In addition, the application must ensure that no ThreadX service calls are made
403from default FIQ ISRs, which is located in tx_initialize_low_level.s.
404
405
4067.3.1 Managed FIQ Interrupts
407
408Full ThreadX management of FIQ interrupts is provided if the ThreadX sources
409are built with the TX_ENABLE_FIQ_SUPPORT defined. If the library is built
410this way, the FIQ interrupt handlers are very similar to the IRQ interrupt
411handlers defined previously. The following is default FIQ handler
412defined in tx_initialize_low_level.s:
413
414
415 RSEG .text:CODE:NOROOT(2)
416 PUBLIC __tx_fiq_handler
417 RSEG .text:CODE:NOROOT(2)
418 PUBLIC __tx_fiq_processing_return
419__tx_fiq_handler
420;
421; /* Jump to fiq context save to save system context. */
422 B _tx_thread_fiq_context_save
423__tx_fiq_processing_return:
424;
425; /* At this point execution is still in the FIQ mode. The CPSR, point of
426; interrupt, and all C scratch registers are available for use. */
427;
428; /* Application FIQ dispatch call goes here! */
429;
430; /* Jump to fiq context restore to restore system context. */
431 B _tx_thread_fiq_context_restore
432
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
449longer required, calling the _tx_thread_fiq_nesting_end service disables
450nesting by disabling FIQ interrupts and switching back to FIQ mode in
451preparation for the FIQ context restore service.
452
453The following is an example of enabling FIQ nested interrupts in the
454typical FIQ handler:
455
456
457 RSEG .text:CODE:NOROOT(2)
458 PUBLIC __tx_fiq_handler
459 RSEG .text:CODE:NOROOT(2)
460 PUBLIC __tx_fiq_processing_return
461__tx_fiq_handler
462;
463; /* Jump to fiq context save to save system context. */
464 B _tx_thread_fiq_context_save
465__tx_fiq_processing_return:
466;
467; /* At this point execution is still in the FIQ mode. The CPSR, point of
468; interrupt, and all C scratch registers are available for use. */
469;
470; /* Enable nested FIQ interrupts. NOTE: Since this service returns
471; with FIQ interrupts enabled, all FIQ interrupt sources must be
472; cleared prior to calling this service. */
473 BL _tx_thread_fiq_nesting_start
474;
475; /* Application FIQ dispatch call goes here! */
476;
477; /* Disable nested FIQ interrupts. The mode is switched back to
478; FIQ mode and FIQ interrupts are disable upon return. */
479 BL _tx_thread_fiq_nesting_end
480;
481; /* Jump to fiq context restore to restore system context. */
482 B _tx_thread_fiq_context_restore
483
484
4858. ThreadX Timer Interrupt
486
487ThreadX requires a periodic interrupt source to manage all time-slicing,
488thread sleeps, timeouts, and application timers. Without such a timer
489interrupt source, these services are not functional. However, all other
490ThreadX services are operational without a periodic timer source.
491
492To add the timer interrupt processing, simply make a call to _tx_timer_interrupt
493in the IRQ processing.
494
495
4969. Thumb/ARM11 Mixed Mode
497
498By default, ThreadX is setup for running in ARM11 32-bit mode. This is
499also true for the demonstration system. It is possible to build any
500ThreadX file and/or the application in Thumb mode. The only exception
501to this is the file tx_thread_shell_entry.c. This file must always be
502built in 32-bit mode. In addition, if any Thumb code is used the entire
503ThreadX assembly source should be built with TX_THUMB defined.
504
505
50610. IAR Thread-safe Library Support
507
508Thread-safe support for the IAR tools is easily enabled by building the ThreadX library
509and the application with TX_ENABLE_IAR_LIBRARY_SUPPORT. Also, the linker control file
510should have the following line added (if not already in place):
511
512initialize by copy with packing = none { section __DLIB_PERTHREAD }; // Required in a multi-threaded application
513
514The project options "General Options -> Library Configuration" should also have the
515"Enable thread support in library" box selected.
516
517
51811. Revision History
519
52004-02-2021 Release 6.1.6 changes:
521 tx_port.h Updated macro definition
522
52309-30-2020 Initial ThreadX 6.1 version for ARM11 using IAR's ARM tools.
524
525
526Copyright(c) 1996-2020 Microsoft Corporation
527
528
529https://azure.com/rtos
530
531