1、中断概念
程序运行过程中,系统外部、系统内部或者现行程序本身若出现紧急事件,CPU暂停当前程序的运行,自动转入预先设定好的的中断服务程序,处理完后,再返回原来的程序继续运行,这整个过程称为中断。
按照中断是否可以屏蔽进行分类,中断可分为可屏蔽中断和不屏蔽中断两类。可由程序控制是否发出中断信号的中断称为可屏蔽中断。中断被屏蔽时,CPU将不接收此中断。反之,对于不能由程序控制其屏蔽状态的中断,只要产生该中断,CPU就一定要立即处理的中断称为不可屏蔽中断。不可屏蔽中断主要用于断电、电源故障等必须立即处理的情况。
按照发出中断信号源头进行分类,中断又分为硬件中断和软件中断。 硬件中断是实际硬件需要通知CPU进行特殊事件处理时候发出的信号,Timer、UART、GPIO等硬件均可以发出硬件中断;而软件中断是由软件(一条CPU指令)触发的一个信号,在各种操作系统中,系统调用的实现一般是通过触发软件中断的方式实现的。
中断的用途很多,系统的时钟tick则是以Timer中断为基准进行计算的;也可以设置UART的配置,使其在接收数据时硬件缓存的数据量到达一定的门限值之后发出中断;CPU外部模块的中断一般是通过连接到CPU上具有中断功能的IO口进行中断事件上报的。
接下来主要以HaaS EDK中的GPIO中断为例进行介绍。
2、中断相关API
API名称 |
功能 |
hal_gpio_enable_irq |
使能指定GPIO的中断模式,挂载中断服务函数 |
hal_gpio_disable_irq |
清除指定GPIO的中断状态 |
hal_gpio_clear_irq |
清除指定GPIO的中断状态 |
在掉用hal_gpio_xxx_irq对指定GPIO 对应的中断进行操作之前需要先呼叫hal_gpio_init将该GPIO设置为中断模式(IRQ_MODE)。
2.1、hal_gpio_enable_irq
使能指定GPIO的中断模式,挂载中断服务函数。
- 函数原型及参数说明
int32_t hal_gpio_enable_irq(gpio_dev_t *gpio, gpio_irq_trigger_t trigger,gpio_irq_handler_t handler, void *arg)
API名称 |
功能 |
gpio |
GPIO设备描述 |
trigger |
中断的触发模式,上升沿、下降沿还是都触发 |
handler |
中断服务函数指针,中断触发后将执行指向的函数 |
arg |
中断服务函数的入参 |
- 返回值
类型:int 返回成功或失败, 返回0使能中断成功,非0表示失败。
2.2、hal_gpio_disable_irq
关闭指定GPIO的中断
- 函数原型及参数说明
int32_t hal_gpio_disable_irq(gpio_dev_t *gpio)
API名称 |
功能 |
gpio |
GPIO设备描述 |
- 返回值
类型:int 返回成功或失败, 返回0表示中断去使能成功,非0表示失败。
2.3、hal_gpio_clear_irq
清除指定GPIO的中断
- 函数原型及参数说明
int32_t hal_gpio_clear_irq(gpio_dev_t *gpio)
API名称 |
功能 |
gpio |
GPIO设备描述 |
- 返回值
类型:int 返回成功或失败, 返回0表示中断去使能成功,非0表示失败。
3、中断实验
将HaaS EDK上面的K1按键设置为中断模式,在按下按键的之后的150ms内检测到按下的动作,并打印“k1 is pressed”日志。
3.1、硬件
其中KEY1直接连接到了CPU的P2_7上,程序代码中的ID宏定义为:HAL_IOMUX_PIN_P2_7
3.2、软件实现
#include <aos/hal/gpio.h>
#define EDK_BOARD_KEY1 HAL_IOMUX_PIN_P2_7
/* define dev */
gpio_dev_t k1;
/* pressed flag */
/* K1按键按下的标志位 */
int k1_pressed = 0;
/* 中断处理程序中将k1_pressed设置为1,代表检测到K1按下的事件 */
void k1_handler(void *arg)
{
k1_pressed = 1;
}
int application_start(int argc, char *argv[])
{
int ret = -1;
/* IRQ pin config */
/* 中断GPIO配置 */
k1.port = EDK_BOARD_KEY1;
/* set as interrupt mode */
/* 设置为中断模式 */
k1.config = IRQ_MODE;
/* configure GPIO with the given settings */
/* 呼叫hal_gpio_init对K1进行初始化 */
ret = hal_gpio_init(&k1);
if (ret != 0) {
printf("k1 init error !\n");
}
/* enable interrupt on K1 */
/* 开启K1对应的中断 */
ret = hal_gpio_enable_irq(&k1, IRQ_TRIGGER_BOTH_EDGES,
k1_handler, NULL);
if (ret != 0) {
printf("gpio irq enable error !\n");
}
/* if k1 is pressed, print "k1 is pressed !" */
/* 检测到k1_pressed标志位1, 打印 "k1 is pressed !" */
while(1) {
if (k1_pressed == 1) {
k1_pressed = 0;
printf("k1 is pressed !\n");
}
/* sleep 100ms, must be shorter than 150ms according to experiment's target */
/* 休眠100ms, 必须要短于150ms,确保在k1_pressed在中断处理程序中被设置成1后能够在150ms内检测到此K1被按下的事件 */
aos_msleep(100);
};
}
此程序运行之后,当按键K1被按下后,串口会打印"k1 is pressed !"
开发者技术支持
如需更多技术支持,可加入钉钉开发者群,或者关注微信公众号
更多技术与解决方案介绍,请访问阿里云AIoT首页https://iot.aliyun.com/