2016-04-15 87 views
1

我应该什么时候使用freertos上的锁使用类似cortex-m3的东西?使用多核系统似乎很明显,但单核的情况如何?FreeRTOS锁和任务

例如我有两个任务。首先我增加名为counter的变量。第二个任务在发生某些事件时保存该变量的当前值。我应该在这里使用锁吗?可能第一个任务损坏了第二个任务正在保存的值?

+1

是的。中断。驱动程序。使用锁。 –

+0

@MartinJames:锁定在中断处理程序中?听起来不是一个好主意。 – Olaf

回答

2

是的,您应该使用锁来保护对共享资源的访问。

您不能确定编译器生成的读取共享变量的序列是否是原子序列,因此它可能不安全。

如果你想成为一个更硬核,可能获得性能,你可以使用各种方法来确保变量可以原子地访问。见评论。

+0

有'_Atomic'加'stdatomic.h'宏,这些类型保证无竞争原子。在嵌入式系统中'_Static_assert'使用的是原子类型,这是很好的。 – Olaf

+0

@Olaf所以我可以使用newlib中的'stdatomic.h'而不用任何技巧? –

+0

@LongSmith:'stdatomic.h'不是newlib的一部分,但通常是编译器。见标准。 – Olaf

1

您需要使用锁来对共享对象的并发访问同步,最简单的情形是这样的:

lock_t l; // defines a lock of your system 

// thread 1: 
lock(l); 
counter += 1; 
unlock(l); 


// thread 2: 
lock(l); 
do_something(counter); 
unlock(l); 
0

在您的具体实例,其中有一个阅读器和一个作家(所以没有在“一般”情况下,并且绝对不是在存在多个写入器的情况下),那么我会建议如果被写入/读取的变量是体系结构的自然字大小,则不需要锁定,并且如果变量不是自然字体系结构的大小。

在你的情况下,字的大小是32位,所以如果变量是uint32_t,那么它会自动更新,一个作者和多个读者是安全的。另一方面,如果变量是uint64_t,那么它将在两次单独的访问中被更新(写入),并且您必须确保读者不访问两次更新之间的变量,因为这样做会读取已损坏(一半更新)值。

在FreeRTOS中这样做的一个简单的方法是使用这样一个基本的关键部分:

taskENTER_CRITICAL(); 
My64BitVariable++; 
taskEXIT_CRITICAL(); 

最好的方法,虽然取决于事件的频率。如果事件“不太快”,那么为什么不使用queue将值从一个任务发送到另一个任务,在这种情况下,FreeRTOS负责为您处理所有并发问题。更好(更快,更少RAM),取决于接收任务在做什么,写作任务直接使用direct to task notification将值发送给接收任务。