[嵌入式系统-37]:龙芯1B 开发学习套件 -6-协处理器CP0之CPU异常处理与外部中断控制器的中断处理

目录

一、MPIS CPU Core与32个异常exception

1.1 龙芯1B的MIPS CPU IP Core

1.2 MIP32指令系统

1.3 MIPS CPU寄存器

1.4 MIPS CPU的异常向量与异常向量号

1.5 龙芯异常exception与中断interrupt的区别

二、协议处理器CP0的中断控制与8个中断

2.1 CP0概述

2.2 协处理器支持的32个寄存器

2.3 CPU协处理器CP0支持的中断

2.4 协处理器CP0的中断服务程序

三、4个外部中断控制器与128个外部中断

3.1 外部中断源与4个中断控制器:INT0、INT1、INT2、INT3

3.2 如何配置外部中断源

3.3 四个中断控制器控制的所有外部中断的中断向量表

3.2.1 软件中断向量表结构定义:ls1b_irq.c

3.2.2 软件中断向量表定义:ls1b_irq.c和ls1b_irq.h

3.3.3 默认的中断处理或中断服务程序:ls1b_irq.c

3.3.4 中断向量表的初始化

3.3.5 安装用户自定义的中断服务程序的安装与移除

3.4 4个中断控制器的中断相关的寄存器

3.4.1 中断相关的寄存器列表(每个中断控制器有一套寄存器)

3.4.2 32bit 中断寄存器含义

3.4.3 32bits如何与中断源对应起来

3.4.5 如何根据中断原因寄存器挨个、逐一分发中断服务程序

2.4.6 四个中断控制器对应的中断服务程序

2.4.7 CPU协处理器是如何调用4个中断控制器对应的中断服务器程序


一、MPIS CPU Core与32个异常exception

1.1 龙芯1B的MIPS CPU IP Core

1.2 MIP32指令系统

1.3 MIPS CPU寄存器

1.4 MIPS CPU的异常向量与异常向量号

/*
 * Define the name of the CPU family.
 */
#define CPU_NAME "MIPS"

/*
 * MIPS Vector numbers for exception conditions. This is a direct map to the causes.
 */
#define MIPS_EXCEPTION_BASE             0

#define MIPS_EXCEPTION_INT              MIPS_EXCEPTION_BASE+0
#define MIPS_EXCEPTION_MOD              MIPS_EXCEPTION_BASE+1
#define MIPS_EXCEPTION_TLBL             MIPS_EXCEPTION_BASE+2
#define MIPS_EXCEPTION_TLBS             MIPS_EXCEPTION_BASE+3
#define MIPS_EXCEPTION_ADEL             MIPS_EXCEPTION_BASE+4
#define MIPS_EXCEPTION_ADES             MIPS_EXCEPTION_BASE+5
#define MIPS_EXCEPTION_IBE              MIPS_EXCEPTION_BASE+6
#define MIPS_EXCEPTION_DBE              MIPS_EXCEPTION_BASE+7
#define MIPS_EXCEPTION_SYSCALL          MIPS_EXCEPTION_BASE+8
#define MIPS_EXCEPTION_BREAK            MIPS_EXCEPTION_BASE+9
#define MIPS_EXCEPTION_RI               MIPS_EXCEPTION_BASE+10
#define MIPS_EXCEPTION_CPU              MIPS_EXCEPTION_BASE+11
#define MIPS_EXCEPTION_OVERFLOW         MIPS_EXCEPTION_BASE+12
#define MIPS_EXCEPTION_TRAP             MIPS_EXCEPTION_BASE+13
#define MIPS_EXCEPTION_VCEI             MIPS_EXCEPTION_BASE+14
/* FPE only on mips2 and higher */
#define MIPS_EXCEPTION_FPE              MIPS_EXCEPTION_BASE+15
#define MIPS_EXCEPTION_C2E              MIPS_EXCEPTION_BASE+16
/* 17-22 reserved */
#define MIPS_EXCEPTION_WATCH            MIPS_EXCEPTION_BASE+23
/* 24-30 reserved */
#define MIPS_EXCEPTION_VCED             MIPS_EXCEPTION_BASE+31

#define MIPS_INTERRUPT_BASE             MIPS_EXCEPTION_BASE+32  //协处理器中断服务程序入口

1.5 龙芯异常exception与中断interrupt的区别

龙芯处理器中的异常(exception)和中断(interrupt)在概念上是有区别的,它们分别代表了不同类型的事件和处理机制:

  1. 异常(Exception):异常是指在程序执行过程中出现的一种非正常事件,通常是由指令执行时产生的,可以看作是处理器内部的问题。异常可以是因为错误的操作码、内存访问冲突、算术错误等原因导致的,需要处理器暂停当前指令的执行并执行相应的异常处理程序。异常通常由处理器本身或者处理器内部逻辑主动触发,它跳转到异常处理程序,处理完异常后再恢复到正常指令流程。

  2. 中断(Interrupt):中断是指来自外部设备的一种请求要求处理器暂停当前正在执行的程序,转而执行与中断相关的处理程序。中断是处理器响应外部事件的一种方式,可以是来自设备的信号或者时钟,需要处理器打断当前执行的指令流程,执行相应的中断服务程序,处理完中断后再返回到被中断的程序继续执行。

        在龙芯处理器中,异常和中断的区别在于触发原因和处理方式上:异常通常是由指令执行过程中的内部错误或意外情况引发,需要处理器内部去处理;而中断是由外部事件触发,需要处理器响应外部设备的请求。处理器在接收到异常或中断信号后,会根据具体情况执行相应的处理程序,保证系统的稳定运行和正确性。

二、协议处理器CP0的中断控制与8个中断

2.1 CP0概述

