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

目录

一、CP0概述

[1.1 CP0概述](#1.1 CP0概述)

[1.2 龙芯异常exception与中断interrupt的区别](#1.2 龙芯异常exception与中断interrupt的区别)

二、CPU协处理器的异常处理

三、外部中断与外部中断控制器

[3.1 外部中断源](#3.1 外部中断源)

[3.2 如何配置外部中断源](#3.2 如何配置外部中断源)

[3.3 外部中断的中断向量表](#3.3 外部中断的中断向量表)

[3.2.1 软件中断向量表结构定义:ls1b_irq.c](#3.2.1 软件中断向量表结构定义:ls1b_irq.c)

[3.2.2 软件中断向量表定义:ls1b_irq.c和ls1b_irq.h](#3.2.2 软件中断向量表定义:ls1b_irq.c和ls1b_irq.h)

[3.3.3 默认的中断处理或中断服务程序:ls1b_irq.c](#3.3.3 默认的中断处理或中断服务程序:ls1b_irq.c)

[3.3.4 中断向量表的初始化](#3.3.4 中断向量表的初始化)

[3.3.5 安装用户自定义的中断服务程序的安装与移除](#3.3.5 安装用户自定义的中断服务程序的安装与移除)


一、CP0概述

1.1 CP0概述

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

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

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

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

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

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

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

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

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

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

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

二、CPU协处理器的异常处理

三、外部中断与外部中断控制器

3.1 外部中断源

龙芯1B SOC芯片内置简单、灵活的中断控制器

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();
    }
}
相关推荐
几度春风里5 小时前
嵌入式Linux系统编程 — 7.2 进程的环境变量
嵌入式·linux系统编程·进程的环境变量
飞翔的佩奇10 小时前
Java项目:基于SSM框架实现的德云社票务管理系统【ssm+B/S架构+源码+数据库+开题报告+毕业论文】
java·数据库·spring·架构·maven·ssm框架·票务系统
鲁鲁51714 小时前
梧桐数据库:存算分离和存算一体架构的分布式数据库技术分析
数据库·分布式·架构·梧桐数据库
向阳逐梦14 小时前
对回收站里的文件进行操作
算法·程序员·架构
飞翔的佩奇14 小时前
Java项目:基于SSM框架实现的智慧城市实验室管理系统分前后台【ssm+B/S架构+源码+数据库+毕业论文】
java·数据库·架构·java-ee·maven·智慧城市·ssm框架
垫脚摸太阳15 小时前
springboot三层架构详细讲解
spring boot·后端·架构
虫小宝16 小时前
Spring Boot中的多租户架构实现
spring boot·后端·架构
rolt18 小时前
[图解]企业应用架构模式2024新译本讲解21-数据映射器3
架构·架构师
桃宝护卫队18 小时前
前后端分离:四种开发模式与实践指南
前端·后端·架构·前后端分离·技术架构
blessing。。19 小时前
Linux中cat命令的英文含义
linux·运维·服务器·嵌入式