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

192 lines
5.3 KiB
C
Executable File
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*
* 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;
}