1 Microsoft's Azure RTOS ThreadX for RISC-V 2 3 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.ewp 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 RISC-V 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 RISC-V simulator. 29 30 313. System Initialization 32 33The entry point in ThreadX for the RISC-V using IAR tools is at label 34__iar_program_start. This is defined within the IAR compiler's startup code. In 35addition, this is where all static and global preset C variable 36initialization processing takes place. 37 38The ThreadX tx_initialize_low_level.s file is responsible for setting up 39various system data structures, and a periodic timer interrupt source. 40 41The _tx_initialize_low_level function inside of tx_initialize_low_level.s 42also determines the first available address for use by the application, which 43is supplied as the sole input parameter to your application definition function, 44tx_application_define. To accomplish this, a section is created in 45tx_initialize_low_level.s called FREE_MEM, which must be located after all 46other RAM sections in memory. 47 48 494. Register Usage and Stack Frames 50 51The IAR RISC-V compiler assumes that registers t0-t6 and a0-a7 are scratch 52registers for each function. All other registers used by a C function must 53be preserved by the function. ThreadX takes advantage of this in situations 54where a context switch happens as a result of making a ThreadX service call 55(which is itself a C function). In such cases, the saved context of a thread 56is only the non-scratch registers. 57 58The following defines the saved context stack frames for context switches 59that occur as a result of interrupt handling or from thread-level API calls. 60All suspended threads have one of these two types of stack frames. The top 61of the suspended thread's stack is pointed to by tx_thread_stack_ptr in the 62associated thread control block TX_THREAD. 63 64 65 66 Offset Interrupted Stack Frame Non-Interrupt Stack Frame 67 68 0x00 1 0 69 0x04 s11 (x27) s11 (x27) 70 0x08 s10 (x26) s10 (x26) 71 0x0C s9 (x25) s9 (x25) 72 0x10 s8 (x24) s8 (x24) 73 0x14 s7 (x23) s7 (x23) 74 0x18 s6 (x22) s6 (x22) 75 0x1C s5 (x21) s5 (x21) 76 0x20 s4 (x20) s4 (x20) 77 0x24 s3 (x19) s3 (x19) 78 0x28 s2 (x18) s2 (x18) 79 0x2C s1 (x9) s1 (x9) 80 0x30 s0 (x8) s0 (x8) 81 0x34 t6 (x31) ra (x1) 82 0x38 t5 (x30) mstatus 83 0x3C t4 (x29) fs0 84 0x40 t3 (x28) fs1 85 0x44 t2 (x7) fs2 86 0x48 t1 (x6) fs3 87 0x4C t0 (x5) fs4 88 0x50 a7 (x17) fs5 89 0x54 a6 (x16) fs6 90 0x58 a5 (x15) fs7 91 0x5C a4 (x14) fs8 92 0x60 a3 (x13) fs9 93 0x64 a2 (x12) fs10 94 0x68 a1 (x11) fs11 95 0x6C a0 (x10) fcsr 96 0x70 ra (x1) 97 0x74 reserved 98 0x78 mepc 99#if __iar_riscv_base_isa == rv32e 100 0x7C ft0 101 0x80 ft1 102 0x84 ft2 103 0x88 ft3 104 0x8C ft4 105 0x90 ft5 106 0x94 ft6 107 0x98 ft7 108 0x9C fs0 109 0xA0 fs1 110 0xA4 fa0 111 0xA8 fa1 112 0xAC fa2 113 0xB0 fa3 114 0xB4 fa4 115 0xB8 fa5 116 0xBC fa6 117 0xC0 fa7 118 0xC4 fs2 119 0xC8 fs3 120 0xCC fs4 121 0xD0 fs5 122 0xD4 fs6 123 0xD8 fs7 124 0xDC fs8 125 0xE0 fs9 126 0xE4 fs10 127 0xE8 fs11 128 0xEC ft8 129 0xF0 ft9 130 0xF4 ft10 131 0xF8 ft11 132 0xFC fcsr 133#endif 134 135 1365. Improving Performance 137 138The distribution version of ThreadX is built without any compiler 139optimizations. This makes it easy to debug because you can trace or set 140breakpoints inside of ThreadX itself. Of course, this costs some 141performance. To make ThreadX run faster, you can change the project 142options to disable debug information and enable the desired 143compiler optimizations. 144 145In addition, you can eliminate the ThreadX basic API error checking by 146compiling your application code with the symbol TX_DISABLE_ERROR_CHECKING 147defined before tx_api.h is included. 148 149 1506. Interrupt Handling 151 152ThreadX provides complete and high-performance interrupt handling for RISC-V 153targets.The ThreadX general exception handler sample is defined as follows, 154where "*" represents the interrupt vector number: 155 156 PUBLIC _sample_interrupt_handler 157 PUBLIC __minterrupt_00000* 158 EXTWEAK __require_minterrupt_vector_table 159_sample_interrupt_handler: 160__minterrupt_00000*: 161 REQUIRE __require_minterrupt_vector_table 162 163 164 /* Before calling _tx_thread_context_save, we have to allocate an interrupt 165 stack frame and save the current value of x1 (ra). */ 166#if __iar_riscv_base_isa == rv32e 167 addi sp, sp, -260 ; Allocate space for all registers - with floating point enabled 168#else 169 addi sp, sp, -128 ; Allocate space for all registers - without floating point enabled 170#endif 171 sw x1, 0x70(sp) ; Store RA 172 call _tx_thread_context_save ; Call ThreadX context save 173 174 /* Call your ISR processing here! */ 175 call your_ISR_processing 176 177 /* Timer interrupt processing is done, jump to ThreadX context restore. */ 178 j _tx_thread_context_restore ; Jump to ThreadX context restore function. Note: this does not return! 179 180 181Some additional conditions: 182 183 1. In the project settings Linker -> Extra Options, --auto_vector_setup should be defined. 184 2. The project linker control file should have the following sections to include the vector table: 185 186 define block MVECTOR with alignment = 128 { ro section .mintvec }; 187 188 if (isdefinedsymbol(_uses_clic)) 189 { 190 define block MINTERRUPT with alignment = 128 { ro section .mtext }; 191 define block MINTERRUPTS { block MVECTOR, 192 block MINTERRUPT }; 193 } 194 else 195 { 196 define block MINTERRUPTS with maximum size = 64k { ro section .mtext, 197 midway block MVECTOR }; 198 } 199 2006.1 Sample Timer ISR 201 202The following sample timer ISR using vector 7 is defined in tx_initialize_low_level.s such that timer 203functionality is available under IAR simulation: 204 205 PUBLIC _tx_timer_interrupt_handler 206 PUBLIC __minterrupt_000007 207 EXTWEAK __require_minterrupt_vector_table 208_tx_timer_interrupt_handler: 209__minterrupt_000007: 210 REQUIRE __require_minterrupt_vector_table 211 212 213 /* Before calling _tx_thread_context_save, we have to allocate an interrupt 214 stack frame and save the current value of x1 (ra). */ 215#if __iar_riscv_base_isa == rv32e 216 addi sp, sp, -260 ; Allocate space for all registers - with floating point enabled 217#else 218 addi sp, sp, -128 ; Allocate space for all registers - without floating point enabled 219#endif 220 sw x1, 0x70(sp) ; Store RA 221 call _tx_thread_context_save ; Call ThreadX context save 222 223 /* Call the ThreadX timer routine. */ 224 call _tx_timer_interrupt ; Call timer interrupt handler 225 226 /* Timer interrupt processing is done, jump to ThreadX context restore. */ 227 j _tx_thread_context_restore ; Jump to ThreadX context restore function. Note: this does not return! 228 229 2307. Revision History 231 232For generic code revision information, please refer to the readme_threadx_generic.txt 233file, which is included in your distribution. The following details the revision 234information associated with this specific port of ThreadX: 235 23604-02-2021 Release 6.1.6 changes: 237 tx_port.h Updated macro definition 238 23908/09/2020 Initial ThreadX version for RISC-V using IAR Tools. 240 241 242Copyright(c) 1996-2020 Microsoft Corporation 243 244 245https://azure.com/rtos 246 247