我有一个难题。我正在使用的部件(NXP KL27,Cortex-M0 +)在其I2C外设中有勘误表,因此在接收期间没有流量控制。结果,它必须是高优先级的中断。我还使用了一个UART,由于它的异步特性,它在接收时没有流控制。因此,它必须是高优先级的中断。
循环优先级
I2C中断的优先级必须高于UART中断的优先级,否则输入字节可以在读取之前在移位寄存器中删除。确实不应该这样,但这就是勘误表,因此它需要具有更高的优先级。
UART中断必须具有比I2C中断更高的优先级,因为要关闭I2C事务,驱动程序(来自NXP的KSDK)需要设置一个标志并等待状态位。在此等待期间,UART上的传入字符可能会使非FIFO移位寄存器溢出。
在尝试解决UART问题时,我发现了这种循环依赖性。最初的问题是字符从UART接收中消失,并且设置了溢出标志。交换优先级时,UART坚如磐石,从未丢失任何字符,但是I2C事务由于超限而最终停滞了。
可能的解决方案
我想出的解决方案涉及动态更改中断优先级。当I2C驱动程序关闭事务时,它没有接收到数据,这意味着导致字节流入不受控制的勘误不是问题。我想在这段时间内降级NVIC中的I2C中断优先级,以便UART能够优先于它,从而使UART开心(并且不丢失任何字符)。
问题
我无法从ARM那里找到任何信息来说明执行该中断时更改中断优先级是否会立即生效,或者当前中断的优先级在开始执行时是否已锁定。我希望有人可以绝对地从他们对体系结构的了解或经验中省去,改变优先级将立即生效,或者不会立即生效。
其他可能的解决方案
还有许多其他可能的解决方案,以及为什么不受欢迎的原因。重构I2C驱动程序以在流程上下文而不是中断上下文中处理循环,这将是挖掘供应商代码并影响调用该代码的应用程序代码的巨大努力。将DMA用于这些外设中的任何一个都会占用大量可用的DMA通道,并且会增加为每个事务设置DMA的开销(并且还会影响调用驱动程序的应用程序代码)。
我对其他解决方案持开放态度,但不愿采用任何会导致对供应商代码进行重大更改的方法。
测试
我有一个实验想法,可以测试NVIC在这方面的工作方式,但我想我会先在这里进行检查。如果我要进行实验,我将在结果中发布后续答案。
答案 0 :(得分:1)
在架构上,这似乎是不可预料的(更改当前活动异常的优先级)。似乎没有适当的逻辑来强制执行更一致的行为(即,您关注的注册逻辑显然没有出现在M0 / M0 +中)。
这意味着,如果您测试解决方法的有效性,那么它似乎可能会起作用-在受限的情况下,它可能会有效。但是,不能保证相同的代码可以在M3上运行,也不能保证在所有情况下都能可靠地运行(例如与调试的任何交互)。您甚至可能会观察到一些完全无法预测的极端情况,但是面积受限
在ARM v6-M ARM的B1.5.4节中将其指定为不可预测。
对于v7-M(B1.5.4,异常优先级和抢占)
此执行优先级的定义意味着异常处理程序 可以以高于优先级的优先级执行 相应的例外。特别是如果处理程序减少了 相应异常的优先级,执行优先级下降 仅优先于最高优先级的抢占式例外。 因此,永远不要降低当前异常的优先级 许可:
抢先的异常,用于抢占当前的异常处理程序。
抢占式例外的优先级倒置。
v7-M方面阐明了一些复杂的情况,如果您尝试利用已确定对M0 +部件有用的不可预测的行为,则必须避免这种情况。
答案 1 :(得分:0)
实验
我今天编写了一个快速实验,以在我的特定Cortex M0 +变体上测试此行为。我将其作为一个无法接受的答案,我相信@Sean Houlihane的答案是最正确的(即,这是不可预测的)。我仍然想测试一下行为,并在使用过程中在特定情况下进行报告。
实验在FRDM-KL43Z板上进行。它具有一个红色LED,一个绿色LED和两个按钮。该应用程序执行了一些GPIO设置和中断,然后陷入无限循环。
按钮1:按钮1的中断处理程序已初始化为中等优先级(0x80)。在按钮1的每个下降沿,它将中断中断。此中断将切换绿色LED的状态。
按钮2:按钮2的中断处理程序已初始化为中等优先级(0x80),但将在执行过程中进行更改。按钮2中断处理程序将运行一个循环,持续大约8秒(两个阶段,共四个阶段),并无限期重复。它将打开红色LED并将其自身的优先级降低到低于按钮1的优先级。四秒钟后,它将关闭红色LED并将其自身的优先级提高到高于按钮1的优先级。四秒钟后,将重复该操作。 >
预期结果
如果假设成立,则红色LED亮起时,按按钮1将切换绿色LED;而在红色LED熄灭时,按按钮1将不起作用,直到红色LED熄灭为止。直到永远循环播放按钮2中断的优先级较低时,按钮1中断才会执行。
结果
这是无聊的部分。我在上一节中期望的所有事情都发生了。
结论
对于实验设置(NXP KL43Z Cortex M0 +),在中断运行时更改当前正在执行的中断的中断优先级会生效。结果,我在忙碌的等待期间降级优先级并在之后恢复优先级的巧妙解决方法应该可以满足我的需求。
编辑: 最新结果
尽管实验成功,但是一旦实施了原始问题的解决方法,问题便开始出现。 UART和I2C处理程序之间的交互相对一致,但是第三个外设在其中断处理程序中开始表现出非常奇怪的行为。请注意不可预测的警告。
答案 2 :(得分:0)
一个替代解决方案可能是在处理的后半部分延迟另一个较低优先级的中断。一个不错的选择是PendSV中断(如果尚未使用),可以(仅)从软件触发该事件。
有关更详细的说明,请参见类似问题的this answer和有关PendSV的this answer。