forked from xuos/xiuos
				
			
		
			
				
	
	
		
			219 lines
		
	
	
		
			4.3 KiB
		
	
	
	
		
			C
		
	
	
	
			
		
		
	
	
			219 lines
		
	
	
		
			4.3 KiB
		
	
	
	
		
			C
		
	
	
	
| /*
 | |
| * Copyright (c) 2020 AIIT XUOS Lab
 | |
| * XiUOS is licensed under Mulan PSL v2.
 | |
| * You can use this software according to the terms and conditions of the Mulan PSL v2.
 | |
| * You may obtain a copy of Mulan PSL v2 at:
 | |
| *        http://license.coscl.org.cn/MulanPSL2
 | |
| * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
 | |
| * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
 | |
| * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
 | |
| * See the Mulan PSL v2 for more details.
 | |
| */
 | |
| 
 | |
| /**
 | |
| * @file:    isr.c
 | |
| * @brief:   the general management of system isr
 | |
| * @version: 1.0
 | |
| * @author:  AIIT XUOS Lab
 | |
| * @date:    2020/3/15
 | |
| *
 | |
| */
 | |
| 
 | |
| #include <xizi.h>
 | |
| #include <xs_hook.h>
 | |
| 
 | |
| struct InterruptServiceRoutines isrManager = { 0} ;
 | |
| 
 | |
| #ifdef ARCH_SMP
 | |
| extern int GetCpuId(void);
 | |
| #endif
 | |
| /**
 | |
|  * This functionwill get the isr nest level.
 | |
|  *
 | |
|  * @return isr nest level
 | |
|  */
 | |
|  uint16 GetIsrCounter()
 | |
| {
 | |
|     uint16 ret = 0;
 | |
| 
 | |
| #ifdef ARCH_SMP
 | |
|     ret = isrManager.isr_count[GetCpuId()];
 | |
| #else
 | |
|     ret = isrManager.isr_count;
 | |
| #endif
 | |
|     return ret;
 | |
| }
 | |
| 
 | |
|  void IncIsrCounter()
 | |
| {
 | |
| #ifdef ARCH_SMP
 | |
|      isrManager.isr_count[GetCpuId()] ++ ;
 | |
| #else
 | |
|      isrManager.isr_count ++;
 | |
| #endif
 | |
|     return ;
 | |
| }
 | |
| 
 | |
|  void DecIsrCounter()
 | |
| {
 | |
| 
 | |
| #ifdef ARCH_SMP
 | |
|      isrManager.isr_count[GetCpuId()] -- ;
 | |
| #else
 | |
|      isrManager.isr_count --;
 | |
| #endif
 | |
|     return ;
 | |
| }
 | |
| 
 | |
|  x_bool IsInIsr()
 | |
| {
 | |
| #ifdef ARCH_SMP
 | |
|     return ( isrManager.isr_count[GetCpuId()] != 0 ? RET_TRUE : RET_FALSE ) ;
 | |
| #else
 | |
|     return ( isrManager.isr_count != 0 ? RET_TRUE : RET_FALSE ) ;
 | |
| #endif
 | |
| 
 | |
| }
 | |
| /**
 | |
|  * This function will register a new irq.
 | |
|  *
 | |
|  * @param irq_num the number of the irq
 | |
|  * @param handler the callback of the interrupt
 | |
|  * @param arg param of thge callback
 | |
|  *
 | |
|  * @return EOK on success; ERROR on failure
 | |
|  */
 | |
| int32 RegisterHwIrq(uint32 irq_num, IsrHandlerType handler, void *arg)
 | |
| {
 | |
|     if (irq_num >=   ARCH_MAX_IRQ_NUM )
 | |
|         return -ERROR;
 | |
| 
 | |
|     struct IrqDesc *desc = &isrManager.irq_table[irq_num];
 | |
| 
 | |
|     desc->handler = handler;
 | |
|     desc->param = arg;
 | |
| 
 | |
|     return EOK;
 | |
| }
 | |
| /**
 | |
|  * This function will free a irq.
 | |
|  *
 | |
|  * @param irq_num the number of the irq
 | |
|  *
 | |
|  * @return EOK on success; ERROR on failure
 | |
|  */
 | |
| int32 FreeHwIrq(uint32 irq_num)
 | |
| {
 | |
|     if (irq_num >=   ARCH_MAX_IRQ_NUM  )
 | |
|         return -ERROR;
 | |
| 
 | |
|     memset(&isrManager.irq_table[irq_num], 0, sizeof(struct IrqDesc));
 | |
| 
 | |
|     return EOK;
 | |
| }
 | |
