2016-04-15 88 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將值發送給接收任務。