龙芯1B协处理器CP0(Coprocessor 0)是龙芯处理器(Loongson)中的一个重要组成部分,主要用于管理处理器的系统级行为和状态信息。CP0是一个与主处理器CPU紧密集成的协处理器,它的功能主要有以下几个方面:

  1. 地址转换和虚拟存储管理MMU:CP0可以实现物理地址的解析和转换,支持虚拟存储管理,使得应用程序可以像访问物理内存一样方便地访问虚拟内存区域。

  2. 异常和中断处理(本文要深入讨论的部分):CP0是处理器内部异常exception和外部中断Interrupt处理的核心,它存储了异常和中断向量表、错误状态码等信息,并负责中断的响应和异常处理程序的执行

  3. 性能计数器和性能分析:CP0中还包括可编程的性能计数器和时钟戳记寄存器,可以用于对程序的性能分析和调优,并支持操作系统的性能监控功能。

  4. 系统控制寄存器:CP0中还包含了一些系统级别的控制寄存器,可以用于修改处理器的运行状态,如设置缓存策略、开/关写缓冲等。

总之,龙芯1B协处理器CP0是Loongson处理器的重要组成部分,它管理和控制处理器中的系统级行为和状态信息,为操作系统和应用程序提供了重要的支持和保障。

2.2 协处理器支持的32个寄存器

协处理器支持32个寄存器,其中部分寄存器用于中断控制!!!

2.3 CPU协处理器CP0支持的中断

/*
 * CP0 Cause ($12)  IP bit(15:8)=IP[7:0], IP[1:0] is soft-interrupt
 *     Status($13)  IM bit(15:8) if mask interrupts
 *
 */
#define LS1B_IRQ_SW0            (MIPS_INTERRUPT_BASE + 0)
#define LS1B_IRQ_SW1            (MIPS_INTERRUPT_BASE + 1)
#define LS1B_IRQ0_REQ           (MIPS_INTERRUPT_BASE + 2)
#define LS1B_IRQ1_REQ           (MIPS_INTERRUPT_BASE + 3)
#define LS1B_IRQ2_REQ           (MIPS_INTERRUPT_BASE + 4)
#define LS1B_IRQ3_REQ           (MIPS_INTERRUPT_BASE + 5)
#define LS1B_IRQ_PERF           (MIPS_INTERRUPT_BASE + 6)
#define LS1B_IRQ_CNT            (MIPS_INTERRUPT_BASE + 7)

2.4 协处理器CP0的中断服务程序

void c_interrupt_handler(void *p)
{
	unsigned int sr;
	unsigned int cause;

	mips_get_sr(sr);
	
	mips_get_cause(cause);  

	cause &= (sr & SR_IMASK);
	cause >>= CAUSE_IPSHIFT;

	/******************************************************************
	 * XXX use as bsp system tick generator.
	 */
	if (cause & 0x80)			/* count/compare interrupt */
	{
		bsp_irq_handler_dispatch(LS1x_IRQ_CNT);
	}

	if (cause & 0x04)			/* Interrupt controller 0 */
	{
		call_vectored_isr(p, cause, (void *)LS1x_INTC0_BASE);
	}

	if (cause & 0x08)			/* Interrupt controller 1 */
	{
		call_vectored_isr(p, cause, (void *)LS1x_INTC1_BASE);
	}

	if (cause & 0x10)			/* Interrupt controller 2 */
	{
		call_vectored_isr(p, cause, (void *)LS1x_INTC2_BASE);
	}

	if (cause & 0x20)			/* Interrupt controller 3 */
	{
		call_vectored_isr(p, cause, (void *)LS1x_INTC3_BASE);
	}

#if defined(LS1B)

	if (cause & 0x40)			/* Performance counter */
	{
		bsp_irq_handler_dispatch(LS1x_IRQ_PERF);
	}

#elif defined(LS1C)

	if (cause & 0x40)			/* Interrupt controller 4 */
	{
		call_vectored_isr(p, cause, (void *)LS1x_INTC4_BASE);
	}

#endif

	if (cause & 0x02)			/* Soft Interrupt SW[1] */
	{
		bsp_irq_handler_dispatch(LS1x_IRQ_SW1);
	}
	
	if (cause & 0x01)			/* Soft Interrupt SW[0] */
	{
		bsp_irq_handler_dispatch(LS1x_IRQ_SW0);
	}
	
	// mips_set_cause(0);
}

三、4个外部中断控制器与128个外部中断

3.1 外部中断源与4个中断控制器:INT0、INT1、INT2、INT3

龙芯1B SOC芯片内置了4个简单、灵活的中断控制器,即INT0、INT1、INT2、INT3,用于管理SOC芯片外设和GPIO的中断。每个中断控制器最大管辖32个中断。

1B芯片的中断控制器除了管理 GPIO输入的中断信号外,中断控制器还处理内部设备引起的中断。所有的中断寄存器的位域安排相同,一个中断源对应其中一位

SOC的中断控制器共四个中断线输出连接到CPU模块,分别对应 INT0, INT1, INT2, INT3

SOC芯片中断控制器本身能够支持 64个内部中断和 64个 GPIO的中断,最大一共128个硬件外部中断源,这128个中断源分为四组,每组最大支持32个中断源,分别归组为:INT0, INT1, INT2, INT3。

其中 INT0和 INT1分别对应于 64个内部中断的前后 32位,INT2和 INT3对应于 64个外部 GPIO中断。但龙芯1B的实现过程中,并非所有的中断源都被使用,部分中断源是保留未使用,

具体中断源如下表所示: 

从上图可以看出:

(1)GPIO31、GPIO62、GPIO63都未使用,属于保留位,因此一个64-3=61个GPIO中断源。

(2)并非所有的INT0和INT1的外设中断都被使用上,实际上,龙芯1B SOC芯片,并没有那么多外设,因此,大量的位都是闲置的,属于保留为,未定义其行为。

3.2 如何配置外部中断源

3.3 四个中断控制器控制的所有外部中断的中断向量表

3.2.1 软件中断向量表结构定义:ls1b_irq.c

/* 中断向量表 */
typedef struct isr_tbl
{
	void (*handler)(int, void *);       // 中断句柄
	unsigned int arg;                   // 参数 
} isr_tbl_t;

