/* * Copyright (c) 2006-2021, RT-Thread Development Team * * SPDX-License-Identifier: Apache-2.0 * * Change Logs: * Date Author Notes * 2018/10/28 Bernard The unify RISC-V porting code. * 2021-02-11 lizhirui add gp support */ #include #include #include "cpuport.h" #include "stack.h" #include #include #define K_SSTATUS_DEFAULT (SSTATUS_SPP | SSTATUS_SPIE | SSTATUS_SUM | SSTATUS_FS) /** * @brief from thread used interrupt context switch * */ volatile rt_ubase_t rt_interrupt_from_thread = 0; /** * @brief to thread used interrupt context switch * */ volatile rt_ubase_t rt_interrupt_to_thread = 0; /** * @brief flag to indicate context switch in interrupt or not * */ volatile rt_ubase_t rt_thread_switch_interrupt_flag = 0; void *_rt_hw_stack_init(rt_ubase_t *sp, rt_ubase_t ra, rt_ubase_t sstatus) { (*--sp) = 0; /* tp */ (*--sp) = ra; /* ra */ (*--sp) = 0; /* s0(fp) */ (*--sp) = 0; /* s1 */ (*--sp) = 0; /* s2 */ (*--sp) = 0; /* s3 */ (*--sp) = 0; /* s4 */ (*--sp) = 0; /* s5 */ (*--sp) = 0; /* s6 */ (*--sp) = 0; /* s7 */ (*--sp) = 0; /* s8 */ (*--sp) = 0; /* s9 */ (*--sp) = 0; /* s10 */ (*--sp) = 0; /* s11 */ (*--sp) = sstatus; /* sstatus */ return (void *)sp; } /** * This function will initialize thread stack, we assuming * when scheduler restore this new thread, context will restore * an entry to user first application * * s0-s11, ra, sstatus, a0 * @param tentry the entry of thread * @param parameter the parameter of entry * @param stack_addr the beginning stack address * @param texit the function will be called when thread exit * * @return stack address */ rt_uint8_t *rt_hw_stack_init(void *tentry, void *parameter, rt_uint8_t *stack_addr, void *texit) { rt_ubase_t *sp = (rt_ubase_t *)stack_addr; // we use a strict alignment requirement for Q extension sp = (rt_ubase_t *)RT_ALIGN_DOWN((rt_ubase_t)sp, 16); (*--sp) = (rt_ubase_t)tentry; (*--sp) = (rt_ubase_t)parameter; (*--sp) = (rt_ubase_t)texit; /* compatible to RESTORE_CONTEXT */ extern void _rt_thread_entry(void); return (rt_uint8_t *)_rt_hw_stack_init(sp, (rt_ubase_t)_rt_thread_entry, K_SSTATUS_DEFAULT); } /* * #ifdef RT_USING_SMP * void rt_hw_context_switch_interrupt(void *context, rt_ubase_t from, rt_ubase_t to, struct rt_thread *to_thread); * #else * void rt_hw_context_switch_interrupt(rt_ubase_t from, rt_ubase_t to); * #endif */ #ifndef RT_USING_SMP void rt_hw_context_switch_interrupt(rt_ubase_t from, rt_ubase_t to, rt_thread_t from_thread, rt_thread_t to_thread) { if (rt_thread_switch_interrupt_flag == 0) rt_interrupt_from_thread = from; rt_interrupt_to_thread = to; rt_thread_switch_interrupt_flag = 1; return; } #endif /* end of RT_USING_SMP */ /** shutdown CPU */ void rt_hw_cpu_shutdown() { rt_uint32_t level; rt_kprintf("shutdown...\n"); level = rt_hw_interrupt_disable(); sbi_shutdown(); while (1) ; } void rt_hw_set_process_id(int pid) { // TODO }