我正在使用stm32f4xx uC的C中的嵌入式项目。
我有一部分代码连续执行循环操作XYZ,并且TIM4中断有时会更改某些全局参数并导致操作XYZ重新启动。
代码是这样的:
for (;;) {
//line A
XYZ;
//line B
}
XYZ是一项涉及缓冲区与其他数据之间传输数据的复杂操作。
TIM4中断处理程序执行此操作:停止XYZ&改变一些影响XYZ操作的全局变量。
基本上我希望XYZ重复执行,TIM4中断停止XYZ,更改参数和然后必须通过使用新的全局参数重新启动XYZ来重启循环。
问题是:由于XYZ有很多指令,TIM4 IRQ可能就在它的中间,在IRQHandler更改全局变量之后,操作从XYZ中间恢复,这会破坏程序
MY INITIAL SOLUTION:使用__disable_irq()禁用A行上的中断,并使用__enable_irq()
在B行恢复它们失败,因为XYZ复杂操作必须使用其他中断(TIM4除外)。
NEXT SOLUTION 仅在A行禁用TIM4中断:
TIM_ITConfig(TIM4, TIM_IT_Update , DISABLE)
并使用以下命令将其启用回B行:
TIM_ITConfig(TIM4, TIM_IT_Update , ENABLE)
失败因为我正在丢失中断:当int恢复时,忽略在XYZ期间到达的中断。这是一个很大的问题(其中一个原因是TIM4 IRQHandler更改全局变量然后再次激活TIM4以产生中断,我这样做是因为中断之间的时间间隔不同)。
有人能帮我解决这个问题吗?有没有更好的方法来禁用/恢复TIM4 IRQ和不丢失任何中断?
答案 0 :(得分:1)
完成XYZ后,您可以操作全局变量的副本并从中断交换新值。
从问题中不清楚是否需要在全局变化时立即停止处理XYZ,或者是否可以等到XYZ完成处理以交换变量的新副本。我会假设你需要打破XYZ的处理,但很容易就不行。
代码看起来像这样:
volatile int x;
int x_prime;
int main(void)
{
while(1)
{
//copy in new global parameter value
x_prime = x;
while(1)
{
//do stuff with x_prime
if (x_prime != x)
{
break;
}
//do more stuff with x_prime
if (x_prime != x)
{
break;
}
}
}
}
// interrupt handler
void TIM_IT_Update(void)
{
x++;
}
break
模式假设您没有更改x_prime
。如果您需要修改x_prime
,则需要另一份副本。
由于永远不会禁用中断,因此您永远不必担心丢失任何中断。并且由于您正在操作中断更改的参数副本,因此中断在执行过程中更改参数并不重要,因为在您复制之前不会查看这些值。
答案 1 :(得分:1)
有一些可能的选项(我不是100%在ARM架构上):
答案 2 :(得分:1)
当我发现自己处于类似情况时,处理可能需要比中断时间更长的时间,我使用FIFO将处理与传入数据分离。 I.E:TIM4填充FIFO。 XYZ(或管理器)使用FIFO并处理数据。
(我觉得你的设计可能是错的,因为你不应该使用全局变量来控制数据或流程。 关于此事的研究的书籍参考:制作嵌入式系统:伟大软件的设计模式)
答案 3 :(得分:0)
在XYZ从缓冲区复制所有内容并使用副本之前。我认为这是最好的方式,在编写gps解析器时有所帮助。
答案 4 :(得分:0)
您是否考虑过为您的系统使用 RTOS?我意识到这需要进行一些重组,但它可以为您提供系统所需的任务处理灵活性和分辨率。如果您使用的是 STM32 的 CubeIDE,那么启用、配置和运行 RTOS 非常简单。