3.2.2 软件中断向量表定义:ls1b_irq.c和ls1b_irq.h

定义龙芯1B实际支持的中断源(去除保留位)


/******************************************************************************
 * Interrupt Vector Numbers
 * MIPS_INTERRUPT_BASE should be 32 (0x20)
 ******************************************************************************/

/*
 * CP0 Cause ($12)  IP bit(15:8)=IP[7:0],

*       IP[1:0] is soft-interrupt
 *     Status($13)  IM bit(15:8) if mask interrupts
 *
 */
#define LS1B_IRQ_SW0            (MIPS_INTERRUPT_BASE + 0)   # 协处理器的软中断
#define LS1B_IRQ_SW1            (MIPS_INTERRUPT_BASE + 1)   # 协处理器的软中断
#define LS1B_IRQ0_REQ           (MIPS_INTERRUPT_BASE + 2)  # 协处理器的中断请求0
#define LS1B_IRQ1_REQ           (MIPS_INTERRUPT_BASE + 3)   # 协处理器的中断请求1
#define LS1B_IRQ2_REQ           (MIPS_INTERRUPT_BASE + 4)   # 协处理器的中断请求2
#define LS1B_IRQ3_REQ           (MIPS_INTERRUPT_BASE + 5)   # 协处理器的中断请求3
#define LS1B_IRQ_PERF           (MIPS_INTERRUPT_BASE + 6)   # 协处理器的性能统计中断
#define LS1B_IRQ_CNT            (MIPS_INTERRUPT_BASE + 7)    # 协处理器的计数或tick中断,操作系统调度使用

/*
 * Interrupt Control 0 Interrupts: 中断控制器0支持的外设中断数量:29个
 */
#define LS1B_IRQ0_BASE          (MIPS_INTERRUPT_BASE + 8)

#define LS1B_UART0_IRQ          (LS1B_IRQ0_BASE + 2)
#define LS1B_UART1_IRQ          (LS1B_IRQ0_BASE + 3)
#define LS1B_UART2_IRQ          (LS1B_IRQ0_BASE + 4)
#define LS1B_UART3_IRQ          (LS1B_IRQ0_BASE + 5)
#define LS1B_CAN0_IRQ           (LS1B_IRQ0_BASE + 6)
#define LS1B_CAN1_IRQ           (LS1B_IRQ0_BASE + 7)
#define LS1B_SPI0_IRQ           (LS1B_IRQ0_BASE + 8)
#define LS1B_SPI1_IRQ           (LS1B_IRQ0_BASE + 9)
#define LS1B_AC97_IRQ           (LS1B_IRQ0_BASE + 10)
#define LS1B_DMA0_IRQ           (LS1B_IRQ0_BASE + 13)
#define LS1B_DMA1_IRQ           (LS1B_IRQ0_BASE + 14)
#define LS1B_DMA2_IRQ           (LS1B_IRQ0_BASE + 15)
#define LS1B_PWM0_IRQ           (LS1B_IRQ0_BASE + 17)
#define LS1B_PWM1_IRQ           (LS1B_IRQ0_BASE + 18)
#define LS1B_PWM2_IRQ           (LS1B_IRQ0_BASE + 19)
#define LS1B_PWM3_IRQ           (LS1B_IRQ0_BASE + 20)
#define LS1B_RTC0_IRQ           (LS1B_IRQ0_BASE + 21)
#define LS1B_RTC1_IRQ           (LS1B_IRQ0_BASE + 22)
#define LS1B_RTC2_IRQ           (LS1B_IRQ0_BASE + 23)
#define LS1B_TOY0_IRQ           (LS1B_IRQ0_BASE + 24)
#define LS1B_TOY1_IRQ           (LS1B_IRQ0_BASE + 25)
#define LS1B_TOY2_IRQ           (LS1B_IRQ0_BASE + 26)
#define LS1B_RTC_IRQ            (LS1B_IRQ0_BASE + 27)
#define LS1B_TOY_IRQ            (LS1B_IRQ0_BASE + 28)
#define LS1B_UART4_IRQ          (LS1B_IRQ0_BASE + 29)
#define LS1B_UART5_IRQ          (LS1B_IRQ0_BASE + 30)

/*
 * Interrupt Control 1 interrupts:中断控制器1支持的外设中断:4个
 */
#define LS1B_IRQ1_BASE          (MIPS_INTERRUPT_BASE + 40)

#define LS1B_EHCI_IRQ           (LS1B_IRQ1_BASE + 0)
#define LS1B_OHCI_IRQ           (LS1B_IRQ1_BASE + 1)
#define LS1B_GMAC0_IRQ          (LS1B_IRQ1_BASE + 2)
#define LS1B_GMAC1_IRQ          (LS1B_IRQ1_BASE + 3)

/*
 * Interrupt Control 2 interrupts (GPIO):中断控制器2支持的GPIO中断数:31个
 */
#define LS1B_IRQ2_BASE          (MIPS_INTERRUPT_BASE + 72)

