xref: /nrf52832-nimble/rt-thread/libcpu/risc-v/common/cpuport.c (revision 104654410c56c573564690304ae786df310c91fc)
1*10465441SEvalZero /*
2*10465441SEvalZero  * Copyright (c) 2006-2018, RT-Thread Development Team
3*10465441SEvalZero  *
4*10465441SEvalZero  * SPDX-License-Identifier: Apache-2.0
5*10465441SEvalZero  *
6*10465441SEvalZero  * Change Logs:
7*10465441SEvalZero  * Date           Author       Notes
8*10465441SEvalZero  * 2018/10/28     Bernard      The unify RISC-V porting code.
9*10465441SEvalZero  */
10*10465441SEvalZero 
11*10465441SEvalZero #include <rthw.h>
12*10465441SEvalZero #include <rtthread.h>
13*10465441SEvalZero 
14*10465441SEvalZero #include "cpuport.h"
15*10465441SEvalZero 
16*10465441SEvalZero #ifndef RT_USING_SMP
17*10465441SEvalZero volatile rt_ubase_t  rt_interrupt_from_thread = 0;
18*10465441SEvalZero volatile rt_ubase_t  rt_interrupt_to_thread   = 0;
19*10465441SEvalZero volatile rt_uint32_t rt_thread_switch_interrupt_flag = 0;
20*10465441SEvalZero #endif
21*10465441SEvalZero 
22*10465441SEvalZero struct rt_hw_stack_frame
23*10465441SEvalZero {
24*10465441SEvalZero     rt_ubase_t epc;        /* epc - epc    - program counter                     */
25*10465441SEvalZero     rt_ubase_t ra;         /* x1  - ra     - return address for jumps            */
26*10465441SEvalZero     rt_ubase_t mstatus;    /*              - machine status register             */
27*10465441SEvalZero     rt_ubase_t gp;         /* x3  - gp     - global pointer                      */
28*10465441SEvalZero     rt_ubase_t tp;         /* x4  - tp     - thread pointer                      */
29*10465441SEvalZero     rt_ubase_t t0;         /* x5  - t0     - temporary register 0                */
30*10465441SEvalZero     rt_ubase_t t1;         /* x6  - t1     - temporary register 1                */
31*10465441SEvalZero     rt_ubase_t t2;         /* x7  - t2     - temporary register 2                */
32*10465441SEvalZero     rt_ubase_t s0_fp;      /* x8  - s0/fp  - saved register 0 or frame pointer   */
33*10465441SEvalZero     rt_ubase_t s1;         /* x9  - s1     - saved register 1                    */
34*10465441SEvalZero     rt_ubase_t a0;         /* x10 - a0     - return value or function argument 0 */
35*10465441SEvalZero     rt_ubase_t a1;         /* x11 - a1     - return value or function argument 1 */
36*10465441SEvalZero     rt_ubase_t a2;         /* x12 - a2     - function argument 2                 */
37*10465441SEvalZero     rt_ubase_t a3;         /* x13 - a3     - function argument 3                 */
38*10465441SEvalZero     rt_ubase_t a4;         /* x14 - a4     - function argument 4                 */
39*10465441SEvalZero     rt_ubase_t a5;         /* x15 - a5     - function argument 5                 */
40*10465441SEvalZero     rt_ubase_t a6;         /* x16 - a6     - function argument 6                 */
41*10465441SEvalZero     rt_ubase_t a7;         /* x17 - s7     - function argument 7                 */
42*10465441SEvalZero     rt_ubase_t s2;         /* x18 - s2     - saved register 2                    */
43*10465441SEvalZero     rt_ubase_t s3;         /* x19 - s3     - saved register 3                    */
44*10465441SEvalZero     rt_ubase_t s4;         /* x20 - s4     - saved register 4                    */
45*10465441SEvalZero     rt_ubase_t s5;         /* x21 - s5     - saved register 5                    */
46*10465441SEvalZero     rt_ubase_t s6;         /* x22 - s6     - saved register 6                    */
47*10465441SEvalZero     rt_ubase_t s7;         /* x23 - s7     - saved register 7                    */
48*10465441SEvalZero     rt_ubase_t s8;         /* x24 - s8     - saved register 8                    */
49*10465441SEvalZero     rt_ubase_t s9;         /* x25 - s9     - saved register 9                    */
50*10465441SEvalZero     rt_ubase_t s10;        /* x26 - s10    - saved register 10                   */
51*10465441SEvalZero     rt_ubase_t s11;        /* x27 - s11    - saved register 11                   */
52*10465441SEvalZero     rt_ubase_t t3;         /* x28 - t3     - temporary register 3                */
53*10465441SEvalZero     rt_ubase_t t4;         /* x29 - t4     - temporary register 4                */
54*10465441SEvalZero     rt_ubase_t t5;         /* x30 - t5     - temporary register 5                */
55*10465441SEvalZero     rt_ubase_t t6;         /* x31 - t6     - temporary register 6                */
56*10465441SEvalZero };
57*10465441SEvalZero 
58*10465441SEvalZero /**
59*10465441SEvalZero  * This function will initialize thread stack
60*10465441SEvalZero  *
61*10465441SEvalZero  * @param tentry the entry of thread
62*10465441SEvalZero  * @param parameter the parameter of entry
63*10465441SEvalZero  * @param stack_addr the beginning stack address
64*10465441SEvalZero  * @param texit the function will be called when thread exit
65*10465441SEvalZero  *
66*10465441SEvalZero  * @return stack address
67*10465441SEvalZero  */
rt_hw_stack_init(void * tentry,void * parameter,rt_uint8_t * stack_addr,void * texit)68*10465441SEvalZero rt_uint8_t *rt_hw_stack_init(void       *tentry,
69*10465441SEvalZero                              void       *parameter,
70*10465441SEvalZero                              rt_uint8_t *stack_addr,
71*10465441SEvalZero                              void       *texit)
72*10465441SEvalZero {
73*10465441SEvalZero     struct rt_hw_stack_frame *frame;
74*10465441SEvalZero     rt_uint8_t         *stk;
75*10465441SEvalZero     int                i;
76*10465441SEvalZero 
77*10465441SEvalZero     stk  = stack_addr + sizeof(rt_ubase_t);
78*10465441SEvalZero     stk  = (rt_uint8_t *)RT_ALIGN_DOWN((rt_ubase_t)stk, REGBYTES);
79*10465441SEvalZero     stk -= sizeof(struct rt_hw_stack_frame);
80*10465441SEvalZero 
81*10465441SEvalZero     frame = (struct rt_hw_stack_frame *)stk;
82*10465441SEvalZero 
83*10465441SEvalZero     for (i = 0; i < sizeof(struct rt_hw_stack_frame) / sizeof(rt_ubase_t); i++)
84*10465441SEvalZero     {
85*10465441SEvalZero         ((rt_ubase_t *)frame)[i] = 0xdeadbeef;
86*10465441SEvalZero     }
87*10465441SEvalZero 
88*10465441SEvalZero     frame->ra      = (rt_ubase_t)texit;
89*10465441SEvalZero     frame->a0      = (rt_ubase_t)parameter;
90*10465441SEvalZero     frame->epc     = (rt_ubase_t)tentry;
91*10465441SEvalZero 
92*10465441SEvalZero     /* force to machine mode(MPP=11) and set MPIE to 1 */
93*10465441SEvalZero     frame->mstatus = 0x00007880;
94*10465441SEvalZero 
95*10465441SEvalZero     return stk;
96*10465441SEvalZero }
97*10465441SEvalZero 
98*10465441SEvalZero /*
99*10465441SEvalZero  * #ifdef RT_USING_SMP
100*10465441SEvalZero  * void rt_hw_context_switch_interrupt(void *context, rt_ubase_t from, rt_ubase_t to, struct rt_thread *to_thread);
101*10465441SEvalZero  * #else
102*10465441SEvalZero  * void rt_hw_context_switch_interrupt(rt_ubase_t from, rt_ubase_t to);
103*10465441SEvalZero  * #endif
104*10465441SEvalZero  */
105*10465441SEvalZero #ifndef RT_USING_SMP
rt_hw_context_switch_interrupt(rt_ubase_t from,rt_ubase_t to)106*10465441SEvalZero void rt_hw_context_switch_interrupt(rt_ubase_t from, rt_ubase_t to)
107*10465441SEvalZero {
108*10465441SEvalZero     if (rt_thread_switch_interrupt_flag == 0)
109*10465441SEvalZero         rt_interrupt_from_thread = from;
110*10465441SEvalZero 
111*10465441SEvalZero     rt_interrupt_to_thread = to;
112*10465441SEvalZero     rt_thread_switch_interrupt_flag = 1;
113*10465441SEvalZero 
114*10465441SEvalZero     return ;
115*10465441SEvalZero }
116*10465441SEvalZero #endif /* end of RT_USING_SMP */
117*10465441SEvalZero 
118*10465441SEvalZero /** shutdown CPU */
rt_hw_cpu_shutdown()119*10465441SEvalZero void rt_hw_cpu_shutdown()
120*10465441SEvalZero {
121*10465441SEvalZero     rt_uint32_t level;
122*10465441SEvalZero     rt_kprintf("shutdown...\n");
123*10465441SEvalZero 
124*10465441SEvalZero     level = rt_hw_interrupt_disable();
125*10465441SEvalZero     while (level)
126*10465441SEvalZero     {
127*10465441SEvalZero         RT_ASSERT(0);
128*10465441SEvalZero     }
129*10465441SEvalZero }
130