| 
 | |
| /**
 | |
|  * This function will enable a irq.
 | |
|  *
 | |
|  * @param irq_num the number of the irq
 | |
|  *
 | |
|  * @return EOK on success; ERROR on failure
 | |
|  */
 | |
| int32 EnableHwIrq(uint32 irq_num)
 | |
| {
 | |
|     if (irq_num >=   ARCH_MAX_IRQ_NUM  )
 | |
|         return -ERROR;
 | |
| 
 | |
|     return ArchEnableHwIrq(irq_num);
 | |
| }
 | |
| /**
 | |
|  * This function will disable a irq.
 | |
|  *
 | |
|  * @param irq_num the number of the irq
 | |
|  *
 | |
|  * @return EOK on success; ERROR on failure
 | |
|  */
 | |
| 
 | |
| int32 DisableHwIrq(uint32 irq_num)
 | |
| {
 | |
|     if (irq_num >=   ARCH_MAX_IRQ_NUM  )
 | |
|         return -ERROR;
 | |
| 
 | |
|     return ArchDisableHwIrq(irq_num);
 | |
| }
 | |
| 
 | |
| /* called from arch-specific ISR wrapper */
 | |
| void IsrCommon(uint32 irq_num)
 | |
| {
 | |
|     struct IrqDesc *desc = &isrManager.irq_table[irq_num];
 | |
| 
 | |
|     if (desc->handler == NONE) {
 | |
|         SYS_KDEBUG_LOG(KDBG_IRQ, ("Spurious interrupt: IRQ No. %d\n", irq_num));
 | |
|         while (1) {}
 | |
|     }
 | |
|     desc->handler(irq_num, desc->param);
 | |
| 
 | |
| }
 | |
| 
 | |
|  void SetIsrSwitchTrigerFlag()
 | |
|  {
 | |
| 
 | |
| #ifdef ARCH_SMP
 | |
|     isrManager.isr_switch_trigger_flag[GetCpuId()] = 1;
 | |
| #else
 | |
|     isrManager.isr_switch_trigger_flag = 1;
 | |
| #endif
 | |
| 
 | |
| }
 | |
| 
 | |
|  void ClearIsrSwitchTrigerFlag()
 | |
|  {
 | |
| 
 | |
| #ifdef ARCH_SMP
 | |
|     isrManager.isr_switch_trigger_flag[GetCpuId()] = 0;
 | |
| #else
 | |
|     isrManager.isr_switch_trigger_flag = 0;
 | |
| #endif
 | |
| }
 | |
| 
 | |
|  uint8 GetIsrSwitchTrigerFlag()
 | |
|  {
 | |
|    
 | |
| #ifdef ARCH_SMP
 | |
|    return  isrManager.isr_switch_trigger_flag[GetCpuId()];
 | |
| #else
 | |
|    return isrManager.isr_switch_trigger_flag ;
 | |
| #endif
 | |
| 
 | |
| }
 | |
| 
 | |
| struct IsrDone isrDone = {
 | |
|     IsInIsr,
 | |
|     RegisterHwIrq ,
 | |
|     FreeHwIrq,
 | |
|     EnableHwIrq,
 | |
|     DisableHwIrq,
 | |
|     IsrCommon,
 | |
|     GetIsrCounter,
 | |
|     IncIsrCounter,
 | |
|     DecIsrCounter,
 | |
|     GetIsrSwitchTrigerFlag,
 | |
|     SetIsrSwitchTrigerFlag,
 | |
|     ClearIsrSwitchTrigerFlag
 | |
| } ;
 | |
| 
 | |
| void SysInitIsrManager()
 | |
| {
 | |
|     extern int __isrtbl_idx_start;
 | |
|     extern int __isrtbl_start;
 | |
|     extern int __isrtbl_end;
 | |
|     memset(&isrManager,0,sizeof(struct InterruptServiceRoutines));
 | |
|     isrManager.done = &isrDone;
 | |
| 
 | |
|     uint32 *index = (uint32 *)&__isrtbl_idx_start;
 | |
|     struct IrqDesc *desc = (struct IrqDesc *)&__isrtbl_start;
 | |
| 
 | |
|     while (desc != (struct IrqDesc *)&__isrtbl_end)
 | |
|         isrManager.irq_table[*index++] = *desc++;
 | |
| }
 |