#define LS1B_GPIO0_IRQ          (LS1B_IRQ2_BASE + 0)
#define LS1B_GPIO1_IRQ          (LS1B_IRQ2_BASE + 1)
#define LS1B_GPIO2_IRQ          (LS1B_IRQ2_BASE + 2)
#define LS1B_GPIO3_IRQ          (LS1B_IRQ2_BASE + 3)
#define LS1B_GPIO4_IRQ          (LS1B_IRQ2_BASE + 4)
#define LS1B_GPIO5_IRQ          (LS1B_IRQ2_BASE + 5)
#define LS1B_GPIO6_IRQ          (LS1B_IRQ2_BASE + 6)
#define LS1B_GPIO7_IRQ          (LS1B_IRQ2_BASE + 7)
#define LS1B_GPIO8_IRQ          (LS1B_IRQ2_BASE + 8)
#define LS1B_GPIO9_IRQ          (LS1B_IRQ2_BASE + 9)
#define LS1B_GPIO10_IRQ         (LS1B_IRQ2_BASE + 10)
#define LS1B_GPIO11_IRQ         (LS1B_IRQ2_BASE + 11)
#define LS1B_GPIO12_IRQ         (LS1B_IRQ2_BASE + 12)
#define LS1B_GPIO13_IRQ         (LS1B_IRQ2_BASE + 13)
#define LS1B_GPIO14_IRQ         (LS1B_IRQ2_BASE + 14)
#define LS1B_GPIO15_IRQ         (LS1B_IRQ2_BASE + 15)
#define LS1B_GPIO16_IRQ         (LS1B_IRQ2_BASE + 16)
#define LS1B_GPIO17_IRQ         (LS1B_IRQ2_BASE + 17)
#define LS1B_GPIO18_IRQ         (LS1B_IRQ2_BASE + 18)
#define LS1B_GPIO19_IRQ         (LS1B_IRQ2_BASE + 19)
#define LS1B_GPIO20_IRQ         (LS1B_IRQ2_BASE + 20)
#define LS1B_GPIO21_IRQ         (LS1B_IRQ2_BASE + 21)
#define LS1B_GPIO22_IRQ         (LS1B_IRQ2_BASE + 22)
#define LS1B_GPIO23_IRQ         (LS1B_IRQ2_BASE + 23)
#define LS1B_GPIO24_IRQ         (LS1B_IRQ2_BASE + 24)
#define LS1B_GPIO25_IRQ         (LS1B_IRQ2_BASE + 25)
#define LS1B_GPIO26_IRQ         (LS1B_IRQ2_BASE + 26)
#define LS1B_GPIO27_IRQ         (LS1B_IRQ2_BASE + 27)
#define LS1B_GPIO28_IRQ         (LS1B_IRQ2_BASE + 28)
#define LS1B_GPIO29_IRQ         (LS1B_IRQ2_BASE + 29)
#define LS1B_GPIO30_IRQ         (LS1B_IRQ2_BASE + 30)
 
/*
 * Interrupt Control 3 source bit (GPIO):中断控制器3支持的GPIO中断数:30个。
 */
#define LS1B_IRQ3_BASE          (MIPS_INTERRUPT_BASE + 104)

#define LS1B_GPIO32_IRQ         (LS1B_IRQ3_BASE + 0)
#define LS1B_GPIO33_IRQ         (LS1B_IRQ3_BASE + 1)
#define LS1B_GPIO34_IRQ         (LS1B_IRQ3_BASE + 2)
#define LS1B_GPIO35_IRQ         (LS1B_IRQ3_BASE + 3)
#define LS1B_GPIO36_IRQ         (LS1B_IRQ3_BASE + 4)
#define LS1B_GPIO37_IRQ         (LS1B_IRQ3_BASE + 5)
#define LS1B_GPIO38_IRQ         (LS1B_IRQ3_BASE + 6)
#define LS1B_GPIO39_IRQ         (LS1B_IRQ3_BASE + 7)
#define LS1B_GPIO40_IRQ         (LS1B_IRQ3_BASE + 8)
#define LS1B_GPIO41_IRQ         (LS1B_IRQ3_BASE + 9)
#define LS1B_GPIO42_IRQ         (LS1B_IRQ3_BASE + 10)
#define LS1B_GPIO43_IRQ         (LS1B_IRQ3_BASE + 11)
#define LS1B_GPIO44_IRQ         (LS1B_IRQ3_BASE + 12)
#define LS1B_GPIO45_IRQ         (LS1B_IRQ3_BASE + 13)
#define LS1B_GPIO46_IRQ         (LS1B_IRQ3_BASE + 14)
#define LS1B_GPIO47_IRQ         (LS1B_IRQ3_BASE + 15)
#define LS1B_GPIO48_IRQ         (LS1B_IRQ3_BASE + 16)
#define LS1B_GPIO49_IRQ         (LS1B_IRQ3_BASE + 17)
#define LS1B_GPIO50_IRQ         (LS1B_IRQ3_BASE + 18)
#define LS1B_GPIO51_IRQ         (LS1B_IRQ3_BASE + 19)
#define LS1B_GPIO52_IRQ         (LS1B_IRQ3_BASE + 20)
#define LS1B_GPIO53_IRQ         (LS1B_IRQ3_BASE + 21)
#define LS1B_GPIO54_IRQ         (LS1B_IRQ3_BASE + 22)
#define LS1B_GPIO55_IRQ         (LS1B_IRQ3_BASE + 23)
#define LS1B_GPIO56_IRQ         (LS1B_IRQ3_BASE + 24)
#define LS1B_GPIO57_IRQ         (LS1B_IRQ3_BASE + 25)
#define LS1B_GPIO58_IRQ         (LS1B_IRQ3_BASE + 26)
#define LS1B_GPIO59_IRQ         (LS1B_IRQ3_BASE + 27)
#define LS1B_GPIO60_IRQ         (LS1B_IRQ3_BASE + 28)
#define LS1B_GPIO61_IRQ         (LS1B_IRQ3_BASE + 29)

#define LS1B_MAXIMUM_VECTORS        (LS1B_GPIO61_IRQ+1)

#define BSP_INTERRUPT_VECTOR_MIN    0
#define BSP_INTERRUPT_VECTOR_MAX    LS1B_MAXIMUM_VECTORS

备注:中断向量表中一共支持8 + 29 + 4 + 31 + 30 = 8 + 33 + 61 = 102个中断。

中断向量表:

static isr_tbl_t isr_table[BSP_INTERRUPT_VECTOR_MAX];

3.3.3 默认的中断处理或中断服务程序:ls1b_irq.c

/*
 * 默认中断 
 */
static void mips_default_isr(int vector, void *arg)
{
	unsigned int sr;
	unsigned int cause;

	mips_get_sr(sr);
	mips_get_cause(cause);

	printf("Unhandled isr exception: vector 0x%02x, cause 0x%08X, sr 0x%08X\n",
	        vector, cause, sr);

	while (1)
	    ;
}

