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