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