3.3.4 中断向量表的初始化

/* 
 * 初始化
 */ 
void mips_init_isr_table(void)
{
	unsigned int i;
	
	for (i=0; i<BSP_INTERRUPT_VECTOR_MAX; i++) 
    {
		isr_table[i].handler = mips_default_isr;
		isr_table[i].arg = i;
	}
}

使用默认的中断服务程序mips_default_isr初始化中断向量表。

3.3.5 安装用户自定义的中断服务程序的安装与移除

void ls1x_install_irq_handler(int vector, void (*isr)(int, void *), void *arg)
{
    if ((vector >= 0) && (vector < BSP_INTERRUPT_VECTOR_MAX))
    {
        mips_interrupt_disable();
        isr_table[vector].handler = isr;
        isr_table[vector].arg = (unsigned int)arg;
        mips_interrupt_enable();
    }
}

void ls1x_remove_irq_handler(int vector)
{
    if ((vector >= 0) && (vector < BSP_INTERRUPT_VECTOR_MAX))
    {
        mips_interrupt_disable();
        isr_table[vector].handler = mips_default_isr;
        isr_table[vector].arg = vector;
        mips_interrupt_enable();
    }
}

3.4 4个中断控制器的中断相关的寄存器

3.4.1 中断相关的寄存器列表(每个中断控制器有一套寄存器)

/*
 * Interrupt Control register
 */
#define LS1B_INTC0_BASE         0xBFD01040  #中断控制器0对应的寄存器的基地址
#define LS1B_INTC1_BASE         0xBFD01058  #中断控制器1对应的寄存器的基地址
#define LS1B_INTC2_BASE         0xBFD01070  #中断控制器2对应的寄存器的基地址
#define LS1B_INTC3_BASE         0xBFD01088  #中断控制器3对应的寄存器的基地址

#define LS1B_INTC_ISR(base)     (*(volatile unsigned int*)(base + 0x00))   /* 中断控制状态寄存器 */
#define LS1B_INTC_IEN(base)     (*(volatile unsigned int*)(base + 0x04))   /* 中断控制使能寄存器 */
#define LS1B_INTC_SET(base)     (*(volatile unsigned int*)(base + 0x08))   /* 中断置位寄存器 */
#define LS1B_INTC_CLR(base)     (*(volatile unsigned int*)(base + 0x0C))   /* 中断清空寄存器 */
#define LS1B_INTC_POL(base)     (*(volatile unsigned int*)(base + 0x10))   /* 高电平触发中断使能寄存器 */
                                                                           /* EDGE 电平触发时: 1=高电平触发, 0=低电平触发
                                                                              EDGE 边沿触发时: 1=上升沿触发, 0=下降沿触发 */
#define LS1B_INTC_EDGE(base)    (*(volatile unsigned int*)(base + 0x14))   /* 边沿触发中断使能寄存器; 1:边沿触发, 0: 电平触发 */

3.4.2 32bit 中断寄存器含义

(1)中断控制状态寄存器:表面是否有某种中断发生

(2)中断控制使能寄存器:使能某个中断控制器的某个中断

(3)中断置位寄存器:强制置位对应bits的中断

(4)中断清空寄存器:强制清空对应bit的中断

(5)高电平触发中断使能寄存器:中断使能

3.4.3 32bits如何与中断源对应起来

四个中断控制器对应的bits有各自的含义

/*
 * Interrupt Control 0 source bit:中断控制器0的中断源
 */
#define INTC0_UART5_BIT         bit(30)
#define INTC0_UART4_BIT         bit(29)
#define INTC0_TOY_BIT           bit(28)
#define INTC0_RTC_BIT           bit(27)
#define INTC0_TOY2_BIT          bit(26)
#define INTC0_TOY1_BIT          bit(25)
#define INTC0_TOY0_BIT          bit(24)
#define INTC0_RTC2_BIT          bit(23)
#define INTC0_RTC1_BIT          bit(22)
#define INTC0_RTC0_BIT          bit(21)
#define INTC0_PWM3_BIT          bit(20)
#define INTC0_PWM2_BIT          bit(19)
#define INTC0_PWM1_BIT          bit(18)
#define INTC0_PWM0_BIT          bit(17)
#define INTC0_DMA2_BIT          bit(15)
#define INTC0_DMA1_BIT          bit(14)
#define INTC0_DMA0_BIT          bit(13)
#define INTC0_AC97_BIT          bit(10)
#define INTC0_SPI1_BIT          bit(9)
#define INTC0_SPI0_BIT          bit(8)
#define INTC0_CAN1_BIT          bit(7)
#define INTC0_CAN0_BIT          bit(6)
#define INTC0_UART3_BIT         bit(5)
#define INTC0_UART2_BIT         bit(4)
#define INTC0_UART1_BIT         bit(3)
#define INTC0_UART0_BIT         bit(2)

/*
 * Interrupt Control 1 source bit:中断控制器1的中断源
 */
#define INTC1_GMAC1_BIT         bit(3)
#define INTC1_GMAC0_BIT         bit(2)
#define INTC1_OHCI_BIT          bit(1)
#define INTC1_EHCI_BIT          bit(0)

/*
 * Interrupt Control 2 source bit (GPIO) :中断控制器2对应的中断源
 */
