软件版本:Anlogic -TD5.9.1-DR1_ES1.1
操作系统:WIN10 64bit
硬件平台:适用安路(Anlogic)FPGA
实验平台:米联客-MLK-L1-CZ06-DR1M90G开发板
板卡获取平台:https://milianke.tmall.com/
登录“米联客”FPGA社区 http://www.uisrc.com 视频课程、答疑解惑!
目录
1 概述
当正常的程序在运行的时候,中断资源可以打断正在运行的程序,让CPU进入中断函数进行一些事务的处理。使用中断处理可以实现多任务的实时处理,可以提高多任务处理的效率。
本文实验目的:
1:掌握理解中断输入的应用场合
2:PS PSIO的中断寄存器功能定义
3:掌握FD下PSIO中断功能的使用
2 系统框图
PSIO一般会分配到固定的外设,包括FLASH、EMMC、TFCARD、UART、USB2.0、ETH以太网。GPIO也可以单独配置成普通的PSIO,如果IO不够用也可以通过PLIO扩展更多IO。
3 GPIO中断处理
中断检测逻辑监控 GPIO输入信号。中断触发器可以是正边缘、负边缘、低电平或高电平。使用GPIOINTTYPE LEVEL、GPIO INT POLARITY 和 GPIO INTEN 对触发灵敏度进行编程。
如果检测到中断,则中断检测逻辑将 GPI0 的 GPIO INTSTATUS 状态置 1。如果 GPIO 中断是边缘敏感的,则中断状态被检测逻辑锁存。通过向 GPIO_PORTA_EOI寄存器写入1来清除中断锁存,然后再通过向 GPIO PORTA EOI寄存器写入0来使能中断。对于电平敏感中断,为了清除中断信号,必须清除中断输入到 GPIO 的中断源。或者,软件可以使用 GPIO INTMASK 寄存器屏蔽输入。
4 硬件电路分析
硬件接口和子卡模块请阅读“附录1”
配套工程的FPGA PIN脚定义路径为soc_prj/uisrc/04_pin/ fpga_pin.adc
5 搭建SOC系统工程
详细的搭建过程这里不再重复,对于初学读者如果还不清楚如何创建SOC工程的,请学习“01Vitis Soc开发入门”这篇文章。
本文中的PS设置内容是新增加的GPIO PS以及GPIO PL部分,关于DDR、PSIO、CPU时钟等设置请参考“01Vitis Soc开发入门”这篇文章。
5.1 GPIO配置
01Vitis Soc开发入门”这篇文章中已经对特定功能的PSIO做了设置,只有剩余的PSIO可以用于其他的自定义功能。以下设置未分配功能的PSIO,以及需要扩展的GPIO PL IO的数量。
5.2 GPIO PL定义
设置好后,右击选择Create Design Port,我们需要两个PL 按键输入
设置IO名称、IO类型、IO位宽
module system_top
(
input [1:0] PL_KEY
);
system I_system (.pl_gpio_in(PL_KEY));
endmodule
5.3编译并导出平台文件
以下步骤简写,有不清楚的看第1篇《01 Soc开发入门》文章。
导出完成后,对应工程路径的soc_hw路径下有硬件平台文件:fpga_prj.hpf的文件。根据硬件平台文件fpga_prj.hpf来创建需要Platform平台。
6 搭建SOC系统工程
创建soc_base sdk platform和APP工程的过程不再重复,如果不清楚请参考本章节第一个demo。
6.1 创建Platform工程
创建soc_base sdk platform和APP工程的过程不再重复,如果不清楚请参考本章节第一个demo《01 Soc开发入门》文章。
6.2 创建gpio_intr APP工程
7 程序分析
gpio_intr.C文件
#include "al_gpio_hal.h"
#define PL_KEY1 54
#define PL_KEY2 55
#define PS_KEY1 50
#define AL_GPIO_DEVICE_ID 0
#define BANK_INTR_VALUE 0x3
#define BANK_TYPE_REG 0x3
#define BANK_POLARUTY_REG 0x0
#define BANK_BOTHEDGE_REG 0x0
//#define BANK_INTR
#define PIN_INTR
AL_S32 AlGpio_Hal_Intr_Example()
{
AL_GPIO_HalStruct *GPIO;
AL_S32 i = 0;
/* 1、Test AlGpio_Hal_Init */
AL_S32 ret = AlGpio_Hal_Init(&GPIO, AL_GPIO_DEVICE_ID, AL_NULL);
if (ret == AL_OK) {
AL_LOG(AL_LOG_LEVEL_INFO, "[TEST] APU AlGpio_Hal_Init success");
}
else {
AL_LOG(AL_LOG_LEVEL_INFO, "[TEST] APU AlGpio_Hal_Init failed");
}
/* 2、Test InputRead EXT register */
for(i = 0; i < 6; i++) {
AL_LOG(AL_LOG_LEVEL_INFO, "GPIO Pin %d input data value is 0x%x", PL_KEY1, AlGpio_Hal_ReadPinInput(GPIO,PL_KEY1));
}
/* 3、Test intr */
#ifdef PIN_INTR
AlGpio_Hal_IntrPinCfg(GPIO, PL_KEY1, GPIO_INTR_TYPE_EDGE_FALLING);
AlGpio_Hal_IntrPinCfg(GPIO, PL_KEY2, GPIO_INTR_TYPE_EDGE_BOTH);
// AlGpio_Hal_IntrPinCfg(GPIO, PS_KEY1, GPIO_INTR_TYPE_EDGE_RISING);
AlSys_MDelay(5000);
#else
AlGpio_Hal_IntrBankCfg(GPIO, AL_GPIO_BANK2, BANK_INTR_VALUE, BANK_TYPE_REG, BANK_POLARUTY_REG, BANK_BOTHEDGE_REG);
#endif
AlIntr_SetLocalInterrupt(AL_FUNC_ENABLE);
while(1);
return AL_OK;
}
AL_S32 main(void) {
AL_LOG(AL_LOG_LEVEL_INFO, "[TEST]AlGpio_Hal_Test start");
AlGpio_Hal_Intr_Example();
return AL_OK;
}
7.1 GPIO位号定义
#define PL_KEY1 54
#define PL_KEY2 55
#define PS_KEY1 50
经过上节课的学习,该部分想必已经掌握,不再赘述。
7.2 中断处理方法
于上节课相同,同样是采用的两种方法来触发中断,与上节课不同的是两种方法不能同时使用,通过#define定义来调整。当你需要使用哪种中断方式时,注销掉另一种即可。注:修改完成后,需要重新编译。
//#define BANK_INTR
#define PIN_INTR
方法一:直接通过Bank控制中断,代码如下:
AlGpio_Hal_IntrBankCfg(GPIO,AL_GPIO_BANK2, BANK_INTR_VALUE, BANK_TYPE_REG, BANK_POLARUTY_REG, BANK_BOTHEDGE_REG);
此函数功能为配置 bank 的中断,包括方向、类型和使能寄存器。这里我们使能两个GPIO PL作为中断。
同时我们需要了解3个宏定义分别是
typedef enum
{
GPIO_INTR_LEVEL = 0x0,
GPIO_INTR_EDGE = 0x1,
}
AL_GPIO_IntrTypeEnum;
typedef enum
{
GPIO_INTR_LOW = 0x0,
GPIO_INTR_HIGH = 0x1,
}
AL_GPIO_IntrPolarityEnum;
typedef enum
{
GPIO_INTR_Single = 0x0,
GPIO_INTR_Both = 0x1,
}
AL_GPIO_IntrBothEdgeEnum;
依次对应的是AlGpio_Hal_IntrBankCfg函数中的BANK_TYPE_REG、 BANK_POLARUTY_REG、 BANK_BOTHEDGE_REG,而我们程序中的定义是
#define BANK_TYPE_REG 0x3
#define BANK_POLARUTY_REG 0x0
#define BANK_BOTHEDGE_REG 0x0
综上,我们该函数设定的含义是GPIO Bank2中的0x3使能作为中断,类型为:边缘触发、低电平触发、每次触发1次。稍后我们可以验证一下是否跟我们的预期一致。
方法二:通过位号控制中断,代码如下:
AlGpio_Hal_IntrPinCfg(GPIO, PL_KEY1, GPIO_INTR_TYPE_EDGE_FALLING);
AlGpio_Hal_IntrPinCfg(GPIO, PL_KEY2, GPIO_INTR_TYPE_EDGE_BOTH);
// AlGpio_Hal_IntrPinCfg(GPIO, PS_KEY1, GPIO_INTR_TYPE_EDGE_RISING);
AlSys_MDelay(5000);
根据原理图,当PL KEY按下后为低电平,所以我们设置两个按键为低电平触发以及高低电平触发。也就是PL_KEY1按下后松开,触发1次中断,PL_KEY2按下后松开,触发2次中断,PS_KEY1按下时,触发1次中断。(经过测试发现如果PS KEY与PL KEY混用的情况下,会出现反馈0x0的情况)
8 方案演示
8.1 硬件准备
本实验需要用到JTAG下载器、USB转串口外设,另外需要把SW1模式开关设置到JTAG模式
8.2 实验结果
由于添加了PL端按键资源,所以Debug时需要将TD生成的soc_prj/soc_prj_Runs/best_result/soc_prj.bit文件同时添加进来,在debug前会先下载PL端资源后启动SOC部分。
BANK_INTR:
每次KEY1和KEY2按键按下的时候,均会产生1个中断
PIN_INTR:
每次KEY1按键按下的时候,会产生1个中断,KEY2按键按下的时候,会产生2个中断