1; 2; Copyright (c) 2006-2022, RT-Thread Development Team 3; 4; SPDX-License-Identifier: Apache-2.0 5; 6; Change Logs: 7; Date Author Notes 8; 2018-09-01 xuzhuoyi the first version. 9; 2019-06-17 zhaoxiaowei fix bugs of old c28x interrupt api. 10; 2019-07-03 zhaoxiaowei add _rt_hw_calc_csb function to support __rt_ffs. 11; 2019-12-05 xiaolifan add support for hardware fpu32 12; 2022-06-21 guyunjie trim pendsv (RTOSINT_Handler) 13; 2022-08-24 guyunjie fix bugs in context switching 14; 2022-10-15 guyunjie add zero-latency interrupt 15 16 .ref rt_interrupt_to_thread 17 .ref rt_interrupt_from_thread 18 .ref rt_thread_switch_interrupt_flag 19 20 .def rtosint_handler 21 .def rt_hw_get_st0 22 .def rt_hw_get_st1 23 .def rt_hw_calc_csb 24 .def rt_hw_context_switch_interrupt 25 .def rt_hw_context_switch 26 .def rt_hw_context_switch_to 27 .def rt_hw_interrupt_thread_switch 28 .def rt_hw_interrupt_disable 29 .def rt_hw_interrupt_enable 30 31 ;importing settings from compiler and config 32 .cdecls C,NOLIST 33 %{ 34 #include <rtconfig.h> 35 36 #ifdef __TMS320C28XX_FPU32__ 37 #define __FPU32__ 1 38 #else 39 #define __FPU32__ 0 40 #endif 41 42 #ifdef __TMS320C28XX_FPU64__ 43 #define __FPU64__ 1 44 #else 45 #define __FPU64__ 0 46 #endif 47 48 #ifdef __TMS320C28XX_VCRC__ 49 #define __VCRC__ 1 50 #else 51 #define __VCRC__ 0 52 #endif 53 54 #ifdef RT_USING_ZERO_LATENCY 55 #define ZERO_LATENCY 1 56 #ifndef ZERO_LATENCY_INT_MASK 57 #error ZERO_LATENCY_INT_MASK must be defined for zero latency interrupt 58 #elif ZERO_LATENCY_INT_MASK & 0x8000 59 #error RTOS bit (0x8000) must not be set in ZERO_LATENCY_INT_MASK 60 #endif 61 #else 62 #define ZERO_LATENCY 0 63 #endif 64 %} 65 66 67.text 68 .newblock 69 70; 71; rt_base_t rt_hw_interrupt_disable(); 72; 73 .asmfunc 74rt_hw_interrupt_disable: 75 .if ZERO_LATENCY 76 MOV AL, IER 77 AND IER, #ZERO_LATENCY_INT_MASK 78 .else 79 PUSH ST1 80 SETC INTM 81 POP AL 82 .endif 83 MOV AH, #0 84 LRETR 85 .endasmfunc 86 87; 88; void rt_hw_interrupt_enable(rt_base_t level); 89; 90 .asmfunc 91rt_hw_interrupt_enable: 92 .if ZERO_LATENCY 93 MOV IER, AL 94 .else 95 PUSH AL 96 POP ST1 97 .endif 98 LRETR 99 .endasmfunc 100 101; 102; void rt_hw_context_switch(rt_uint32 from, rt_uint32 to); 103; ACC --> from 104; SP[4] --> to 105; 106 .asmfunc 107rt_hw_context_switch_interrupt: 108 109; ACC, XAR4-7 are "save on call" following TI C28x C/C++ compiler convention 110; and therefore can be used in a function without being saved on stack first 111; (the compiler has already saved it before the call). 112; Reference: TMS320C28x Optimizing CC++ Compiler 113; note this convention is only applicable to normal functions not to isrs 114 115 MOVL XAR6, ACC 116 MOVL XAR4, *-SP[4] 117 ; set rt_thread_switch_interrupt_flag to 1 118 MOVL XAR5, #rt_thread_switch_interrupt_flag 119 MOVL ACC, *XAR5 120 BF reswitch2, NEQ ; ACC!=0 121 MOVB ACC, #1 122 MOVL *XAR5, ACC 123 124 MOVL XAR5, #rt_interrupt_from_thread ; set rt_interrupt_from_thread 125 MOVL *XAR5, XAR6 126 127reswitch2: 128 MOVL XAR5, #rt_interrupt_to_thread ; set rt_interrupt_to_thread 129 MOVL *XAR5, XAR4 130 LRETR 131 .endasmfunc 132 133; 134; void rt_hw_context_switch(rt_uint32 from, rt_uint32 to); 135; ACC --> from 136; SP[4] --> to 137; 138 .asmfunc 139rt_hw_context_switch: 140 141 MOVL XAR6, ACC 142 MOVL XAR4, *-SP[4] 143 ; set rt_thread_switch_interrupt_flag to 1 144 MOVL XAR5, #rt_thread_switch_interrupt_flag 145 MOVL ACC, *XAR5 146 BF reswitch1, NEQ ; ACC!=0 147 MOVB ACC, #1 148 MOVL *XAR5, ACC 149 150 MOVL XAR5, #rt_interrupt_from_thread ; set rt_interrupt_from_thread 151 MOVL *XAR5, XAR6 152 153reswitch1: 154 MOVL XAR5, #rt_interrupt_to_thread ; set rt_interrupt_to_thread 155 MOVL *XAR5, XAR4 156 OR IFR, #0x8000 157 LRETR 158 .endasmfunc 159; 160; * void rt_hw_context_switch_to(rt_uint32 to); 161; * ACC --> to 162; 163 .asmfunc 164rt_hw_context_switch_to: 165 ; get to thread 166 MOVL XAR5, #rt_interrupt_to_thread 167 MOVL *XAR5, ACC 168 169 ; set from thread to 0 170 MOVL XAR5, #rt_interrupt_from_thread 171 MOVL XAR4, #0 172 MOVL *XAR5, XAR4 173 174 ; set interrupt flag to 1 175 MOVL XAR5, #rt_thread_switch_interrupt_flag 176 MOVL XAR4, #1 177 MOVL *XAR5, XAR4 178 179 ; trigger rtos interrupt 180 OR IFR, #0x8000 181 OR IER, #0x8000 182 CLRC INTM 183 184 ; never reach here! 185 .endasmfunc 186 187 .asmfunc 188rtosint_handler: 189 190 .if ZERO_LATENCY 191 ; mask out non-critical interrupts and enable global interrupt 192 ; so rtosint_handler won't block critical interrupts 193 AND IER, #ZERO_LATENCY_INT_MASK 194 CLRC INTM 195 .endif 196 197 MOVL ACC, *-SP[4] 198 MOV AR0, AL ; save original IER 199 200 PUSH AR1H:AR0H 201 PUSH XAR2 202 203 ; get rt_thread_switch_interrupt_flag 204 MOVL XAR1, #rt_thread_switch_interrupt_flag 205 MOVL ACC, *XAR1 206 BF rtosint_exit, EQ ; rtos_int already handled 207 208 ; clear rt_thread_switch_interrupt_flag to 0 209 MOVL XAR2, #0 210 MOVL *XAR1, XAR2 211 212 MOVL XAR1, #rt_interrupt_from_thread 213 MOVL ACC, *XAR1 214 BF switch_to_thread, EQ ; skip register save at the first time 215 216 PUSH XAR3 217 PUSH XAR4 218 PUSH XAR5 219 PUSH XAR6 220 PUSH XAR7 221 PUSH XT 222 PUSH RPC 223 224 .if __FPU32__ 225 PUSH RB 226 MOV32 *SP++, STF 227 MOV32 *SP++, R0H 228 MOV32 *SP++, R1H 229 MOV32 *SP++, R2H 230 MOV32 *SP++, R3H 231 MOV32 *SP++, R4H 232 MOV32 *SP++, R5H 233 MOV32 *SP++, R6H 234 MOV32 *SP++, R7H 235 .endif 236 237 .if __FPU64__ 238 MOV32 *SP++, R0L 239 MOV32 *SP++, R1L 240 MOV32 *SP++, R2L 241 MOV32 *SP++, R3L 242 MOV32 *SP++, R4L 243 MOV32 *SP++, R5L 244 MOV32 *SP++, R6L 245 MOV32 *SP++, R7L 246 .endif 247 248 .if __VCRC__ 249 VMOV32 *SP++, VCRC 250 VMOV32 *SP++, VSTATUS 251 VMOV32 *SP++, VCRCPOLY 252 VMOV32 *SP++, VCRCSIZE 253 .endif 254 255 MOVL ACC, *XAR1 256 MOVL XAR1, ACC 257 MOVZ AR2, @SP ; get from thread stack pointer 258 MOVL *XAR1, XAR2 ; update from thread stack pointer 259 260switch_to_thread: 261 MOVL XAR1, #rt_interrupt_to_thread 262 MOVL ACC, *XAR1 263 MOVL XAR1, ACC 264 MOVL ACC, *XAR1 265 MOV @SP, AL ; load thread stack pointer 266 267 .if __VCRC__ 268 VMOV32 VCRCSIZE, *--SP 269 VMOV32 VCRCPOLY, *--SP 270 VMOV32 VSTATUS, *--SP 271 VMOV32 VCRC, *--SP 272 .endif 273 274 .if __FPU64__ 275 MOV32 R7L, *--SP 276 MOV32 R6L, *--SP 277 MOV32 R5L, *--SP 278 MOV32 R4L, *--SP 279 MOV32 R3L, *--SP 280 MOV32 R2L, *--SP 281 MOV32 R1L, *--SP 282 MOV32 R0L, *--SP 283 .endif 284 285 .if __FPU32__ 286 MOV32 R7H, *--SP 287 MOV32 R6H, *--SP 288 MOV32 R5H, *--SP 289 MOV32 R4H, *--SP 290 MOV32 R3H, *--SP 291 MOV32 R2H, *--SP 292 MOV32 R1H, *--SP 293 MOV32 R0H, *--SP 294 MOV32 STF, *--SP 295 POP RB 296 .endif 297 298 POP RPC 299 POP XT 300 POP XAR7 301 POP XAR6 302 POP XAR5 303 POP XAR4 304 POP XAR3 305 306rtosint_exit: 307 ; do not restore interrupt here: to be restored according to the 308 ; switched-to context during IRET (automaticlly by hardware) 309 310 POP XAR2 311 POP AR1H:AR0H 312 313 MOVL ACC , *-SP[4] 314 MOV AL, AR0 315 MOVL *-SP[4], ACC 316 317 IRET 318 .endasmfunc 319 320 .asmfunc 321rt_hw_get_st0: 322 PUSH ST0 323 POP AL 324 LRETR 325 .endasmfunc 326 327 .asmfunc 328rt_hw_get_st1: 329 PUSH ST1 330 POP AL 331 LRETR 332 .endasmfunc 333 334; C28x do not have a build-in "__ffs" func in its C compiler. 335; We can use the "Count Sign Bits" (CSB) instruction to make one. 336; CSB will return the number of 0's minus 1 above the highest set bit. 337; The count is placed in T. For example: 338; ACC T maxbit 339; 0x00000001 30 0 340; 0x00000010 26 4 341; 0x000001FF 22 8 342; 0x000001F0 22 8 343 .asmfunc 344rt_hw_calc_csb: 345 MOV AH, #0 346 CSB ACC ; T = no. of sign bits - 1 347 MOVU ACC, T ; ACC = no. of sign bits - 1 348 SUBB ACC, #30 ; ACC = ACC - 30 349 ABS ACC ; ACC = |ACC| 350 LRETR 351 .endasmfunc 352 353; compatible with old version 354 .asmfunc 355rt_hw_interrupt_thread_switch: 356 LRETR 357 NOP 358 .endasmfunc 359 360.end 361