こんにちは。NoMaYです。Azure RTOSでRXマイコンが使えるようになったのですね。コンパイラはGNURXが使われていました。Getting started with the Renesas Starter Kit+ for RX65N-2MB (英文です。)02/05/2021 Ryan Winterdocs.microsoft.com/ja-jp/samples/azure-rtos/getting-started/getting-started-with-the-renesas-starter-kit-for-rx65n-2mb/
libs/threadx/ports/rxv3/ccrx/src/tx_thread_contex_save.src
;VOID _tx_thread_context_save(VOID);{ .GLB __tx_thread_context_save__tx_thread_context_save:;; /* Upon entry to this routine, it is assumed that interrupts are locked; out and the (interrupt) stack frame looks like the following:;; (lower address) SP -> [return address of this call]; SP+4 -> Saved R1; SP+8 -> Saved R2; SP+12-> Interrupted PC; SP+16-> Interrupted PSW;; /* Check for a nested interrupt condition. */; if (_tx_thread_system_state++); {; MOV.L #__tx_thread_system_state, R1 ; Pick up address of system state MOV.L [R1], R2 ; Pick up system state CMP #0, R2 ; 0 -> no nesting BEQ __tx_thread_not_nested_save;; /* Nested interrupt condition. */; ADD #1, r2 ; _tx_thread_system_state++ MOV.L r2, [r1];; /* Save the rest of the scratch registers on the interrupt stack and return to the; calling ISR. */ POP R1 ; Recuperate return address from stack PUSHM R3-R5 PUSHM R14-R15 PUSHC FPSW ; (top) FPSW, R14, R15, R3, R4, R5, R1, R2, PC, PSW (bottom) JMP R1 ; Return address was preserved in R1;__tx_thread_not_nested_save:; };; /* Otherwise, not nested, check to see if a thread was running. */; else if (_tx_thread_current_ptr); {; ADD #1, R2 ; _tx_thread_system_state++ MOV.L R2, [R1] MOV.L #__tx_thread_current_ptr, R2 ; Pickup current thread pointer MOV.L [R2], R2 CMP #0,R2 ; Is it NULL? BEQ __tx_thread_idle_system_save ; Yes, idle system is running - idle restore;; /* Move stack frame over to the current threads stack. */; /* complete stack frame with registers not saved yet (R3-R5, R14-R15, FPSW) */; MVFC USP, R1 ; Pick up user stack pointer MOV.L 16[R0], R2 MOV.L R2, [-R1] ; Save PSW on thread stack MOV.L 12[R0], R2 MOV.L R2, [-R1] ; Save PC on thread stack MOV.L 8[R0], R2 MOV.L R2, [-R1] ; Save R2 on thread stack MOV.L 4[R0], R2 MOV.L R2, [-R1] ; Save R1 on thread stack MOV.L R5, [-R1] ; Save R5 on thread stack MOV.L R4, [-R1] ; Save R4 on thread stack MOV.L R3, [-R1] ; Save R3 on thread stack MOV.L R15, [-R1] ; Save R15 on thread stack MOV.L R14, [-R1] ; Save R14 on thread stack MVFC FPSW, R3 MOV.L R3, [-R1] ; Save FPSW on thread stack POP R2 ; Pick up return address from interrupt stack ADD #16, R0, R0 ; Correct interrupt stack pointer back to the bottom MVTC R1, USP ; Set user/thread stack pointer JMP R2 ; Return to ISR; }; else; {;__tx_thread_idle_system_save:;; /* Interrupt occurred in the scheduling loop. */; POP R1 ; Pick up return address ADD #16, R0, R0 ; Correct interrupt stack pointer back to the bottom (PC), don't care about saved registers JMP R1 ; Return to caller;; };}
libs/threadx/ports/rxv3/ccrx/src/tx_thread_contex_restore.src
;VOID _tx_thread_context_restore(VOID);{ .GLB __tx_thread_context_restore__tx_thread_context_restore:;; /* Lockout interrupts. */ CLRPSW I ; Disable interrupts; /* Determine if interrupts are nested. */; if (--_tx_thread_system_state); { MOV.L #__tx_thread_system_state, R1 MOV.L [R1], R2 SUB #1, R2 MOV.L R2,[R1] BEQ __tx_thread_not_nested_restore ;; /* Interrupts are nested. */;; /* Recover the saved registers from the interrupt stack; and return to the point of interrupt. */;__tx_thread_nested_restore: POPC FPSW ; Restore FPU status POPM R14-R15 ; Restore R14-R15 POPM R3-R5 ; Restore R3-R5 POPM R1-R2 ; Restore R1-R2 RTE ; Return to point of interrupt, restore PSW including IPL; }__tx_thread_not_nested_restore:;; /* Determine if a thread was interrupted and no preemption is required. */; else if (((_tx_thread_current_ptr) && (_tx_thread_current_ptr == _tx_thread_execute_ptr) ; || (_tx_thread_preempt_disable)); { MOV.L #__tx_thread_current_ptr, R1 ; Pickup current thread ptr address MOV.L [R1], R2 CMP #0, R2 BEQ __tx_thread_idle_system_restore MOV.L #__tx_thread_preempt_disable, R3 ; Pick up preempt disable flag MOV.L [R3], R3 CMP #0, R3 BNE __tx_thread_no_preempt_restore ; If pre-empt disable flag set, we simply return to the original point of interrupt regardless MOV.L #__tx_thread_execute_ptr, R3 ; (_tx_thread_current_ptr != _tx_thread_execute_ptr) CMP [R3], R2 BNE __tx_thread_preempt_restore ; Jump to pre-empt restoring;__tx_thread_no_preempt_restore: SETPSW U ; User stack POPC FPSW ; Restore FPU status POPM R14-R15 ; Restore R14-R15 POPM R3-R5 ; Restore R3-R5 POPM R1-R2 ; Restore R1-R2 RTE ; Return to point of interrupt, restore PSW including IPL; }; else; {__tx_thread_preempt_restore:; /* Save the remaining time-slice and disable it. */; if (_tx_timer_time_slice); { MOV.L #__tx_timer_time_slice, R3 ; Pickup time-slice address MOV.L [R3],R4 ; Pickup actual time-slice CMP #0, R4 BEQ __tx_thread_dont_save_ts ; No time-slice to save;; _tx_thread_current_ptr -> tx_thread_time_slice = _tx_timer_time_slice;; _tx_timer_time_slice = 0;; MOV.L R4,24[R2] ; Save thread's time slice MOV.L #0,R4 ; Clear value MOV.L R4,[R3] ; Disable global time slice flag; }__tx_thread_dont_save_ts:;; /* Now store the remaining registers! */ SETPSW U ; User stack PUSHM R6-R13 MVFACGU #0, A1, R4 ; Save accumulators. MVFACHI #0, A1, R5 MVFACLO #0, A1, R6 PUSHM R4-R6 MVFACGU #0, A0, R4 MVFACHI #0, A0, R5 MVFACLO #0, A0, R6 PUSHM R4-R6.IF __DPFPU == 1 MOV.L 144[R2], R4 ; Get tx_thread_fpu_enable. CMP #0, R4 BEQ __tx_thread_preempt_restore_fpu_skip DPUSHM.D DR0-DR15 ; Save FPU register bank if tx_thread_fpu_enable is not 0. DPUSHM.L DPSW-DECNT__tx_thread_preempt_restore_fpu_skip:.ENDIF;; /* Clear the current task pointer. */; _tx_thread_current_ptr = TX_NULL;; R1 -> _tx_thread_current_ptr; R2 -> *_tx_thread_current_ptr MOV.L R0,8[R2] ; Save thread's stack pointer in thread control block MOV.L #0,R2 ; Build NULL value MOV.L R2,[R1] ; Set current thread to NULL; /* Return to the scheduler. */; _tx_thread_schedule();__tx_thread_idle_system_restore: MVTC #0, PSW ; Reset interrupt priority level to 0 BRA __tx_thread_schedule ; Jump to scheduler; };;}
libs/threadx/ports/rxv3/ccrx/src/tx_thread_schedule.src
;VOID _tx_thread_schedule(VOID);{ .GLB __tx_thread_schedule__tx_thread_schedule:;;; /* Wait for a thread to execute. */; do; { MOV.L #__tx_thread_execute_ptr, R1 ; Address of thread to executer ptr__tx_thread_schedule_loop: SETPSW I ; Enable interrupts CLRPSW I ; Disable interrupts MOV.L [R1],R2 ; Pickup next thread to execute CMP #0,R2 ; Is it NULL? BNE __tx_thread_thread_ready ; Not NULL, schedule the thread ; Idle system - no thread is ready .IF TX_LOW_POWER==1 MOV.L #__tx_thread_preempt_disable, R1 ; Load prempt disable flag. MOV.L [R1], R2 ADD #1, R2 ; Disable preemption while enter/exit MOV.L R2, [R1] BSR _tx_low_power_enter ; Possibly enter low power mode.ENDIF.IF TX_ENABLE_WAIT==1 WAIT ; Wait for interrupt.ENDIF.IF TX_LOW_POWER==1 CLRPSW I ; Disable interrupts (because WAIT enables interrupts) BSR _tx_low_power_exit ; Possibly exit low power mode MOV.L #__tx_thread_preempt_disable, R1 ; Load prempt disable flag. MOV.L [R1], R2 SUB #1, R2 ; Enable preemption MOV.L R2, [R1] MOV.L #__tx_thread_execute_ptr, R1 ; Address of thread to executer ptr.ENDIF BRA __tx_thread_schedule_loop ; Idle system, keep checking__tx_thread_thread_ready:;; }; while(_tx_thread_execute_ptr == TX_NULL);; ; /* Yes! We have a thread to execute. Note that interrupts are locked out at this point. */;; /* Setup the current thread pointer. */; _tx_thread_current_ptr = _tx_thread_execute_ptr;; MOV.L #__tx_thread_current_ptr, R3 MOV.L R2,[R3] ; Setup current thread pointer;; /* Increment the run count for this thread. */; _tx_thread_current_ptr -> tx_thread_run_count++;; MOV.L 4[R2],R3 ; Pickup run count ADD #1,R3 ; Increment run counter MOV.L R3,4[R2] ; Store it back in control block;; /* Setup time-slice, if present. */; _tx_timer_time_slice = _tx_thread_current_ptr -> tx_thread_time_slice;; MOV.L 24[R2],R3 ; Pickup thread time-slice MOV.L #__tx_timer_time_slice,R4 ; Pickup pointer to time-slice MOV.L R3, [R4] ; Setup time-slice ;; /* Switch to the thread's stack. */; SP = _tx_thread_execute_ptr -> tx_thread_stack_ptr; SETPSW U ; User stack mode MOV.L 8[R2],R0 ; Pickup stack pointer;.IF __DPFPU == 1 MOV.L 144[R2], R1 ; Get tx_thread_fpu_enable. CMP #0, R1 BEQ __tx_thread_schedule_fpu_skip DPOPM.L DPSW-DECNT ; Restore FPU register bank if tx_thread_fpu_enable is not 0. DPOPM.D DR0-DR15__tx_thread_schedule_fpu_skip:.ENDIF POPM R1-R3 ; Restore accumulators. MVTACLO R3, A0 MVTACHI R2, A0 MVTACGU R1, A0 POPM R1-R3 MVTACLO R3, A1 MVTACHI R2, A1 MVTACGU R1, A1 POPM R6-R13 ; Recover interrupt stack frame POPC FPSW POPM R14-R15 POPM R3-R5 POPM R1-R2 RTE ; Return to point of interrupt, this restores PC and PSW ;;}