#define INTC2_GPIO30_BIT        bit(30)
#define INTC2_GPIO29_BIT        bit(29)
#define INTC2_GPIO28_BIT        bit(28)
#define INTC2_GPIO27_BIT        bit(27)
#define INTC2_GPIO26_BIT        bit(26)
#define INTC2_GPIO25_BIT        bit(25)
#define INTC2_GPIO24_BIT        bit(24)
#define INTC2_GPIO23_BIT        bit(23)
#define INTC2_GPIO22_BIT        bit(22)
#define INTC2_GPIO21_BIT        bit(21)
#define INTC2_GPIO20_BIT        bit(20)
#define INTC2_GPIO19_BIT        bit(19)
#define INTC2_GPIO18_BIT        bit(18)
#define INTC2_GPIO17_BIT        bit(17)
#define INTC2_GPIO16_BIT        bit(16)
#define INTC2_GPIO15_BIT        bit(15)
#define INTC2_GPIO14_BIT        bit(14)
#define INTC2_GPIO13_BIT        bit(13)
#define INTC2_GPIO12_BIT        bit(12)
#define INTC2_GPIO11_BIT        bit(11)
#define INTC2_GPIO10_BIT        bit(10)
#define INTC2_GPIO9_BIT         bit(9)
#define INTC2_GPIO8_BIT         bit(8)
#define INTC2_GPIO7_BIT         bit(7)
#define INTC2_GPIO6_BIT         bit(6)
#define INTC2_GPIO5_BIT         bit(5)
#define INTC2_GPIO4_BIT         bit(4)
#define INTC2_GPIO3_BIT         bit(3)
#define INTC2_GPIO2_BIT         bit(2)
#define INTC2_GPIO1_BIT         bit(1)
#define INTC2_GPIO0_BIT         bit(0)

/*
 * Interrupt Control 3 source bit (GPIO):中断控制器3对应的中断源
 */
#define INTC3_GPIO61_BIT        bit(29)
#define INTC3_GPIO60_BIT        bit(28)
#define INTC3_GPIO59_BIT        bit(27)
#define INTC3_GPIO58_BIT        bit(26)
#define INTC3_GPIO57_BIT        bit(25)
#define INTC3_GPIO56_BIT        bit(24)
#define INTC3_GPIO55_BIT        bit(23)
#define INTC3_GPIO54_BIT        bit(22)
#define INTC3_GPIO53_BIT        bit(21)
#define INTC3_GPIO52_BIT        bit(20)
#define INTC3_GPIO51_BIT        bit(19)
#define INTC3_GPIO50_BIT        bit(18)
#define INTC3_GPIO49_BIT        bit(17)
#define INTC3_GPIO48_BIT        bit(16)
#define INTC3_GPIO47_BIT        bit(15)
#define INTC3_GPIO46_BIT        bit(14)
#define INTC3_GPIO45_BIT        bit(13)
#define INTC3_GPIO44_BIT        bit(12)
#define INTC3_GPIO43_BIT        bit(11)
#define INTC3_GPIO42_BIT        bit(10)
#define INTC3_GPIO41_BIT        bit(9)
#define INTC3_GPIO40_BIT        bit(8)
#define INTC3_GPIO39_BIT        bit(7)
#define INTC3_GPIO38_BIT        bit(6)
#define INTC3_GPIO37_BIT        bit(5)
#define INTC3_GPIO36_BIT        bit(4)
#define INTC3_GPIO35_BIT        bit(3)
#define INTC3_GPIO34_BIT        bit(2)
#define INTC3_GPIO33_BIT        bit(1)
#define INTC3_GPIO32_BIT        bit(0)

3.4.5 如何根据中断原因寄存器挨个、逐一分发中断服务程序

(1)读取中断原因寄存器

#define LS1B_INTC_ISR(base)     (*(volatile unsigned int*)(base + 0x00))   /* 中断控制状态寄存器 */

#define LS1x_INTC_ISR(base)     LS1B_INTC_ISR(base)

(2)逐一检查原因寄存器

//-----------------------------------------------------------------------------

static void call_vectored_isr(void *p, unsigned int cause, void *ctrlr)
{
    unsigned int src;
    int index;

    /* check request */
    src = LS1x_INTC_ISR((unsigned int)ctrlr);
    index = 0;

    while (src)  //挨个检查所有的中断源
    {
        /* check LSB */
        if (src & 1) 
        {
            /* clear */
            LS1x_INTC_CLR((unsigned int)ctrlr) = (1 << index);
            asm volatile ("sync");
            
            if ((unsigned int)ctrlr == LS1x_INTC0_BASE)
            {
            	bsp_irq_handler_dispatch(LS1x_IRQ0_BASE + index);
            }
            else if ((unsigned int)ctrlr == LS1x_INTC1_BASE)
            {
            	bsp_irq_handler_dispatch(LS1x_IRQ1_BASE + index);
            }
            else if ((unsigned int)ctrlr == LS1x_INTC2_BASE)
            {
            	bsp_irq_handler_dispatch(LS1x_IRQ2_BASE + index);
            }
            else if ((unsigned int)ctrlr == LS1x_INTC3_BASE)
            {
            	bsp_irq_handler_dispatch(LS1x_IRQ3_BASE + index);
            }
    #if defined(LS1C)
            else if ((unsigned int)ctrlr == LS1x_INTC4_BASE)
            {
            	bsp_irq_handler_dispatch(LS1x_IRQ4_BASE + index);
            }
    #endif
        }

        index++;

        /* shift, and make sure MSB is clear */
        src = (src >> 1) & 0x7fffffff;  //挨个检查所有的中断源
    }
}

(3)根据中断向量表执行中断服务器程序

//-----------------------------------------------------------------------------
// 中断分发 
//-----------------------------------------------------------------------------

static void bsp_irq_handler_dispatch(int vector)
{
	if ((vector >= 0) && (vector < BSP_INTERRUPT_VECTOR_MAX))
	{
	    if (isr_table[vector].handler)
        {
            /* 
             * 关中断由中断程序自己处理 
             */
             
            isr_table[vector].handler(vector, (void *)isr_table[vector].arg);
            
            /* 
             * 开中断由中断程序自己处理 
             */
        }
        else
        {
            mips_default_isr(vector, NULL);
        }
	}
	else
	{
		mips_default_isr(vector, NULL);
	}
}

2.4.6 四个中断控制器对应的中断服务程序

