1 /*
2  * Copyright (c) 2006-2022, RT-Thread Development Team
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  *
6  * Change Logs:
7  * Date           Author       Notes
8  * 2011-02-23     Bernard      the first version
9  * 2012-03-03     xuzhenglim   modify for rx62N
10  */
11 
12 #include <rthw.h>
13 #include <rtthread.h>
14 
15 #include "cpuconfig.h"
16 
17 #include "machine.h"
18 #include "iorx62n.h"
19 
20 #define ENTER_INTERRUPT()  ICU.SWINTR.BIT.SWINT = 1;
21 
22 extern volatile rt_atomic_t rt_interrupt_nest;
23 
24 
25 /* switch flag on interrupt and thread pointer to save switch record */
26 rt_uint32_t rt_interrupt_from_thread;
27 rt_uint32_t rt_interrupt_to_thread;
28 rt_uint32_t rt_thread_switch_interrupt_flag;
29 
30 
31 /* stack frame*/
32 struct stack_frame
33 {
34     rt_uint32_t ACCLO;
35     rt_uint32_t ACCHI;
36     rt_uint32_t FPSW;
37     rt_uint32_t R1;
38     rt_uint32_t R2;
39     rt_uint32_t R3;
40     rt_uint32_t R4;
41     rt_uint32_t R5;
42     rt_uint32_t R6;
43     rt_uint32_t R7;
44     rt_uint32_t R8;
45     rt_uint32_t R9;
46     rt_uint32_t R10;
47     rt_uint32_t R11;
48     rt_uint32_t R12;
49     rt_uint32_t R13;
50     rt_uint32_t R14;
51     rt_uint32_t R15;
52     //there is not R0 register,it is special for stack pointer
53     rt_uint32_t PC;
54     rt_uint32_t PSW;
55 };
56 
57 /**
58  * Initilial the thread stack.
59  *
60  * @author LXZ (2014/11/8)
61  *
62  * @param void* tentry
63  * @param void* parameter
64  * @param rt_uint8_t* stack_addr
65  * @param void* texit
66  *
67  * @return rt_uint8_t*
68  */
rt_hw_stack_init(void * tentry,void * parameter,rt_uint8_t * stack_addr,void * texit)69 rt_uint8_t *rt_hw_stack_init(void *tentry, void *parameter,
70                              rt_uint8_t *stack_addr, void *texit)
71 {
72     unsigned long *stk;
73     struct stack_frame *stack_frame;
74     unsigned long       i;
75 
76     stk      = (unsigned long *)stack_addr;
77     *(stk)   = (unsigned long)texit;
78     stack_frame = (struct stack_frame *)(stack_addr - sizeof(struct stack_frame)) ;
79 
80     //Initilial all register
81     for (i = 0; i < sizeof(struct stack_frame) / sizeof(rt_uint32_t); i ++)
82     {
83         ((rt_uint32_t *)stack_frame)[i] = 0xdeadbeef;
84     }
85 
86     stack_frame->PSW = (unsigned long)0x00030000 ;   /* psw */
87     stack_frame->PC = (unsigned long)tentry;        /* thread entery*/
88     stack_frame->R1 = (unsigned long )parameter;   /* r1 : parameter */
89     stack_frame->FPSW = 0x00000100;                  /* fpsw */
90 
91     return(rt_uint8_t *)stack_frame;
92 }
93 
94 #if defined(RT_USING_FINSH) && defined(MSH_USING_BUILT_IN_COMMANDS)
95 extern void list_thread(void);
96 #endif
97 extern rt_thread_t rt_current_thread;
98 /**
99  * deal exception
100  *
101  * @author LXZ (2014/11/8)
102  *
103  * @param struct stack_frame* exception_contex
104  */
rt_hw_hard_fault_exception(struct stack_frame * exception_contex)105 void rt_hw_hard_fault_exception(struct stack_frame* exception_contex)
106 {
107     if (exception_contex != RT_NULL) {
108         rt_kprintf("psw: 0x%08x\n", exception_contex->PSW);
109         rt_kprintf("pc: 0x%08x\n", exception_contex->PC);
110         rt_kprintf("r0: 0x%08x\n", exception_contex->R1);
111         rt_kprintf("r0: 0x%08x\n", exception_contex->R2);
112         rt_kprintf("r0: 0x%08x\n", exception_contex->R3);
113         rt_kprintf("r0: 0x%08x\n", exception_contex->R4);
114         rt_kprintf("r0: 0x%08x\n", exception_contex->R5);
115         rt_kprintf("r0: 0x%08x\n", exception_contex->R6);
116         rt_kprintf("r0: 0x%08x\n", exception_contex->R7);
117         rt_kprintf("r0: 0x%08x\n", exception_contex->R8);
118         rt_kprintf("r0: 0x%08x\n", exception_contex->R9);
119         rt_kprintf("r0: 0x%08x\n", exception_contex->R10);
120         rt_kprintf("r0: 0x%08x\n", exception_contex->R11);
121         rt_kprintf("r0: 0x%08x\n", exception_contex->R12);
122         rt_kprintf("r0: 0x%08x\n", exception_contex->R13);
123         rt_kprintf("r0: 0x%08x\n", exception_contex->R14);
124         rt_kprintf("r0: 0x%08x\n", exception_contex->R15);
125         rt_kprintf("fpsw: 0x%08x\n", exception_contex->FPSW);
126         rt_kprintf("acchi: 0x%08x\n", exception_contex->ACCHI);
127         rt_kprintf("acclo: 0x%08x\n", exception_contex->ACCLO);
128     }
129         rt_kprintf("hard fault on thread: %s\n", rt_current_thread->parent.name);
130     #if defined(RT_USING_FINSH) && defined(MSH_USING_BUILT_IN_COMMANDS)
131         list_thread();
132     #endif
133         while (1);
134 
135 }
136 
137 
138 /**
139  * switch thread in interrupt
140  *
141  * @author LXZ (2014/11/8)
142  *
143  * @param rt_uint32_t from
144  * @param rt_uint32_t to
145  */
rt_hw_context_switch(rt_uint32_t from,rt_uint32_t to)146 void rt_hw_context_switch(rt_uint32_t from, rt_uint32_t to)
147 {
148     if (rt_thread_switch_interrupt_flag == 0)
149     {
150         rt_thread_switch_interrupt_flag = 1;
151         rt_interrupt_from_thread = from;
152     }
153 
154     rt_interrupt_to_thread = to;
155     ENTER_INTERRUPT();
156 }
157 /**
158  * switch thread out the interrupt
159  *
160  * @author LXZ (2014/11/8)
161  *
162  * @param rt_uint32_t from
163  * @param rt_uint32_t to
164  */
rt_hw_context_switch_interrupt(rt_uint32_t from,rt_uint32_t to)165 void rt_hw_context_switch_interrupt(rt_uint32_t from, rt_uint32_t to)
166 {
167     if (rt_thread_switch_interrupt_flag == 0)
168     {
169         rt_thread_switch_interrupt_flag = 1;
170         rt_interrupt_from_thread = from;
171     }
172 
173     rt_interrupt_to_thread = to;
174     ENTER_INTERRUPT();
175 }
176 
177 /**
178  * switch to the first thread,it just call one time
179  *
180  * @author LXZ (2014/11/8)
181  *
182  * @param rt_uint32_t to
183  */
rt_hw_context_switch_to(rt_uint32_t to)184 void rt_hw_context_switch_to(rt_uint32_t to)
185 {
186 
187     rt_interrupt_from_thread = 0;
188     rt_interrupt_to_thread = to;
189     rt_thread_switch_interrupt_flag = 1;
190     /* enable interrupt*/
191     _IEN( _ICU_SWINT ) = 1;
192 
193     /*clear the interrupt flag*/
194     _IR( _ICU_SWINT ) = 0;
195     _IPR( _ICU_SWINT ) = MAX_SYSCALL_INTERRUPT_PRIORITY + 1;
196 
197     /*touch the software interrupt*/
198     ENTER_INTERRUPT();
199     /*wait for first thread start up*/
200     while(1);
201 }
202 
203