1 Microsoft's Azure RTOS ThreadX for Cortex-A8 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-A8 simulator. The instructions that follow describe 24how to get the ThreadX evaluation running under the MULTI Cortex-A8 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-A8 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-A8 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-A8 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-A8 Mixed Mode 489 490By default, ThreadX is setup for running in Cortex-A8 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 514 51513. Revision History 516 517For generic code revision information, please refer to the readme_threadx_generic.txt 518file, which is included in your distribution. The following details the revision 519information associated with this specific port of ThreadX: 520 52104-02-2021 Release 6.1.6 changes: 522 tx_port.h Updated macro definition 523 52405/19/2020 Initial ThreadX version of Cortex-A8/Green Hills port. 525 526 527Copyright(c) 1996-2020 Microsoft Corporation 528 529 530https://azure.com/rtos 531 532