summaryrefslogtreecommitdiff
path: root/libcpu/risc-v/common/stack.c
blob: d7d428b745d3fedf7307754b438158b196e808eb (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
/*
 * Copyright (c) 2006-2025, 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
 * 2021-11-19     JasonHu      add fpu support
 * 2025-04-20     GuEe-GUI     Port for CPU ID
 */

#include <rtthread.h>

#include <cpu.h>
#include <csr.h>
#include <stack.h>
#include <cpuport.h>
#ifdef ARCH_MM_MMU
#include <mmu.h>
#endif

/**
 * 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_hw_switch_frame_t frame;

    /* We use a strict alignment requirement for Q extension */
    sp = (rt_ubase_t *)RT_ALIGN_DOWN((rt_ubase_t)stack_addr, 16);

    *(--sp) = (rt_ubase_t)tentry;
    *(--sp) = (rt_ubase_t)parameter;
    *(--sp) = (rt_ubase_t)texit;
    /* Alignment */
    --sp;

    frame = (rt_hw_switch_frame_t)((rt_ubase_t)sp - sizeof(*frame));
    rt_memset(frame, 0, sizeof(*frame));

    frame->regs[RT_HW_SWITCH_CONTEXT_RA] = (rt_ubase_t)_thread_start;
    frame->regs[RT_HW_SWITCH_CONTEXT_XSTATUS] = K_XSTATUS_DEFAULT;
    /* Bare SMP keeps the current hart's tp across context switches. */

    return (void *)frame;
}