痞子衡嵌入式:关于恩智浦SDK2.0里事务型中断处理函数(DriverIRQHandler)的重定向注意事项
大家好,我是痞子衡,是正经搞技术的痞子。今天痞子衡给大家介绍的是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 工程为例。
打开这个 lpuart_interrupt_transfer 工程,找到芯片启动文件 startup_MIMXRT1011.s,在里面我们能找到 PUBWEAK 型的 LPUART1_IRQHandler() 函数定义,这个是大家比较常见的中断处理函数名,其代码里面就是简单跳转到另一个 PUBWEAK 型 LPUART1_DriverIRQHandler 函数。
在 fsl_lpuart.c/.h 驱动里,找不到 LPUART1_IRQHandler() 定义,但是有 LPUART1_DriverIRQHandler() 定义。这意味着 SDK 驱动设计时,将默认的 LPUART1_IRQHandler() 函数重写的权利留给了用户,而重新设计了 LPUART1_DriverIRQHandler() 函数来存放事务性中断处理代码,从而避免因用户自己重写中断处理函数时发生函数名重定义而去修改 fsl_lpuart.c 驱动文件的麻烦。
三、重定向事务型中断处理函数
现在我们尝试重定向 lpuart_interrupt_transfer 工程,可以按照 《IAR下代码重定向的三种方法》 一文里的方法,将 fsl_lpuart.o 和 lpuart_interrupt_transfer.o 两个目标文件都重定向到 RAM 中,并且在 main 里加上拷贝 0x60002000 处开始的 1KB 中断向量表数据到 SRAM 中并且将 SCB->VTOR 指向对应 SRAM 的代码(这个过程可以参考 《Cortex-M中断向量表重定向方法》 一文)。
上述改动完成之后,编译工程查看 map 文件,我们发现所有的相关代码都已经被链接在了 SRAM 里,但是 LPUART1_IRQHandler() 仍然在 Flash 里,很显然这种情况下中断发生时,仍然会有 Flash 访问行为(暂不考虑 L1-Cache 生效的情况),这就是客户遇到的问题。
那么如何解决这个问题?其实 SDK 已经为你考虑到了,在 fsl_common_arm.c 文件中定义了 InstallIRQHandler() 函数(仅在 ENABLE_RAM_VECTOR_TABLE 宏存在的情况下生效),查看其源码,发现作用有两个:一、如果 SCB->VTOR 指向得不是 SRAM,那么将中断向量表从 Flash 拷贝到 SRAM 中,并且重置 VTOR;二、根据传入参数修改 SRAM 中的某个中断向量值。
因此 lpuart_interrupt_transfer 例程中,如果需要彻底重定向中断处理函数,记得在 main 函数里的 LPUART_TransferCreateHandle() 函数调用之后加上如下一句代码,其作用除了重定向中断向量表之外,还将表里的 LPUART1 中断向量从 LPUART1_IRQHandler() 更换为了 LPUART1_DriverIRQHandler(),这样代码重定向就彻底了。
InstallIRQHandler(LPUART1_IRQn, (uint32_t)LPUART1_DriverIRQHandler);
此时再编译工程下载运行,发现出现 hardfault,这是怎么回事?别急,因为 InstallIRQHandler() 函数里需要用到链接文件 MIMXRT1011xxxxx_flexspi_nor.icf 里定义的三个 Symbol,工程选项 Linker/Configuration file symbol 里必须添加 __ram_vector_table__=1 设置,那些 Symbol 才会真正产生重定向作用。
define symbol __ram_vector_table_size__ = isdefinedsymbol(__ram_vector_table__) ? 0x00000400 : 0;
define exported symbol __VECTOR_TABLE = m_interrupts_start;
define exported symbol __VECTOR_RAM = isdefinedsymbol(__ram_vector_table__) ? m_interrupts_ram_start : m_interrupts_start;
define exported symbol __RAM_VECTOR_TABLE_SIZE = __ram_vector_table_size__;
至此,SDK2.0里事务型中断处理函数(DriverIRQHandler)的重定向注意事项痞子衡便介绍完毕了,掌声在哪里~~~
欢迎订阅
文章会同时发布到我的 博客园主页、CSDN主页、知乎主页、微信公众号 平台上。
微信搜索"痞子衡嵌入式"或者扫描下面二维码,就可以在手机上第一时间看了哦。

