平台中断控制器(Platform Level Interrupt Controller,PLIC)是国科安芯AS32系列MCU芯片的中断控制器,主要对中断源进行采样,优先级仲裁和分发。各外设中断统一连到PLIC,PLIC统一管理并输出中断请求到内核。
硬件设计
本节硬件同USART章节一致。
软件设计
代码分析
在之前的按键章节我们已经对AS32的中断进行了简单实用,本节将用串口的接收中断实验进一步加深一下使用过程。
回顾之前的启动文件章节,有如下一段代码:
在RISCV指令集中,在机器模式下中断相关的寄存器有MSTATUS、MIE和MTVEC,其中前两个寄存器控制系统中断使能,具体内容颗翻看启动文件讲解,MTVEC用于保存中断入口地址,当中断发生时,程序指针会自动跳转到TrapEntry地址处开始执行,该段代码位于as32x601_trapentry.S文件中,用汇编文件编写,在这个函数下,我们会将RISCV内核所有相关寄存器,包括PC指针等全部进行保存,然后调用中断入口处理函数,完成后恢复现场寄存器值,从而实现中断功能。
中断处理函数位于as32x601_plic.c文件中,我们找到如下函数:
- / *
- Function: PLIC_TrapHandler
- Description: Interrupt handler type selection.
- Param: Mcause: determine the type of exception or interrupt based on the value of the mcause register.
- Return: None
- */
- void PLIC_TrapHandler(uint32_t Mcause)
- {
*/* Initializes the external interrupt structure */*
PLIC_EXTITypeDef ExtInt = {{0}, 0};
11.
12. ```
if((Mcause & 0x80000000) != 0)
{
14. ```
switch (Mcause & 0x0fff)
{
16. ```
case 3: */* Machine software interrupt */*
MSoftWare_IRQ_Handler();
18. ```
break;
case 7: / Machine timer interrupt /
20. ```
MTimer_IRQ_Handler();
break;
22. ```
case 11: */* Machine external interrupt */*
PLIC_SwitchMEXTI(&ExtInt);
24. ```
break;
default:
26. ```
break;
}
28. ```
}
else
30. ```
{
switch (Mcause & 0xfff)
32. ```
{
case 0: / Instruction address misaligned /
34. ```
InstAddrMisalign_Handler();
break;
36. ```
case 1: */* Instruction access fault */*
InstAccessFault_Handler();
38. ```
break;
case 2: / Illegal instruction /
40. ```
IllegalInst_Handler();
break;
42. ```
case 3: */* Breakpoint */*
Breakpoint_Handler();
44. ```
break;
case 4: / Load address misaligned /
46. ```
LoadAddrMisalign_Handler();
break;
48. ```
case 5: */* Load access fault */*
LoadAccessFault_Handler();
50. ```
break;
case 6: / Store/AMO address misaligned /
52. ```
StoreAMOAddrMisalign_Handler();
break;
54. ```
case 7: */* Store/AMO access fault */*
StoreAMOAccessFault_Handler();
56. ```
break;
case 11: / Environment call from M-mode /
58. ```
ECall_Handler();
break;
60. ```
case 12: */* Instruction page fault */*
InstPageFault_Handler();
62. ```
break;
case 13: / Load page fault /
64. ```
LoadPageFault_Handler();
break;
66. ```
case 15: */* Store/AMO page fault */*
StoreAMOPageFalut_Handler();
68. ```
break;
default:
70. ```
break;
}
72. ```
}
- }
在这个函数中,系统中断首先会读取MCAUSE寄存器的最高位,如果最高位为0,代表此事件为异常,RISCV定义了此类型,具体可直接查看MCAUSE寄存器定义;如果最高位为1,证明此事件为系统中断,此时可根据低位去选择处理的中断类型。
AS32除了系统定时中断和软件中断外,plic定义了64个plic中断,之前的的异常和中断均为向量类型,但进入plic中断后即为非向量模式,但可以软件支持嵌套,64个中断类型均已经在此文件中定义,所有定义均为弱函数,因此可以复制中断处理函数名写在自定义位置。接下来以串口中断为例介绍用法:
复制之前的usart工程,在print.c中修改初始化代码如下:
- / *
- Function: User_Print_Init
- Description: Configure Print USART.
- Param: BaudRate: USART communication baud rate.
- Return: None.
- */
- void User_Print_Init(uint32_t BaudRate)
- {
USART_InitTypeDef USART_InitStructure;
GPIO_InitTypeDef GPIO_InitStructure;
11. ```
PLIC_InitTypeDef PLIC_InitStructure;
GPIOD_CLK_ENABLE();
14. ```
USART0_CLK_ENABLE();
/ Set GPIO multiplex mapping /
17. ```
GPIO_PinAFConfig(GPIOD, GPIO_PinSource8, GPIO_AF_USART0); */* USART0_TX */*
GPIO_PinAFConfig(GPIOD, GPIO_PinSource9, GPIO_AF_USART0); / USART0_RX /
19. ```
*/* GPIO Configure */*
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8;
21. ```
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
GPIO_InitStructure.GPIO_OType = GPIO_Out_PP;
23. ```
GPIO_InitStructure.GPIO_OStrength = GPIO_OStrength_4_5mA;
GPIO_Init(GPIOD, &GPIO_InitStructure);
25. ```
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN;
27. ```
GPIO_InitStructure.GPIO_IType = GPIO_IN_FLOATING;
GPIO_InitStructure.GPIO_OStrength = GPIO_OStrength_4_5mA;
29. ```
GPIO_Init(GPIOD, &GPIO_InitStructure);
USART_DeInit(USART0);
32.
33. ```
USART_StructInit(&USART_InitStructure);
/ Initializes the USART0 /
36. ```
USART_InitStructure.USART_BaudRate = BaudRate;
USART_InitStructure.USART_WordLength = USART_WordLength_8b;
38. ```
USART_InitStructure.USART_StopBits = USART_StopBits_1;
USART_InitStructure.USART_Parity = USART_Parity_No;
40. ```
USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
USART_InitStructure.USART_OverSampling = USART_OverSampling_16;
42. ```
USART_Init(USART0, &USART_InitStructure);
USART_Cmd(USART0, ENABLE);
45.
46. ```
USART_ITConfig(USART0, USART_IT_RXNE, ENABLE);
/ Configer the USART0 interrupt /
49. ```
PLIC_InitStructure.PLIC_IRQChannel = USART0_IRQn;
PLIC_InitStructure.PLIC_IRQPriority = 1;
51. ```
PLIC_InitStructure.PLIC_IRQChannelCmd = ENABLE;
PLIC_Init(&PLIC_InitStructure);
53. }
54.
55. */* *
56. * Function: USART0_IRQ_Handler
57. * Description: USART0 interrupt handler function.
58. * Param: None.
59. * Return: None.
60. */
61.
62. void USART0_IRQ_Handler()
63. {
64.
65. ```
if(USART_GetFlagStatus(USART0, USART_FLAG_RXNE) != RESET)
{
67. ```
*/* Clear the interrupt pending bits */*
USART_SendData(USART0,USART_ReceiveData(USART0));
69. ```
}
- }
在这个代码中,44行之前和串口章节完全一样,不再重复进行说明。第46行,调用串口的中断使能函数,使能串口接收中断,该处形参中的中断类型已经定义好,可以自行查询,之后需要开启PLIC的中断通道以及优先级配置,之后调用PLIC_Init函数进行初始化。
接下来,需要重写中断处理函数,该函数名已经在PLIC库文件中定义完成,直接复制过来即可,在这个函数中首先判断终端的来源,之后通过调用发送函数原路径发出,当然这只是一个实验,功能比较简单,实际使用过程中切忌这种用法。
最后主函数中对上述代码只需要做初始化即可,没有实际逻辑,因此在这不做展示。
下板验证
将上述代码编译烧录完成,连接串口线与上位机,观察现象。
审核编辑 黄宇
-
驱动
+关注
关注
12文章
1928浏览量
88206 -
中断控制器
+关注
关注
0文章
62浏览量
9774
发布评论请先 登录
串口中断触发卡死怎么解决?
e203添加中断源,中断源无法使能怎么解决?
浅析riscv中的plic与eclic
蜂鸟E203内核中断管理模块sirv_plic_man代码分析
基于 AS32X601 微控制器的定时器模块(TIM)技术研究与应用实践
AS32X601芯片Flash擦写调试技术解析
AS32X601系列MCU硬件最小系统设计与调试方案探析
AS32X601驱动系列教程 USART_串口通讯详解
AS32X601驱动系列教程 GPIO_按键检测详解
AS32X601驱动系列教程 GPIO_点亮LED详解
AS32X601驱动系列教程 SMU_系统时钟详解
面向工业与汽车领域的高安全可靠MCU——AS32X601系列芯片解析
AS32X601芯片技术剖析
AS32X601双核锁步MCU技术优势分析
EE-188:使用C语言在ADSP-219x DSP上实现中断驱动系统

AS32X601驱动系列教程 PLIC_中断应用详解
评论