sdk-hwV1.3/lichee/melis-v3.0/source/ekernel/arch/riscv/common/port.c

192 lines
5.3 KiB
C
Raw Normal View History

2024-05-07 10:09:20 +00:00
/*
* Copyright (c) 2019-2025 Allwinner Technology Co., Ltd. ALL rights reserved.
*
* Allwinner is a trademark of Allwinner Technology Co.,Ltd., registered in
* the the People's Republic of China and other countries.
* All Allwinner Technology Co.,Ltd. trademarks are used with permission.
*
* DISCLAIMER
* THIRD PARTY LICENCES MAY BE REQUIRED TO IMPLEMENT THE SOLUTION/PRODUCT.
* IF YOU NEED TO INTEGRATE THIRD PARTYS TECHNOLOGY (SONY, DTS, DOLBY, AVS OR MPEGLA, ETC.)
* IN ALLWINNERSSDK OR PRODUCTS, YOU SHALL BE SOLELY RESPONSIBLE TO OBTAIN
* ALL APPROPRIATELY REQUIRED THIRD PARTY LICENCES.
* ALLWINNER SHALL HAVE NO WARRANTY, INDEMNITY OR OTHER OBLIGATIONS WITH RESPECT TO MATTERS
* COVERED UNDER ANY REQUIRED THIRD PARTY LICENSE.
* YOU ARE SOLELY RESPONSIBLE FOR YOUR USAGE OF THIRD PARTYS TECHNOLOGY.
*
*
* THIS SOFTWARE IS PROVIDED BY ALLWINNER"AS IS" AND TO THE MAXIMUM EXTENT
* PERMITTED BY LAW, ALLWINNER EXPRESSLY DISCLAIMS ALL WARRANTIES OF ANY KIND,
* WHETHER EXPRESS, IMPLIED OR STATUTORY, INCLUDING WITHOUT LIMITATION REGARDING
* THE TITLE, NON-INFRINGEMENT, ACCURACY, CONDITION, COMPLETENESS, PERFORMANCE
* OR MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
* IN NO EVENT SHALL ALLWINNER BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS, OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
* OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <stdlib.h>
#include <rtthread.h>
#include <port.h>
#include <csr.h>
#include <irqflags.h>
#include <excep.h>
#include <cpuport.h>
#include <typedef.h>
#include <debug.h>
#include <rtdef.h>
#include <compiler.h>
unsigned long awos_arch_lock_irq(void)
{
return arch_local_irq_save();
}
void awos_arch_unlock_irq(unsigned long cpu_sr)
{
arch_local_irq_restore(cpu_sr);
}
rt_base_t rt_hw_interrupt_disable(void)
{
return arch_local_irq_save();
}
RTM_EXPORT(rt_hw_interrupt_disable);
void rt_hw_interrupt_enable(rt_base_t level)
{
arch_local_irq_restore(level);
}
RTM_EXPORT(rt_hw_interrupt_enable);
int irqs_disabled(void)
{
return arch_irqs_disabled();
}
void local_irq_enable(void)
{
arch_local_irq_enable();
}
void local_irq_disable(void)
{
arch_local_irq_disable();
}
void finish_task_switch(rt_thread_t ARG_UNUSED(last));
void ret_from_create_c(unsigned long *frsp, unsigned long *tosp)
{
rt_thread_t last = RT_NULL;
rt_thread_t curr = RT_NULL;
/* thread fn of entry. */
register long s1 __asm__("s1");
/* thread paramter of entry. */
register long s2 __asm__("s2");
/* thread exit entry. */
register long s3 __asm__("s3");
void (*entry)(void *) = (void (*)(void *))s1;
void (*exity)(void) = (void (*)(void))s3;
void *parameter = (void *)s2;
if (frsp == RT_NULL)
{
rt_kprintf("scheduler startup\n");
}
else
{
last = rt_container_of(frsp, struct rt_thread, sp);
}
finish_task_switch(last);
curr = rt_container_of(tosp, struct rt_thread, sp);
if (last == rt_thread_self())
{
software_break();
}
else if (curr != rt_thread_self())
{
software_break();
}
// enable local irq.
//arch_local_irq_enable();
if (irqs_disabled())
{
software_break();
}
if (exity != rt_thread_exit)
{
software_break();
}
if (entry)
{
entry(parameter);
}
else
{
software_break();
}
exity();
/* never come here */
CODE_UNREACHABLE;
}
/**
* This function will initialize thread stack
*
* @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
*/
uint8_t *awos_arch_stack_init(void *tentry, void *parameter, uint8_t *stack_addr, void *texit)
{
rt_uint8_t *stk;
switch_ctx_regs_t *frame;
stk = stack_addr + sizeof(rt_ubase_t);
stk = (rt_uint8_t *)RT_ALIGN_DOWN((rt_ubase_t)stk, REGBYTES);
stk -= sizeof(switch_ctx_regs_t);
frame = (switch_ctx_regs_t *)stk;
frame->ra = (rt_ubase_t)ret_from_create_c;
// ABI take as FP, so cant pass parameter by S0.
frame->s[0] = (rt_ubase_t) -1;
frame->s[1] = (rt_ubase_t)tentry;
frame->s[2] = (rt_ubase_t)parameter;
frame->s[3] = (rt_ubase_t)texit;
frame->s[4] = (rt_ubase_t)0xdeadbeef;
frame->s[5] = (rt_ubase_t)0xdeadbeef;
frame->s[6] = (rt_ubase_t)0xdeadbeef;
frame->s[7] = (rt_ubase_t)0xdeadbeef;
frame->s[8] = (rt_ubase_t)0xdeadbeef;
frame->s[9] = (rt_ubase_t)0xdeadbeef;
frame->s[10] = (rt_ubase_t)0xdeadbeef;
frame->s[11] = (rt_ubase_t)0xdeadbeef;
// Restore Previous Interrupt Enable and Previous Privledge level status.
#ifdef CONFIG_RV_MACHINE_MODE
frame->sstatus = MR_MPP | MR_MPIE | SR_FS_CLEAN; /* Supervisor, irqs on, Initial fpu for ready to use */
#else
frame->sstatus = SR_SPP | SR_SPIE | SR_FS_CLEAN; /* Supervisor, irqs on, Initial fpu for ready to use */
#endif
return stk;
}