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)
21OS_SEC_BSS U32 g_hwiMaxNumConfig;
22#endif
23OS_SEC_BSS OsVoidFunc g_excTrap;
24/*
25 * 重定位以后的向量表,
26 * 其最后一个四字节表示当前运行的中断号,初始化系统定义异常向量,以便初始化阶段异常接管
27 */
28VEC_SEC_DATA HwiPubintFunc g_hwiTable[OS_MX_VECTOR_CNT + 1] = {
29    (HwiPubintFunc)MSTACK_VECTOR,
30    (HwiPubintFunc)OsResetVector,
31};
32
33OS_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
42OS_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 */
80OS_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 */
123OS_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
129OS_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 */
137OS_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 */
156OS_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 */
173OS_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 */
189OS_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 */
213OS_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
229OS_SEC_L4_TEXT U32 PRT_HwiDelExitHook(HwiExitHook hook)
230{
231    return OsHookDel(OS_HOOK_HWI_EXIT, (OsVoidFunc)hook);
232}
233OS_SEC_L4_TEXT U32 PRT_HwiAddExitHook(HwiExitHook hook)
234{
235    return OsHookAdd(OS_HOOK_HWI_EXIT, (OsVoidFunc)hook);
236}
237OS_SEC_L4_TEXT U32 PRT_HwiDelEntryHook(HwiEntryHook hook)
238{
239    return OsHookDel(OS_HOOK_HWI_ENTRY, (OsVoidFunc)hook);
240}
241OS_SEC_L4_TEXT U32 PRT_HwiAddEntryHook(HwiEntryHook hook)
242{
243    return OsHookAdd(OS_HOOK_HWI_ENTRY, (OsVoidFunc)hook);
244}
245