/* * Copyright (c) 2006-2022, RT-Thread Development Team * * SPDX-License-Identifier: Apache-2.0 * * Change Logs: * Date Author Notes * 2011-02-23 Bernard the first version * 2012-03-03 xuzhenglim modify for rx62N */ #include #include #include "cpuconfig.h" #include "machine.h" #include "iorx62n.h" #define ENTER_INTERRUPT() ICU.SWINTR.BIT.SWINT = 1; extern volatile rt_uint8_t rt_interrupt_nest; /* switch flag on interrupt and thread pointer to save switch record */ rt_uint32_t rt_interrupt_from_thread; rt_uint32_t rt_interrupt_to_thread; rt_uint32_t rt_thread_switch_interrupt_flag; /* stack frame*/ struct stack_frame { rt_uint32_t ACCLO; rt_uint32_t ACCHI; rt_uint32_t FPSW; rt_uint32_t R1; rt_uint32_t R2; rt_uint32_t R3; rt_uint32_t R4; rt_uint32_t R5; rt_uint32_t R6; rt_uint32_t R7; rt_uint32_t R8; rt_uint32_t R9; rt_uint32_t R10; rt_uint32_t R11; rt_uint32_t R12; rt_uint32_t R13; rt_uint32_t R14; rt_uint32_t R15; //there is not R0 register,it is special for stack pointer rt_uint32_t PC; rt_uint32_t PSW; }; /** * Initilial the thread stack. * * @author LXZ (2014/11/8) * * @param void* tentry * @param void* parameter * @param rt_uint8_t* stack_addr * @param void* texit * * @return rt_uint8_t* */ rt_uint8_t *rt_hw_stack_init(void *tentry, void *parameter, rt_uint8_t *stack_addr, void *texit) { unsigned long *stk; struct stack_frame *stack_frame; unsigned long i; stk = (unsigned long *)stack_addr; *(stk) = (unsigned long)texit; stack_frame = (struct stack_frame *)(stack_addr - sizeof(struct stack_frame)) ; //Initilial all register for (i = 0; i < sizeof(struct stack_frame) / sizeof(rt_uint32_t); i ++) { ((rt_uint32_t *)stack_frame)[i] = 0xdeadbeef; } stack_frame->PSW = (unsigned long)0x00030000 ; /* psw */ stack_frame->PC = (unsigned long)tentry; /* thread entery*/ stack_frame->R1 = (unsigned long )parameter; /* r1 : parameter */ stack_frame->FPSW = 0x00000100; /* fpsw */ return(rt_uint8_t *)stack_frame; } #if defined(RT_USING_FINSH) && defined(MSH_USING_BUILT_IN_COMMANDS) extern void list_thread(void); #endif extern rt_thread_t rt_current_thread; /** * deal exception * * @author LXZ (2014/11/8) * * @param struct stack_frame* exception_contex */ void rt_hw_hard_fault_exception(struct stack_frame* exception_contex) { if (exception_contex != RT_NULL) { rt_kprintf("psw: 0x%08x\n", exception_contex->PSW); rt_kprintf("pc: 0x%08x\n", exception_contex->PC); rt_kprintf("r0: 0x%08x\n", exception_contex->R1); rt_kprintf("r0: 0x%08x\n", exception_contex->R2); rt_kprintf("r0: 0x%08x\n", exception_contex->R3); rt_kprintf("r0: 0x%08x\n", exception_contex->R4); rt_kprintf("r0: 0x%08x\n", exception_contex->R5); rt_kprintf("r0: 0x%08x\n", exception_contex->R6); rt_kprintf("r0: 0x%08x\n", exception_contex->R7); rt_kprintf("r0: 0x%08x\n", exception_contex->R8); rt_kprintf("r0: 0x%08x\n", exception_contex->R9); rt_kprintf("r0: 0x%08x\n", exception_contex->R10); rt_kprintf("r0: 0x%08x\n", exception_contex->R11); rt_kprintf("r0: 0x%08x\n", exception_contex->R12); rt_kprintf("r0: 0x%08x\n", exception_contex->R13); rt_kprintf("r0: 0x%08x\n", exception_contex->R14); rt_kprintf("r0: 0x%08x\n", exception_contex->R15); rt_kprintf("fpsw: 0x%08x\n", exception_contex->FPSW); rt_kprintf("acchi: 0x%08x\n", exception_contex->ACCHI); rt_kprintf("acclo: 0x%08x\n", exception_contex->ACCLO); } rt_kprintf("hard fault on thread: %s\n", rt_current_thread->parent.name); #if defined(RT_USING_FINSH) && defined(MSH_USING_BUILT_IN_COMMANDS) list_thread(); #endif while (1); } /** * switch thread in interrupt * * @author LXZ (2014/11/8) * * @param rt_uint32_t from * @param rt_uint32_t to */ void rt_hw_context_switch(rt_uint32_t from, rt_uint32_t to) { if (rt_thread_switch_interrupt_flag == 0) { rt_thread_switch_interrupt_flag = 1; rt_interrupt_from_thread = from; } rt_interrupt_to_thread = to; ENTER_INTERRUPT(); } /** * switch thread out the interrupt * * @author LXZ (2014/11/8) * * @param rt_uint32_t from * @param rt_uint32_t to */ void rt_hw_context_switch_interrupt(rt_uint32_t from, rt_uint32_t to) { if (rt_thread_switch_interrupt_flag == 0) { rt_thread_switch_interrupt_flag = 1; rt_interrupt_from_thread = from; } rt_interrupt_to_thread = to; ENTER_INTERRUPT(); } /** * switch to the first thread,it just call one time * * @author LXZ (2014/11/8) * * @param rt_uint32_t to */ void rt_hw_context_switch_to(rt_uint32_t to) { rt_interrupt_from_thread = 0; rt_interrupt_to_thread = to; rt_thread_switch_interrupt_flag = 1; /* enable interrupt*/ _IEN( _ICU_SWINT ) = 1; /*clear the interrupt flag*/ _IR( _ICU_SWINT ) = 0; _IPR( _ICU_SWINT ) = MAX_SYSCALL_INTERRUPT_PRIORITY + 1; /*touch the software interrupt*/ ENTER_INTERRUPT(); /*wait for first thread start up*/ while(1); }