static void call_vectored_isr(void *p, unsigned int cause, void *ctrlr)
{
    unsigned int src;
    int index;

    /* check request */
    src = LS1x_INTC_ISR((unsigned int)ctrlr);
    index = 0;

    while (src) 
    {
        /* check LSB */
        if (src & 1) 
        {
            /* clear */
            LS1x_INTC_CLR((unsigned int)ctrlr) = (1 << index);
            asm volatile ("sync");
            
            if ((unsigned int)ctrlr == LS1x_INTC0_BASE)
            {
            	bsp_irq_handler_dispatch(LS1x_IRQ0_BASE + index);
            }
            else if ((unsigned int)ctrlr == LS1x_INTC1_BASE)
            {
            	bsp_irq_handler_dispatch(LS1x_IRQ1_BASE + index);
            }
            else if ((unsigned int)ctrlr == LS1x_INTC2_BASE)
            {
            	bsp_irq_handler_dispatch(LS1x_IRQ2_BASE + index);
            }
            else if ((unsigned int)ctrlr == LS1x_INTC3_BASE)
            {
            	bsp_irq_handler_dispatch(LS1x_IRQ3_BASE + index);
            }
    #if defined(LS1C)
            else if ((unsigned int)ctrlr == LS1x_INTC4_BASE)
            {
            	bsp_irq_handler_dispatch(LS1x_IRQ4_BASE + index);
            }
    #endif
        }

        index++;

        /* shift, and make sure MSB is clear */
        src = (src >> 1) & 0x7fffffff;
    }
}

2.4.7 CPU协处理器是如何调用4个中断控制器对应的中断服务器程序

