|
大家好,我是痞子衡,是正经搞技术的痞子。今天痞子衡给大家介绍的是SDK2.0里事务型中断处理函数(DriverIRQHandler)的重定向注意事项。
最近有一个 i.MXRT 客户在使用官方 SDK 外设驱动里的中断处理函数时遇到了代码重定向失效问题,客户用得是一个 XIP Flash 工程,想把程序中断向量表以及相关外设的驱动函数全部重定向到 RAM 中以提高系统性能,但实测发现中断发生时,仍然存在 Flash 访问行为。这本来不是个大问题,因为 SDK 在设计时已经从中断处理函数命名上就做了明确提醒,但是很多客户并没有意识到,今天痞子衡就来聊聊这个话题:
一、事务型驱动函数简介恩智浦 SDK 软件包里的外设驱动(HAL级)正常来说提供的 API 都是面对外设配置(init、deinit、set_feature、get_status) 的通用功能函数。此外对于通信接口类外设,一般还会有阻塞式(blocking)的数据传输功能函数。以 LPUART 外设为例,其数据传输有以下四个 API:
// 写入(发送)一个 Byte 数据(需在 FIFO 没满的情况下)
static inline void LPUART_WriteByte(LPUART_Type *base, uint8_t data);
// 读取(接收)一个 Byte 数据(需在 FIFO 非空的情况下)
static inline uint8_t LPUART_ReadByte(LPUART_Type *base);
// 阻塞式写入(发送)多个 Byte 数据
status_t LPUART_WriteBlocking(LPUART_Type *base, const uint8_t *data, size_t length);
// 阻塞式读取(接收)多个 Byte 数据
status_t LPUART_ReadBlocking(LPUART_Type *base, uint8_t *data, size_t length);
阻塞式数据传输 API 本质上就是独占 CPU 时间进行查询式传输,API 一旦调用,必须等到数据收发结束才会返回,这样会导致 CPU 利用率不高,其一般不利用外设中断。为了结合外设中断进行高效数据传输(non-blocking),SDK2.0 中额外提供了如下事务型相关函数(仅列出了部分):
// 创建事务型数据传输句柄
void LPUART_TransferCreateHandle(LPUART_Type *base,
lpuart_handle_t *handle,
lpuart_transfer_callback_t callback,
void *userData);
// 非阻塞式写入(发送)多个 Byte 数据
status_t LPUART_TransferSendNonBlocking(LPUART_Type *base, lpuart_handle_t *handle, lpuart_transfer_t *xfer)
// 非阻塞式读取(接收)多个 Byte 数据
status_t LPUART_TransferReceiveNonBlocking(LPUART_Type *base,
lpuart_handle_t *handle,
lpuart_transfer_t *xfer,
size_t *receivedBytes);
// 事务型数据传输中断处理函数
void LPUART_TransferHandleIRQ(LPUART_Type *base, void *irqHandle);
非阻塞式数据传输 API 显然就是结合了外设中断来做数据传输,API 调用后填入一些配置后会立刻返回,没有过多消耗 CPU 时间,等外设中断发生时再进一步处理数据。这类型 API 常常和应用设计紧相关,所以也称为事务型函数(transactional API)。
SDK 里并不是所有外设驱动里包含事务性函数,这类 API 常出现在传输接口类外设上。对于 i.MXRT 来说,支持此类 API 的外设有:DMA、LPUART、LPSPI、LPI2C、SAI、FLEXIO、FLEXSPI、USDHC、ENET、CAN、MIPI_DSI/CSI、SPDIF、ASRC、PDM 等。
二、事务型中断处理函数设计这里继续以 LPUART 外设来具体介绍。如下 i.MXRT1011 SDK 里提供的 8 个 LPUART 例程中有 5 个是基于事务型驱动函数的,我们就以 interrupt_transfer 的 IAR 工程为例。 |
|