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