1 /*
2 * Copyright (c) 2009-2022 Huawei Technologies Co., Ltd. All rights reserved.
3 *
4 * UniProton is licensed under Mulan PSL v2.
5 * You can use this software according to the terms and conditions of the Mulan PSL v2.
6 * You may obtain a copy of Mulan PSL v2 at:
7 * http://license.coscl.org.cn/MulanPSL2
8 * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
9 * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
10 * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
11 * See the Mulan PSL v2 for more details.
12 * Create: 2009-12-22
13 * Description: Hardware interrupt implementation
14 */
15 #include "prt_hook_external.h"
16 #include "prt_lib_external.h"
17 #include "prt_task_external.h"
18 #include "prt_hwi_internal.h"
19
20 #if defined(OS_OPTION_HWI_MAX_NUM_CONFIG)
21 OS_SEC_BSS U32 g_hwiMaxNumConfig;
22 #endif
23 OS_SEC_BSS OsVoidFunc g_excTrap;
24 /*
25 * 重定位以后的向量表,
26 * 其最后一个四字节表示当前运行的中断号,初始化系统定义异常向量,以便初始化阶段异常接管
27 */
28 VEC_SEC_DATA HwiPubintFunc g_hwiTable[OS_MX_VECTOR_CNT + 1] = {
29 (HwiPubintFunc)MSTACK_VECTOR,
30 (HwiPubintFunc)OsResetVector,
31 };
32
OsScheduleInit(void)33 OS_SEC_L4_TEXT void OsScheduleInit(void)
34 {
35 OS_SET_VECTOR(OS_EXC_PEND_SV, OsPendSv);
36 OS_SET_VECTOR(OS_EXC_SVC_CALL, OsSvchandler);
37
38 NVIC_SET_EXC_PRI(OS_EXC_PEND_SV, OS_HWI_PRI_LOWEST);
39 NVIC_SET_EXC_PRI(OS_EXC_SVC_CALL, OS_HWI_PRI_HIGHEST);
40 }
41
OsHwiGICInit(void)42 OS_SEC_L4_TEXT void OsHwiGICInit(void)
43 {
44 U32 loop;
45 /* 系统中断向量表初始化 */
46 for (loop = 0; loop < OS_MX_SYS_VECTOR_CNT; loop++) {
47 g_hwiTable[loop] = (HwiPubintFunc)OsHwiDefaultHandler;
48 }
49 OS_SET_VECTOR(0, (HwiPubintFunc)MSTACK_VECTOR);
50 OS_SET_VECTOR(OS_EXC_RESET, OsResetVector);
51 OS_SET_VECTOR(OS_EXC_NMI, OsExcNmi);
52 OS_SET_VECTOR(OS_EXC_HARD_FAULT, OsExcHardFault);
53 OS_SET_VECTOR(OS_EXC_MPU_FAULT, OsExcMemFault);
54 OS_SET_VECTOR(OS_EXC_BUS_FAULT, OsExcBusFault);
55 OS_SET_VECTOR(OS_EXC_USAGE_FAULT, OsExcUsageFault);
56 g_excTrap = (OsVoidFunc)OsExcSvcCall;
57 OsScheduleInit();
58 OS_SET_VECTOR(OS_EXC_SYS_TICK, OsTickIsr);
59 // 将Tick的优先级置为最低
60 NVIC_SET_EXC_PRI(OS_EXC_SYS_TICK, OS_HWI_PRI_LOWEST);
61
62 /* 用户中断向量表初始化 */
63 for (loop = OS_MX_SYS_VECTOR_CNT; loop < OS_MX_VECTOR_CNT; loop++) {
64 g_hwiTable[loop] = OsInterrupt;
65 }
66
67 /* 中断向量表定位 */
68 *(volatile U32 *)OS_NVIC_VTOR = (U32)(uintptr_t)g_hwiTable;
69 /*
70 * 访问钥匙:任何对该寄存器的写操作都必须同时把0x05FA写入此段,否则写操作被忽略
71 * 位段10:8为优先级分组
72 */
73 *(volatile U32 *)OS_NVIC_AIRCR = (OS_NVIC_AIRCR_REG_ACCESS_PSW |
74 (OS_NVIC_AIRCR_PRIGROUP << OS_NVIC_AIRCR_PRIGOUP_BIT_OFFSET));
75 }
76
77 /*
78 * 描述:默认外部中断处理函数
79 */
OsInterrupt(void)80 OS_SEC_TEXT void OsInterrupt(void)
81 {
82 HwiHandle hwiNum;
83 uintptr_t intSave;
84
85 /* 操作basepri 设置成关中断 */
86 intSave = PRT_HwiLock();
87 UNI_FLAG |= OS_FLG_HWI_ACTIVE;
88 g_intCount++;
89
90 /* 取外部中断号,中断号减去系统中断号 */
91 hwiNum = OsIntNumGet() - OS_MX_SYS_VECTOR_CNT;
92 #ifdef OS_OPTION_HWI_MAX_NUM_CONFIG
93 if (hwiNum > g_hwiMaxNumConfig) {
94 PRT_HwiRestore(intSave);
95 return;
96 }
97 #endif
98 OsTskHighestSet();
99
100 (void)PRT_HwiUnLock();
101 // ISR执行(这里一处开中断)
102 OsHwiHookDispatcher(hwiNum);
103
104 (void)PRT_HwiLock();
105
106 g_intCount--;
107
108 if (g_intCount == 0) {
109 UNI_FLAG &= ~OS_FLG_HWI_ACTIVE;
110 }
111
112 /* 恢复 basepri */
113 PRT_HwiRestore(intSave);
114
115 if ((UNI_FLAG & OS_FLG_TSK_REQ) != 0) {
116 OsHwiTrap();
117 }
118 }
119
120 /*
121 * 描述:硬中断模式设置
122 */
OsHwiPrioritySet(HwiHandle hwiNum,HwiPrior hwiPrio)123 OS_SEC_L4_TEXT void OsHwiPrioritySet(HwiHandle hwiNum, HwiPrior hwiPrio)
124 {
125 /* 设置优先级,当前芯片高4位有效,左移4位 */
126 NVIC_SET_IRQ_PRI(hwiNum, OS_HWI_GET_HWI_PRIO(hwiPrio));
127 }
128
OsHwiPriorityGet(HwiHandle hwiNum)129 OS_SEC_L4_TEXT U32 OsHwiPriorityGet(HwiHandle hwiNum)
130 {
131 return (U32)OS_HWI_GET_USER_PRIO((*((volatile U8 *)((uintptr_t)OS_NVIC_PRI_BASE + (hwiNum)))));
132 }
133
134 /*
135 * 描述:使能指定中断号
136 */
PRT_HwiEnable(HwiHandle hwiNum)137 OS_SEC_L2_TEXT U32 PRT_HwiEnable(HwiHandle hwiNum)
138 {
139 uintptr_t intSave;
140
141 if (hwiNum > OS_HWI_MAX) {
142 return OS_ERRNO_HWI_NUM_INVALID;
143 }
144
145 intSave = PRT_HwiLock();
146
147 NVIC_SET_IRQ(hwiNum);
148 PRT_HwiRestore(intSave);
149
150 return OS_OK;
151 }
152
153 /*
154 * 描述:清除所有的中断请求位
155 */
PRT_HwiClearAllPending(void)156 OS_SEC_L2_TEXT void PRT_HwiClearAllPending(void)
157 {
158 uintptr_t intSave;
159 U32 loop;
160
161 intSave = PRT_HwiLock();
162
163 for (loop = 0; loop < OS_HWI_CLRPEND_REG_NUM; loop += sizeof(U32)) {
164 *(volatile U32 *)((uintptr_t)OS_NVIC_CLRPEND_BASE + loop) = OS_MAX_U32;
165 }
166 PRT_HwiRestore(intSave);
167 return;
168 }
169
170 /*
171 * 描述:清除单个硬中断的Pending位
172 */
PRT_HwiClearPendingBit(HwiHandle hwiNum)173 OS_SEC_L2_TEXT U32 PRT_HwiClearPendingBit(HwiHandle hwiNum)
174 {
175 uintptr_t intSave;
176 if (hwiNum > OS_HWI_MAX) {
177 return OS_ERRNO_HWI_NUM_INVALID;
178 }
179
180 intSave = PRT_HwiLock();
181 NVIC_CLR_IRQ_PEND(hwiNum);
182 PRT_HwiRestore(intSave);
183 return OS_OK;
184 }
185
186 /*
187 * 描述:触发指定硬中断号
188 */
PRT_HwiTrigger(U32 dstCore,HwiHandle hwiNum)189 OS_SEC_L2_TEXT U32 PRT_HwiTrigger(U32 dstCore, HwiHandle hwiNum)
190 {
191 uintptr_t intSave;
192
193 if (hwiNum > OS_HWI_MAX) {
194 return OS_ERRNO_HWI_NUM_INVALID;
195 }
196
197 if (OsGetHwThreadId() != dstCore) {
198 return OS_ERRNO_HWI_CORE_ID_INVALID;
199 }
200
201 intSave = PRT_HwiLock();
202
203 NVIC_SET_IRQ_PEND(hwiNum);
204
205 PRT_HwiRestore(intSave);
206
207 return OS_OK;
208 }
209
210 /*
211 * 描述:禁止指定中断号
212 */
PRT_HwiDisable(HwiHandle hwiNum)213 OS_SEC_L2_TEXT U32 PRT_HwiDisable(HwiHandle hwiNum)
214 {
215 uintptr_t intSave;
216
217 if (hwiNum > OS_HWI_MAX) {
218 return OS_ERRNO_HWI_NUM_INVALID;
219 }
220
221 intSave = PRT_HwiLock();
222
223 NVIC_CLR_IRQ(hwiNum);
224 PRT_HwiRestore(intSave);
225
226 return OS_OK;
227 }
228
PRT_HwiDelExitHook(HwiExitHook hook)229 OS_SEC_L4_TEXT U32 PRT_HwiDelExitHook(HwiExitHook hook)
230 {
231 return OsHookDel(OS_HOOK_HWI_EXIT, (OsVoidFunc)hook);
232 }
PRT_HwiAddExitHook(HwiExitHook hook)233 OS_SEC_L4_TEXT U32 PRT_HwiAddExitHook(HwiExitHook hook)
234 {
235 return OsHookAdd(OS_HOOK_HWI_EXIT, (OsVoidFunc)hook);
236 }
PRT_HwiDelEntryHook(HwiEntryHook hook)237 OS_SEC_L4_TEXT U32 PRT_HwiDelEntryHook(HwiEntryHook hook)
238 {
239 return OsHookDel(OS_HOOK_HWI_ENTRY, (OsVoidFunc)hook);
240 }
PRT_HwiAddEntryHook(HwiEntryHook hook)241 OS_SEC_L4_TEXT U32 PRT_HwiAddEntryHook(HwiEntryHook hook)
242 {
243 return OsHookAdd(OS_HOOK_HWI_ENTRY, (OsVoidFunc)hook);
244 }
245