痞子衡嵌入式:关于恩智浦SDK2.0里事务型中断处理函数(DriverIRQHandler)的重定向注意事项的更多相关文章
- 痞子衡嵌入式:恩智浦i.MX RT1xxx系列MCU启动那些事(11.0)- FlexSPI NOR启动时间(RT1170)
大家好,我是痞子衡,是正经搞技术的痞子.今天痞子衡给大家介绍的是恩智浦i.MX RT1170 FlexSPI NOR启动时间. 痞子衡刚刚拿到i.MXRT1170 B0版本的芯片,迫不及待地在上面跑了 ...
- 痞子衡嵌入式:恩智浦MCU安全加密启动一站式工具NXP-MCUBootUtility用户指南
NXP MCU Boot Utility English | 中文 1 软件概览 1.1 介绍 NXP-MCUBootUtility是一个专为NXP MCU安全加密启动而设计的工具,其特性与NXP M ...
- 痞子衡嵌入式:恩智浦i.MX RTxxx系列MCU特性介绍(2)- RT685EVKA性能实测(Dhrystone)
大家好,我是痞子衡,是正经搞技术的痞子.今天痞子衡给大家介绍的是恩智浦i.MX RTxxx系列MCU的性能. 在前面的文章 i.MXRTxxx微控制器概览 里,痞子衡给大家简介过恩智浦半导体在2018 ...
- 痞子衡嵌入式:恩智浦i.MX RTxxx系列MCU启动那些事(3)- Serial ISP模式(blhost)
大家好,我是痞子衡,是正经搞技术的痞子.今天痞子衡给大家介绍的是恩智浦i.MX RTxxx系列MCU的Serial ISP模式. 在上一篇文章 Boot配置(ISP Pin, OTP) 里痞子衡为大家 ...
- 痞子衡嵌入式:恩智浦i.MX RTxxx系列MCU启动那些事(4)- OTP及其烧写方法
大家好,我是痞子衡,是正经搞技术的痞子.今天痞子衡给大家介绍的是恩智浦i.MX RTxxx系列MCU的OTP. 在i.MXRTxxx启动系列第二篇文章 Boot配置(ISP Pin, OTP) 里痞子 ...
- 痞子衡嵌入式:恩智浦i.MX RTxxx系列MCU启动那些事(8)- 从Serial(1-bit SPI) NOR恢复启动
大家好,我是痞子衡,是正经搞技术的痞子.今天痞子衡给大家介绍的是恩智浦i.MX RTxxx系列MCU的1-bit SPI NOR恢复启动. 在前几篇里痞子衡介绍的Boot Device都属于主动启动的 ...
- 痞子衡嵌入式:恩智浦SDK驱动代码风格、模板、检查工具
大家好,我是痞子衡,是正经搞技术的痞子.今天痞子衡给大家讲的是恩智浦 SDK 驱动的代码风格. 上周痞子衡受领导指示,给 SE 同事做了一个关于 SDK 代码风格的分享.随着组内新人的增多,这样的培训 ...
- 痞子衡嵌入式:恩智浦i.MX RT1xxx系列MCU启动那些事(13.A)- LPSPI NOR启动时间(RT1170)
大家好,我是痞子衡,是正经搞技术的痞子.今天痞子衡给大家介绍的是恩智浦i.MX RT1170 1bit SPI NOR恢复启动时间. 本篇是i.MXRT1170启动时间评测第三弹了,前两篇分别给大家评 ...
- 痞子衡嵌入式:恩智浦i.MX RT1xxx系列MCU硬件那些事(2.4)- 串行NOR Flash下载算法(Keil MDK工具篇)
大家好,我是痞子衡,是正经搞技术的痞子.今天痞子衡给大家介绍的是Keil MDK工具下i.MXRT的串行NOR Flash下载算法设计. 在i.MXRT硬件那些事系列之<在串行NOR Flash ...
- 痞子衡嵌入式:恩智浦i.MX RT1xxx系列MCU硬件那些事(2.5)- 串行NOR Flash下载算法(IAR EWARM篇)
大家好,我是痞子衡,是正经搞技术的痞子.今天痞子衡给大家介绍的是IAR开发环境下i.MXRT的串行NOR Flash下载算法设计. 在i.MXRT硬件那些事系列之<在串行NOR Flash XI ...
随机推荐
- Elsa V3学习之Hello Word
前面文章介绍了Elsa的基础节点内容,接下来我们来开始实践一下. 启动项目 启动源码目录src\bundles中的Elsa.ServerAndStudio.Web的项目.这个项目包含Elsa Serv ...
- AI驱动的PlantUML:快速生成专业级UML图表
**对于程序员来说,编写验收文档中的各种UML图是最让人头疼的事情之一,相信各位读者对此深有体会.** 本文将探讨如何利用AI驱动的PlantUML来快速生成专业级别的UML图表,从而减轻这一负担. ...
- docker高级篇-docker-compose容器编排介绍及实战
Docker-compose是什么?能干嘛?解决了哪些痛点? 是什么? Docker-compose是Docker官方推出 的一个工具软件,可以管理多个Docker容器组成的一个应用.你需要编写一个一 ...
- 肉夹馍(Rougamo)4.0.1 异步方法变量调试修复与IoC系列扩展
肉夹馍(https://github.com/inversionhourglass/Rougamo),一款编译时AOP组件,无需在应用启动时进行初始化,也无需繁琐的配置:支持所有种类方法(同步和异步. ...
- 移动端Android跟ios兼容性问题,反人类!!!
一.查询参数编码问题 我们在日常开发中,有时候会遇到拼接参数特别多的情况,那么就会导致一行代码特别长.那么为了美观呢,有的同学会进行换行处理,如下代码: 可以看到我红色框出来的地方就是经过了手动的回车 ...
- 【YashanDB知识库】YMP元数据阶段二报错YAS-04204
[问题分类]YMP迁移 [关键字]YMP迁移,YAS-04204 [问题描述]数据库采用最小规格部署,机器配置2C8G,使用YMP进行数据和对象迁移,在元数据阶段二创建索引时报错:YAS-04204 ...
- 面试官:limit 100w,10为什么慢?如何优化?
在 MySQL 中,limit X,Y 的查询中,X 值越大,那么查询速度也就越慢,例如以下示例: limit 0,10:查询时间大概在 20 毫秒左右. limit 1000000,10:查询时间可 ...
- Git Bash OpenSSL – Generate Self Signed Certificate
前言 以前就写过了, 只是写的太乱, 这篇是一个整理版. 以前的文章: Git Bash 创建证书 PowerShell 创建证书 我已经没有用 PowerSheel 做证书了, 所以就不介绍了. 参 ...
- Shiro-550—漏洞分析(CVE-2016-4437)
目录 漏洞原理 源码分析 加密过程 解密过程 漏洞复现 漏洞原理 Shiro-550(CVE-2016-4437)反序列化漏洞 在调试cookie加密过程的时候发现开发者将AES-CBC用来加密的密钥 ...
- 反DDD模式之“复用”
本文书接上回<反DDD模式之关系型数据库>,关注公众号(老肖想当外语大佬)获取信息: 最新文章更新: DDD框架源码(.NET.Java双平台): 加群畅聊,建模分析.技术实现交流: 视频 ...