ESP32-C3中断使用

中断系统

中断矩阵

ESP32-C3有62个外部中断©可映射到cpu的31个中断源,主要特性如下:

  • 允许62个中断输入
  • 输出31个中断到cpu
  • 查询当前外设中断状态
  • 可配置cpu中断源的优先级、类型、阈值和使能信号

Esp32-c3技术参考手册表8-1列出了所有的外部中断源。
在这里插入图片描述

中断映射

通过设置技术参考手册表8-1中的各个MAP寄存器可映射对应外设中断到31个cpu中断,可设置多个外设中断到同一个cpu中断,任何一个中断触发即可触发cpu中断,通过查询中断状态,确定中断来源。
清除MAP寄存器可取消中断映射。

CPU中断控制器

ESP32-C3采用中断控制器,并非ISA,cpu中断编号从1-31,每个中断都有下列特性:

  • 优先级从1(最低)-15(最高)
  • 可配置电平触发/边沿触发
  • 通过中断阈值可屏蔽低优先级中断

每个cpu中断有下列5个属性:

  • Enable State:0 == 使能
  • Type:1 == 边沿触发; 0 == 电平触发
  • Priority:优先级从1(最低)-15(最高),具有相同优先级的中断通过其ID确定优先级,最低ID具有最高优先级
  • Pending State:触发cpu中断后,该中断首先会被挂起,若没有更高优先级的挂起中断,则响应该中断,若有更高优先级中断处于挂起状态,则该中断排队等待。挂起且已响应中断服务程序称作”claimed”,挂起但未响应中断服务程序称作”unclaimed”.
  • Clear State:将INTERRUPT_CORE0_CPU_INT_CLEAR_REG寄存器相应bit先置1再置0,可清除挂起且已响应的中断。电平类型的中断无法通过该bit清除。如需清除挂起但未响应的中断,可先清除INTERRUPT_CORE0_CPU_INT_ENABLE_REG 寄存器相应bit,然后再清除状态bit。

关键函数说明

头文件

#include "hal/usb_serial_jtag_ll.h" //usb_serial外设驱动
#include "soc/periph_defs.h"//usb_serial外设相关定义
#include "esp_intr_alloc.h" 

分配中断

//分配中断
esp_err_t esp_intr_alloc(
			int source, //外部中断源,共计62个外部中断源
			int flags, //ESP_INTR_FLAG_LEVEL1~6: 1为最低优先级 6为最高优先级; ESP_INTR_FLAG_SHARED:共享中断; ESP_INTR_FLAG_EDGE:边沿触发中断 
			intr_handler_t handler, //中断句柄,当优先级大于3时为NULL,因为大于3级不能被C调用
			void *arg, //给中断服务程序传递的参数
			intr_handle_t *ret_handle)//指向中断句柄的指针,用于释放中断,不用为NULL

//释放中断
esp_err_t esp_intr_free(intr_handle_t handle);//传入中断句柄

示例程序

本示例程序为USB_Serial_JTAG外设分配一个中断,在中断服务程序中将主机发来的数据回传,注意由于硬件缓冲区只有64Byte,因此建议一次发送数据不要大于64Byte。
为提高中断响应速度,采用 IRAM_ATTR 属性将中断服务函数放置在内部RAM,避免频繁读取flash延迟影响程序执行效率。

#include <stdio.h>
#include "sdkconfig.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "esp_system.h"
#include "esp_spi_flash.h"
#include "string.h"

#include "hal/usb_serial_jtag_ll.h"
#include "soc/periph_defs.h"
#include "esp_intr_alloc.h"
//#include "esp_attr.h"


static void IRAM_ATTR usb_serial_jtag_isr_handler_default(void *arg) //采用IRAM_ATTR属性将该函数放置在内部RAM
{
    uint8_t  *rxbuf;
    uint32_t  usbjtag_intr_status = 0;
    rxbuf = (uint8_t *)malloc(64);
    usbjtag_intr_status = usb_serial_jtag_ll_get_intsts_mask();
    if (usbjtag_intr_status & USB_SERIAL_JTAG_INTR_SERIAL_OUT_RECV_PKT)
    {
        usb_serial_jtag_ll_clr_intsts_mask(USB_SERIAL_JTAG_INTR_SERIAL_OUT_RECV_PKT); //清除中断标志
        uint32_t  rx_fifo_len = usb_serial_jtag_ll_read_rxfifo(rxbuf, 64);
        usb_serial_jtag_ll_write_txfifo((const uint8_t *)rxbuf, rx_fifo_len); //将接收数据回环发送
        usb_serial_jtag_ll_txfifo_flush();                                    //刷新发送buf
    }
    free(rxbuf); //与malloc成对使用
}

void app_main(void)
{
    esp_err_t err = ESP_OK;
    intr_handle_t intr_handle;

    usb_serial_jtag_ll_clr_intsts_mask(USB_SERIAL_JTAG_INTR_SERIAL_OUT_RECV_PKT);
    usb_serial_jtag_ll_ena_intr_mask(USB_SERIAL_JTAG_INTR_SERIAL_OUT_RECV_PKT); //收到1包数据响应中断
    err = esp_intr_alloc(ETS_USB_SERIAL_JTAG_INTR_SOURCE, ESP_INTR_FLAG_LOWMED, usb_serial_jtag_isr_handler_default, NULL, &intr_handle);
    if (err != ESP_OK)
    {
        printf("error alloc intr\n");
    }
    while (1)
    {
        vTaskDelay(pdMS_TO_TICKS(5000));
    }
    esp_intr_free(intr_handle);
}

注意: 使用该功能前需要禁止控制台打印到USB,否则控制台打印信息会和usb打印信息混在一起,配置如下:
在这里插入图片描述

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值