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

本文主要是介绍[嵌入式系统-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 龙芯异常exception与中断interrupt的区别

1.5 向量中断与非向量中断

 1.6 MIPS CPU的异常向量与异常向量号:向量中断的支持

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

2.1 CP0概述

2.2 协处理器支持的32个寄存器与CP0寄存器操作指令

 2.3 CPU协处理器CP0支持的指令执行异常:32个异常​编辑

2.4 CPU协处理器CP0支持的中断:8个中断

2.4.1 默认的中断号定义

2.4.2 中断号的配置与控制

2.5 协处理器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 龙芯异常exception与中断interrupt的区别

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

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

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

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

1.5 同步中断与非同步中断

同步中断和异步中断是计算机中两种不同类型的中断处理方式。

  1. 同步中断

    • 在同步中断中,中断事件的发生和处理是同步发生的,也就是说,处理器会立即响应中断请求,并在当前执行的指令之后立即处理中断。
    • 这种中断处理方式通常用于一些特定的同步事件,例如硬件错误、系统调用等。在这种情况下,处理器需要立即响应并处理中断,以保证系统的正确性和稳定性。
  2. 异步中断

    • 异步中断是指中断事件的发生和处理是异步的,处理器不会立即响应中断请求,而是在当前执行的指令结束后,再由中断控制器通知处理器发生了中断事件,然后才开始处理中断。
    • 典型的异步中断包括外部设备的输入输出请求、定时器中断等。这些中断事件的发生不受处理器当前指令的影响,因此称为异步中断

总的来说,同步中断是指中断事件和处理是同步发生的,而异步中断则是指中断事件和处理是异步的,处理器会在适当的时候才响应和处理中断请求。

1.6 向量中断与非向量中断

向量中断与非向量中断是处理器中处理中断的两种主要方式。

  1. 向量中断(Vectored Interrupts):

    • 在向量中断系统中,每个中断都有一个唯一的向量号
    • 处理器硬件可以根据中断向量号直接访问/调用中断服务程序的入口地址
    • 当中断发生时,处理器硬件会自动跳转到相应中断服务程序的入口地址。
    • 向量中断系统通常能够提供更快的中断响应时间,因为处理器软件不需要额外的逻辑来确定中断服务程序的入口地址。
  2. 非向量中断(Non-Vectored Interrupts):

    • 在非向量中断系统中,中断服务程序的入口地址不是由中断向量表直接确定的。
    • 处理器收到中断后,需要通过硬件设计或软件配置来确定统一的中断服务程序的入口地址。如在龙芯1B中为c_exception_handler。
    • 通常需要额外的逻辑来确定中断服务程序的入口地址,因此可能导致较长的中断响应时间。包括额外的硬件逻辑和额外的软件逻辑,硬件逻辑包括控制器和原因寄存器,软件包括读取中断原因寄存器,并根据中断原因寄存器执行中断,此时的中断向量表是通过软件数组来维护的。
    • 非向量中断系统在处理不同类型的中断时可能需要更多的处理逻辑。

 1.7 MIPS CPU的异常向量与异常向量号:向量中断的支持

龙芯1B GS232处理器支持向量中断(Non-Vectored Interrupts)和非向量中断

如下是1B GS232处理器支持的异常向量表:

实际上,龙芯1B也支持非向量中断,非向量中断更加的灵活,大部分场景下,采用的是非向量中断,下面就阐述龙芯1B对非向量中断的支持。

二、协议处理器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个寄存器与CP0寄存器操作指令

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

 2.3 CPU协处理器CP0支持的指令执行异常:32个异常

备注:

  • 异常代码0:代表8个中断异常,在异常编码中,编码最小,优先级最低。
  • 上述指令异常,部分需要软件处理,大部分是不需要软件处理的,而是有硬件电路进行处理
  • Cause寄存器中的代码,不需要提供中断服务程序,提供个软件记录和现实异常的原因,辅助定位,大部分的异常处理,是由硬件完成纠错和处理,不需要软件参与。软件只需要把这些异常的原因记录和现实下来。

/** 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 

#define MIPS_EXCEPTION_BASE             0

#define MIPS_EXCEPTION_INT                   MIPS_EXCEPTION_BASE+0  # 中断异常

#define MIPS_EXCEPTION_WATCH            MIPS_EXCEPTION_BASE+23

#define MIPS_EXCEPTION_VCED               MIPS_EXCEPTION_BASE+31

#define MIPS_INTERRUPT_BASE                MIPS_EXCEPTION_BASE+32  //中断控制器的中断服务程序入口

2.4 CPU协处理器CP0支持的中断:8个中断

2.4.1 默认的中断号定义

/*
 * 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)  //软件触发的中断SW0
#define LS1B_IRQ_SW1             (MIPS_INTERRUPT_BASE + 1)  //软件触发的中断SW1

#define LS1B_IRQ0_REQ    (MIPS_INTERRUPT_BASE + 2) //来自SOC芯片的中断控制器0
#define LS1B_IRQ1_REQ    (MIPS_INTERRUPT_BASE + 3) //来自SOC芯片的中断控制器1
#define LS1B_IRQ2_REQ    (MIPS_INTERRUPT_BASE + 4) //来自SOC芯片的中断控制器2
#define LS1B_IRQ3_REQ     (MIPS_INTERRUPT_BASE + 5)//来自SOC芯片的中断控制器3
#define LS1B_IRQ_PERF           (MIPS_INTERRUPT_BASE + 6) //来自CP0的性能统计
#define LS1B_IRQ_CNT            (MIPS_INTERRUPT_BASE + 7)  //来自CP0的Tick计数,用
于操作系统tick调度

// 备注:

//中断号越大,优先级越高

//中断号越小,优先级越低

2.4.2 中断号的配置与控制

默认情况下,性能统计和Tick计数的中断,其中断号是6和7,龙芯1B允许对该中断号进行修改,以降低其优先级,默认情况下,数值越大,优先级越高。

  • IPTI:自定义Tick计数器中断的中断号
  • IPPCI:自定义性能统计计数器中断的中断号
  • VS:定义中断向量表的地址间隔,0表示相邻,1表示相隔32字节.....

2.5 协处理器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);}#endifif (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);}#endifif (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);
}

这篇关于[嵌入式系统-37]:龙芯1B 开发学习套件 -6-协处理器CP0之CPU异常处理与外部中断控制器的中断处理的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/792004

相关文章

HarmonyOS学习(七)——UI(五)常用布局总结

自适应布局 1.1、线性布局(LinearLayout) 通过线性容器Row和Column实现线性布局。Column容器内的子组件按照垂直方向排列,Row组件中的子组件按照水平方向排列。 属性说明space通过space参数设置主轴上子组件的间距,达到各子组件在排列上的等间距效果alignItems设置子组件在交叉轴上的对齐方式,且在各类尺寸屏幕上表现一致,其中交叉轴为垂直时,取值为Vert

Ilya-AI分享的他在OpenAI学习到的15个提示工程技巧

Ilya(不是本人,claude AI)在社交媒体上分享了他在OpenAI学习到的15个Prompt撰写技巧。 以下是详细的内容: 提示精确化:在编写提示时,力求表达清晰准确。清楚地阐述任务需求和概念定义至关重要。例:不用"分析文本",而用"判断这段话的情感倾向:积极、消极还是中性"。 快速迭代:善于快速连续调整提示。熟练的提示工程师能够灵活地进行多轮优化。例:从"总结文章"到"用

不懂推荐算法也能设计推荐系统

本文以商业化应用推荐为例,告诉我们不懂推荐算法的产品,也能从产品侧出发, 设计出一款不错的推荐系统。 相信很多新手产品,看到算法二字,多是懵圈的。 什么排序算法、最短路径等都是相对传统的算法(注:传统是指科班出身的产品都会接触过)。但对于推荐算法,多数产品对着网上搜到的资源,都会无从下手。特别当某些推荐算法 和 “AI”扯上关系后,更是加大了理解的难度。 但,不了解推荐算法,就无法做推荐系

这15个Vue指令,让你的项目开发爽到爆

1. V-Hotkey 仓库地址: github.com/Dafrok/v-ho… Demo: 戳这里 https://dafrok.github.io/v-hotkey 安装: npm install --save v-hotkey 这个指令可以给组件绑定一个或多个快捷键。你想要通过按下 Escape 键后隐藏某个组件,按住 Control 和回车键再显示它吗?小菜一碟: <template

基于人工智能的图像分类系统

目录 引言项目背景环境准备 硬件要求软件安装与配置系统设计 系统架构关键技术代码示例 数据预处理模型训练模型预测应用场景结论 1. 引言 图像分类是计算机视觉中的一个重要任务,目标是自动识别图像中的对象类别。通过卷积神经网络(CNN)等深度学习技术,我们可以构建高效的图像分类系统,广泛应用于自动驾驶、医疗影像诊断、监控分析等领域。本文将介绍如何构建一个基于人工智能的图像分类系统,包括环境

水位雨量在线监测系统概述及应用介绍

在当今社会,随着科技的飞速发展,各种智能监测系统已成为保障公共安全、促进资源管理和环境保护的重要工具。其中,水位雨量在线监测系统作为自然灾害预警、水资源管理及水利工程运行的关键技术,其重要性不言而喻。 一、水位雨量在线监测系统的基本原理 水位雨量在线监测系统主要由数据采集单元、数据传输网络、数据处理中心及用户终端四大部分构成,形成了一个完整的闭环系统。 数据采集单元:这是系统的“眼睛”,

无人叉车3d激光slam多房间建图定位异常处理方案-墙体画线地图切分方案

墙体画线地图切分方案 针对问题:墙体两侧特征混淆误匹配,导致建图和定位偏差,表现为过门跳变、外月台走歪等 ·解决思路:预期的根治方案IGICP需要较长时间完成上线,先使用切分地图的工程化方案,即墙体两侧切分为不同地图,在某一侧只使用该侧地图进行定位 方案思路 切分原理:切分地图基于关键帧位置,而非点云。 理论基础:光照是直线的,一帧点云必定只能照射到墙的一侧,无法同时照到两侧实践考虑:关

Hadoop企业开发案例调优场景

需求 (1)需求:从1G数据中,统计每个单词出现次数。服务器3台,每台配置4G内存,4核CPU,4线程。 (2)需求分析: 1G / 128m = 8个MapTask;1个ReduceTask;1个mrAppMaster 平均每个节点运行10个 / 3台 ≈ 3个任务(4    3    3) HDFS参数调优 (1)修改:hadoop-env.sh export HDFS_NAMENOD

【前端学习】AntV G6-08 深入图形与图形分组、自定义节点、节点动画(下)

【课程链接】 AntV G6:深入图形与图形分组、自定义节点、节点动画(下)_哔哩哔哩_bilibili 本章十吾老师讲解了一个复杂的自定义节点中,应该怎样去计算和绘制图形,如何给一个图形制作不间断的动画,以及在鼠标事件之后产生动画。(有点难,需要好好理解) <!DOCTYPE html><html><head><meta charset="UTF-8"><title>06

学习hash总结

2014/1/29/   最近刚开始学hash,名字很陌生,但是hash的思想却很熟悉,以前早就做过此类的题,但是不知道这就是hash思想而已,说白了hash就是一个映射,往往灵活利用数组的下标来实现算法,hash的作用:1、判重;2、统计次数;