简体   繁体   English

在事件驱动的嵌入式系统中使用事件队列避免竞争条件

[英]Avoiding Race Condition with event queue in event driven embedded system

I am trying to program stm32 and use event driven architecture.我正在尝试对 stm32 进行编程并使用事件驱动架构。 For example I am going to toggle a pin when timer interrupt occurs and transfer some data to external flash when ADC DMA buffer full interrupt occurs and so on..例如,当发生定时器中断时,我将切换一个引脚,并在发生 ADC DMA 缓冲区完全中断时将一些数据传输到外部 flash 等等。

There will be multiple interrupt sources each with same priority which disables nesting.将有多个中断源,每个中断源具有相同的优先级,从而禁用嵌套。

I will use the interrupts to set a flag to signal my main that interrupt occured and process data inside main.我将使用中断来设置一个标志来通知我的 main 发生了中断并在 main 中处理数据。 There will be no processing/instruction inside ISRs. ISR 内部不会有处理/指令。

What bothers me is that accessing a variable(flags in this case) in main and ISRs may cause race condition bug in the long run.困扰我的是,从长远来看,在 main 和 ISR 中访问变量(在这种情况下为标志)可能会导致竞争条件错误。

So I want to use an circular event queue instead of flags.所以我想使用循环事件队列而不是标志。

Only ISRs will be able to write to event queue buffer and increment "head".只有 ISR 能够写入事件队列缓冲区并增加“head”。 Only main will be able to read the event queue(and execute instructions according to event) and increment "tail".只有 main 能够读取事件队列(并根据事件执行指令)并增加“tail”。

Since ISR nesting is disabled and each ISR will access different element of event queue array and main function will only react when there is new event on event queue, race condition is avoided right?由于 ISR 嵌套被禁用,每个 ISR 将访问事件队列数组的不同元素,主 function 只会在事件队列上有新事件时做出反应,避免竞争条件对吧? or am I missing something?还是我错过了什么?

Please correct me if I am doing something wrong.如果我做错了什么,请纠正我。

Thank you.谢谢你。

If the interrupt only sets a variable and nothing gets done until main context is ready to do it then there is really no reason to have an interrupt at all.如果中断只设置了一个变量,并且在主上下文准备好之前什么都不做,那么根本就没有理由产生中断。

For example: if you get a DMA complete hardware interrupt and set a variable then all you have achieved is to copy one bit of information from a hardware register to a variable.例如:如果你得到一个 DMA 完整的硬件中断并设置了一个变量,那么你所做的就是将一位信息从硬件寄存器复制到一个变量中。 You could have much simpler code with identical performance and less potential for error by instead of polling a variable just not enabling the interrupt and polling the hardware flag directly.通过轮询变量而不是不启用中断并直接轮询硬件标志,您可以拥有更简单的代码,具有相同的性能和更少的错误可能性。

Only enable the interrupt if you are actually going to do something in interrupt context that cannot wait, for example: reading a UART received data register so that the next character received doesn't overflow the buffer.仅当您实际上要在无法等待的中断上下文中执行某些操作时才启用中断,例如:读取 UART 接收到的数据寄存器,以便接收到的下一个字符不会溢出缓冲区。

If after the interrupt has done the thing that cannot wait it then needs to communicate something with main-context then you need to have shared data.如果在中断完成后不能等待的事情然后需要与主上下文进行通信,那么您需要共享数据。 This will mean that you need some way of preventing race-conditions.这意味着您需要某种方法来防止竞争条件。 The simplest way is atomic access with only one side writing to the data item.最简单的方法是原子访问,只有一侧写入数据项。 If that is not sufficient then the old-fashioned way is to turn off interrupts when main context is accessing the shared data.如果这还不够,那么老式的方法是在主上下文访问共享数据时关闭中断。 There are more complicated ways using LDREX/STREX instructions but you should only explore these once you are sure that the simple way isn't good enough for your application.使用 LDREX/STREX 指令有更复杂的方法,但只有在确定简单方法对您的应用程序不够好时,您才应该探索这些方法。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM