zephyr/arch/rx/core/switch.S
Duy Nguyen fb7bdf0df4 arch: Initial support for RX architecture support
This commit add require code for supporting RX architecture
to Zephyr, it include:
- Add require config and CMakelists for RX arch
- Intialization startup code for RX
- Interrupt and exception handling
- Thread creation adn thread context switch
- irq offload using SW interrupt

Signed-off-by: Duy Nguyen <duy.nguyen.xa@renesas.com>
2025-05-02 09:18:16 +02:00

138 lines
4.0 KiB
ArmAsm

/*
* Copyright (c) 2021 KT-Elektronik, Klaucke und Partner GmbH
* Copyright (c) 2024 Renesas Electronics Corporation
* SPDX-License-Identifier: Apache-2.0
*/
#include <zephyr/toolchain.h>
#include <zephyr/linker/sections.h>
#include <offsets_short.h>
GTEXT(_z_rx_arch_switch)
GTEXT(_switch_isr_wrapper)
/* void z_rx_arch_switch(void *switch_to, void **switched_from)
*
* @brief switch between threads
*
* @param switch_to (r1) pointer to switch handle of the new thread
* @param switched_from (r2) pointer to pointer to switch handle of the old
* thread
*
* Thread-switching is treated differently depending on whether it is a
* cooperative switch triggered by old thread itself or a preemptive switch
* triggered by an interrupt (in this case the function has been called from an
* ISR).
*/
.section .text._z_rx_arch_switch
.align 4
_z_rx_arch_switch:
mvfc psw,r3
tst #0x130000, r3 /* test if PM, U or I bit are set*/
bz _z_rx_context_switch_isr /* if none of them are set, this is an isr */
mov #_coop_switch_to,r3
mov r1,[r3]
mov #_coop_switched_from,r3
mov r2,[r3]
/* trigger unconditional interrupt dedicated to thread switching. The content of r1 and r2
* will not change by invoking the interrupt so the parameters switch_to and switched_from
* will be available in _z_rx_context_switch_isr, which has been entered into the vector
* table as ISR for interrupt 1
*/
int #1
/* at this point, r0 points to the entry point, so RTS will enter it */
rts
/* void switch_isr_wrapper(void)
*
* @brief isr for interrupt 1 as wrapper for _z_rx_context_switch_isr
*
* _z_rx_context_switch_isr ends in rts, so it does not return from the interrupt context
*/
.section .text._switch_isr_wrapper
.align 4
_switch_isr_wrapper:
pushm r1-r15
/* Save the accumulator. */
mvfachi r15 /* Accumulator high 32 bits. */
push r15
mvfacmi r15 /* Accumulator middle 32 bits. */
shll #16, r15 /* Shifted left as it is restored to the low order word.*/
push r15
mov #_coop_switch_to,r3
mov [r3],r1
mov #_coop_switched_from,r3
mov [r3],r2
bsr _z_rx_context_switch_isr
/* Restore the registers from the stack of the task pointed to by
pxCurrentTCB. */
pop r15
mvtaclo r15 /* Accumulator low 32 bits. */
pop r15
mvtachi r15 /* Accumulator high 32 bits. */
popm r1-r15
rte
/* void z_rx_context_switch_isr(void *switch_to, void **switched_from)
*
* @brief switch between threads in the interrupt context
*
* @param switch_to (r1) pointer to switch handle of the new thread
* @param switched_from (r2) pointer to pointer to switch handle of the old thread
*
* since this is part of an ISR, PSW, PC and general registers of the old thread are already
* stored in the interrupt stack, so copy the corresponding part of the interrupt stack to the
* stack of the interrupted thread
*/
_z_rx_context_switch_isr:
/* store arguments switch_to and switched_from to registers r4 and r5 as
* registers r2 and r3 are needed for the smovf operation */
mov r1,r4
mov r2,r5
/* set r2 (smovb source address) to the beginning of the interrupt stack */
mov #(_z_interrupt_stacks + CONFIG_ISR_STACK_SIZE)-1,r2
mvfc usp,r1 /* set r1 (smovb dest) to USP */
sub #1,r1 /* correct by one byte to use smovb compared to push/pop */
/* set r3 to number of bytes to move
* Accumulator 64bit (4byte * 2)
* 15*4 byte for 15 general registers
* + PSW (4 byte)
* + PC (4 byte)
*/
mov #76,r3
smovb /* block copy from interrupt stack to old thread stack */
add #1,r1 /* smovb leaves r1 pointing 1 byte before the stack */
add #1,r2 /* same with r2 */
mov r1,[r5] /* store stack pointer of old thread in *switched_from */
mov r2,r1 /* set r1 (smovf dest) to the beginning of the interrupt stack */
mov r4,r2 /* set r2 (smovf source) to the sp of the new thread*/
mov #76,r3 /* set r3 to number of bytes to move */
smovf /* block copy from new thread stack to interrupt stack */
mvtc r2,usp /* set USP to the new thread stack */
#ifdef CONFIG_INSTRUMENT_THREAD_SWITCHING
bsr _z_thread_mark_switched_in
#endif
rts