void c_interrupt_handler(void *p)
{
	unsigned int sr;
	unsigned int cause;

	mips_get_sr(sr);
	
	mips_get_cause(cause);  

	cause &= (sr & SR_IMASK);
	cause >>= CAUSE_IPSHIFT;

	/******************************************************************
	 * XXX use as bsp system tick generator.
	 */
	if (cause & 0x80)			/* count/compare interrupt */
	{
		bsp_irq_handler_dispatch(LS1x_IRQ_CNT);
	}

	if (cause & 0x04)			/* Interrupt controller 0 中断控制器0对应的中断服务程序 */
	{
		call_vectored_isr(p, cause, (void *)LS1x_INTC0_BASE);
	}

	if (cause & 0x08)			/* Interrupt controller 1 中断控制器1对应的中断服务程序*/
	{
		call_vectored_isr(p, cause, (void *)LS1x_INTC1_BASE);
	}

	if (cause & 0x10)			/* Interrupt controller 2 中断控制器2对应的中断服务程序*/
	{
		call_vectored_isr(p, cause, (void *)LS1x_INTC2_BASE);
	}

	if (cause & 0x20)			/* Interrupt controller 3 中断控制器3对应的中断服务程序*/
	{
		call_vectored_isr(p, cause, (void *)LS1x_INTC3_BASE);
	}

#if defined(LS1B)

	if (cause & 0x40)			/* Performance counter */
	{
		bsp_irq_handler_dispatch(LS1x_IRQ_PERF);
	}

#elif defined(LS1C)

	if (cause & 0x40)			/* Interrupt controller 4 */
	{
		call_vectored_isr(p, cause, (void *)LS1x_INTC4_BASE);
	}

#endif

	if (cause & 0x02)			/* Soft Interrupt SW[1] */
	{
		bsp_irq_handler_dispatch(LS1x_IRQ_SW1);
	}
	
	if (cause & 0x01)			/* Soft Interrupt SW[0] */
	{
		bsp_irq_handler_dispatch(LS1x_IRQ_SW0);
	}
	
	// mips_set_cause(0);
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/440256.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Word文档一键转换成电子书,告别繁琐操作!

你是否曾经为了将Word文档转换为电子书而苦恼&#xff1f;手动复制粘贴、调整格式、排版等等繁琐的操作&#xff0c;不仅耗时费力&#xff0c;还容易出错。现在我教你只需轻轻一点&#xff0c;即可将Word文档轻松转换为电子书&#xff0c;无需任何手动操作 一、Word转换电子书步…

基于React低代码平台开发:直击最新应用构建

文章目录 前言一、React与低代码平台的结合优势二、基于React的低代码平台开发挑战三、基于React的低代码平台开发实践四、未来展望《低代码平台开发实践&#xff1a;基于React》编辑推荐内容简介作者简介目录前言为什么要写这本书读者对象如何阅读本书 前言 随着数字化转型的…

Word论文格式怎么设置 Word论文查重功能在哪里 论文格式要求及字体大小 论文查重怎么查 WPS论文查重准确吗

Word文档是由Microsoft Word处理软件创建和编辑的文档。Word文档通常用于创建各种类型的文档&#xff0c;如信函、报告、简历、论文等。本篇文章将为大家介绍Word论文格式怎么设置以及Word论文查重功能在哪里。 一、Word论文格式怎么设置 一个好的论文格式&#xff0c;是论文…

【框架设计】MVC、MVP、MVVM对比图

1. MVC&#xff08;Model-View-Controller&#xff09; 2. MVP&#xff08;Model-View-Presenter&#xff09; 3. MVVM&#xff08;Model-View-ViewModel&#xff09;

ai数字人虚拟直播:AI大模型带给你不一样的体验

AI数字人虚拟直播&#xff0c;这一新兴的科技形式&#xff0c;正逐渐融入人们的生活之中。通过AI大模型的技术支持&#xff0c;数字人可以实现高度仿真的互动体验&#xff0c;让观众感受到前所未有的沉浸式乐趣。 数字人虚拟直播的魅力在于其超越了传统直播形式的局限性&#…

Python爬虫——Scrapy-1

目录 简介 安装 基本使用 1. 创建爬虫的项目 2. 创建爬虫文件 3. 运行爬虫代码 scrapy项目组成 scrapy工作原理 ​编辑 58同城 scrapy架构组成 汽车之家 总结 简介 Scrapy 是一个基于 Python 的开源网络爬虫框架&#xff0c;它可以帮助开发者快速、高效地构…

数据结构从入门到精通——栈

栈 前言一、栈1.1栈的概念及结构1.2栈的实现1.3栈的面试题 二、栈的具体实现代码栈的初始化栈的销毁入栈出栈返回栈顶元素返回栈中的元素个数检测是否为空Stack.hStack.ctest.c 前言 栈&#xff0c;作为一种后进先出&#xff08;LIFO&#xff09;的数据结构&#xff0c;在计算…

Windows系统搭建it-tools工具箱并结合内网穿透实现公网远程访问

文章目录 1. 使用Docker本地部署it-tools2. 本地访问it-tools3. 安装cpolar内网穿透4. 固定it-tools公网地址 本篇文章将介绍如何在Windows上使用Docker本地部署IT- Tools&#xff0c;并且同样可以结合cpolar实现公网访问。 在前一篇文章中我们讲解了如何在Linux中使用Docker搭…

FPGA FIFO 读取模式

FPGA FIFO 读取模式分两种&#xff1a; Normal Mode: In normal mode, the “rdreq” signal serves as the read request or read enable. When this signal goes high, the data output provides the first data from the FIFO.Essentially, in normal mode, data is availa…

pytest测试框架使用基础07 fixture—parametrize获取参数的几种常用形式

【pytest】parametrize获取参数的几种常用形式: a.数据结构 b.文件 c.数据库 d.conftest.py配置一、直接在标签上传参 1.1 一个参数多个值 pytest.mark.parametrize("参数", (参数值1, 参数值2, 参数值3))示例&#xff1a; import pytest # 单个参数的情况 pytest.…

如何向各大媒体网站投稿 海外媒体发稿平台有哪些

在数字化时代&#xff0c;各大媒体网站是企业推广和个人展示的重要平台。通过在媒体网站上发布文章&#xff0c;可以有效地扩大影响力和提升知名度。但是&#xff0c;如何投稿到各大媒体网站呢&#xff1f;以下是一些常用的方法和步骤。 1. 研究目标媒体 在投稿之前&#xff0…

宠物空气净化器值得入手吗?选购宠物空气净化器关注哪些方面?

一开始养猫时&#xff0c;每天看着可爱的猫咪在家里快乐奔跑&#xff0c;让人心情愉悦。然而&#xff0c;作为铲屎官都知道&#xff0c;猫咪会掉毛&#xff0c;特别是在换毛期间&#xff0c;地板、沙发上都会有一大堆猫毛&#xff0c;甚至衣服也可能沾满猫毛。养猫家庭中&#…

安装邮件服务器postfix、mail客户端发送邮件

安装邮件服务器postfix、mail客户端发送邮件 1 安装postfix sudo apt-get update sudo apt-get install postfix -y安装过程中会让你选择一种Postfix配置类型&#xff0c;直接选择默认的第二种配置Internet Site就可以了。 选择ok之后会让你填入域名&#xff0c;一般会自动填…

鞋服品牌怎样合理把控订货深度和宽度

在鞋服品牌的运营管理中&#xff0c;订货深度和宽度是两个至关重要的概念。订货深度指的是某一款式或规格的产品数量&#xff0c;而订货宽度则代表品牌所涵盖的产品种类和款式。合理把控订货深度和宽度对于品牌的库存管理、销售情况以及顾客满意度都有着深远的影响。本文将探讨…

MindOpt优化器: 浅谈版本0.x和1.x之间API的差异

Mindopt 是一个优化求解器&#xff0c;如果它有两个主要版本——0.xx和1.x.x&#xff08;最新版本1.1.1&#xff09;&#xff0c;它们代表着软件开发的两个不同阶段。版本1.0.0表示软件的一个大的里程碑&#xff0c;代表着软件第一个正式的“成熟”发布版本&#xff0c;而0.25是…

【保姆级爬虫】微博关键词搜索并获取博文和评论内容(python+selenium+chorme)

微博爬虫记录 写这个主要是为了防止自己忘记以及之后的组内工作交接&#xff0c;至于代码美不美观&#xff0c;写的好不好&#xff0c;统统不考虑&#xff0c;我只能说&#xff0c;能跑就不错了&#xff0c;上学压根没学过python好吧&#xff0c;基本上是crtlc&ctrlv丝滑小…

说说flexbox(弹性盒布局模型)及适用场景?

文章目录 一、是什么二、属性flex-directionflex-wrapflex-flowjustify-contentalign-itemsalign-contentorderflex-growflex-basisflexalign-self 三、应用场景参考文献 一、是什么 Flexible Box 简称 flex&#xff0c;意为”弹性布局”&#xff0c;可以简便、完整、响应式地…

轻松关掉电脑用户账户控制弹窗!

对于新装的或者是电脑自带的系统来说,是不是会经常遇到的一个情况是,就是在你运行某些程序或者改动一些系统设置的时候,每次都会弹出个提示框,以提示你这个操作是安全的,某一个提示还行,但是每次运行程序都有提示框弹出,就会有点烦了,那么这个提示框是什么呐,如何关闭…

如何实现企业内部ERP、OA、CRM、MES系统的快速一体化集成

在企业数字化规划中&#xff0c;企业纷纷引入ERP&#xff08;企业资源规划&#xff09;、OA&#xff08;办公自动化&#xff09;、CRM&#xff08;客户关系管理&#xff09;、MES&#xff08;制造执行系统&#xff09;、电商ERP(电商订单系统)等多种信息化管理系统&#xff0c;…

你自降门槛 我就该回头吗?

作者&#xff1a;朱溪 琥珀酒研社快评&#xff1a; 曾经的你让我高攀不起 现在的我对你爱答不理 同事的哥哥 因为拿不出30万的彩礼和女友分了 两年后他开了公司也有了钱 女友跑来求复合 同事的哥哥想都没想就拒绝了 用金钱给爱情设门槛&#xff0c;爱情黄了 一个能力…