Picproje Elektronik Sitesi

MİKRODENETLEYİCİLER => RTOS Uygulamaları => Konuyu başlatan: mr.engineer - 08 Mayıs 2020, 17:10:38

Başlık: Rtos task
Gönderen: mr.engineer - 08 Mayıs 2020, 17:10:38
Merhaba,
Aşağıda basit şekilde iki tane task oluşturup, (ikisi de aynı önceliğe sahip) çalıştırıyorum. İkisi de fonksiyonda yazılan stringleri uart ile bilgisayara yolluyor.

void vTask1( void *pvParameters )
{
const char *pcTaskName = "Task 1 is running\r\n";
volatile uint32_t ul; /* volatile to ensure ul is not optimized away. */
/* As per most tasks, this task is implemented in an infinite loop. */
for( ;; )
{
/* Print out the name of this task. */
HAL_UART_Transmit(&huart2, (uint8_t*)pcTaskName, sizeof(pcTaskName),100);
//HAL_UART_Transmit_IT(&huart2,(uint8_t*)pcTaskName, sizeof(pcTaskName));
/* Delay for a period. */
osDelay(100);
}
}


void vTask2( void *pvParameters )
{
const char *pcTaskName = "Task 2 is running\r\n";
volatile uint32_t ul; /* volatile to ensure ul is not optimized away. */
/* As per most tasks, this task is implemented in an infinite loop. */
for( ;; )
{
/* Print out the name of this task. */
HAL_UART_Transmit(&huart2, (uint8_t*)pcTaskName, sizeof(pcTaskName),100);
/* Delay for a period. */
osDelay(100);
}
}

Normalde şu şekilde bir output bekleniyor

Task 1 is running
Task 2 is running
Task 1 is running
Task 2 is running

Fakat bende çıkan sonuç şu:
TaskTaskTaskTaskTaskTaskTaskTask......

Benim anladığım iki task arasındaki geçişler çok hızlı ve bir stringi tamamen gönderemiyor. Yani her iki task da "Task" ile başladığından sadece ilk 4 karakter yani "Task" yollanıyor. Fakat anlamadığım şey Task2 bitip tekrar Task1'e dönüldüğünde stringi kaldığı yerden göndermeye devam etmesi gerekmiyor mu? Yani "Task 1 is running" cümlesinde "1 is running" yazısını da yollaması gerekmez mi? Buradaki sıkıntı nedir? HAL_UART fonksiyonu ile alakalı olabilir mi?
Başlık: Ynt: Rtos task
Gönderen: Tagli - 08 Mayıs 2020, 19:51:54
HAL_UART_Transmit() fonksiyonu thread-safe (veya bir başka ifade ile re-entrant) olmadığı için her türlü acayiplikle karşılaşabilirsin. Bu fonksiyona aynı anda iki task (thread) erişmemeli. Bunun için de bir mutex oluşturmalı ve bu fonksiyona mutex koruması altında erişmelisin.
Başlık: Ynt: Rtos task
Gönderen: mr.engineer - 08 Mayıs 2020, 21:18:55
Alıntı yapılan: Tagli - 08 Mayıs 2020, 19:51:54HAL_UART_Transmit() fonksiyonu thread-safe (veya bir başka ifade ile re-entrant) olmadığı için her türlü acayiplikle karşılaşabilirsin. Bu fonksiyona aynı anda iki task (thread) erişmemeli. Bunun için de bir mutex oluşturmalı ve bu fonksiyona mutex koruması altında erişmelisin.

Mutexi bilmiyordum daha yeniyim. Bir çeşit semafor, flag gibi çalışıyor. Yani stringi tamamen yollayana kadar task'den çıkmasını engelliyoruz.
HAL_UART (kesmesiz) fonksiyonunun thread-safe olması nedir bilmiyorum ileride kitap bahsediyor ordan bakarım.

Peki HAL kütüphanesini kullanmasam register seviyesinde kodlayıp stringleri o şekilde yollasam bu sorun ortadan kalkar mı? Yani task kaldığı yerden devam edip stringin kalanını yollar mı? Bu durumda mutex falan kullanmaya gerek kalmaz heralde.
Başlık: Ynt: Rtos task
Gönderen: Tagli - 08 Mayıs 2020, 21:41:40
Alıntı yapılan: mr.engineer - 08 Mayıs 2020, 21:18:55Peki HAL kütüphanesini kullanmasam register seviyesinde kodlayıp stringleri o şekilde yollasam bu sorun ortadan kalkar mı?
Muhtemelen hayır, yine olmaz. Kendi fonksiyonunu her seferinde 1 byte gönderecek şekilde yazarsan belki. Ama uğraşmaya değmez. Mutex kullanmak gözde büyütülecek bir şey değil.

Alıntı yapılan: mr.engineer - 08 Mayıs 2020, 21:18:55Yani stringi tamamen yollayana kadar task'den çıkmasını engelliyoruz.
Hayır, bu şekilde çalışmıyor. Mutex bir critical section tanımlamanı sağlıyor. O bölgeye ilk varan thread (A diyelim) işini bitirip oradan çıkana kadar başka bir thread (B diyelim) aynı bölgeye giremiyor. A işini bitirmeden B çalışmaya başlayabilir belki, ama kritik bölgeye vardığında ilerleyemez ve RTOS tarafından bloklanır, yerine bir başka thread çalışır (belki tekrar A, veya belki C).
Başlık: Ynt: Rtos task
Gönderen: mufitsozen - 08 Mayıs 2020, 22:07:46
sorunu yanlis teshis ettiniz, tasklar, suresi vsde bir problem yok. dizi boyutu olarak " sizeof(pcTaskName)" yazmissiniz. Bu degisken pointer ve boyuda 4 byte. Buraya dizinin boyunu (mesela strlen fonksiyonu ile) vermelisiniz. Hep ilk 4 karakteri yaziyorsunuz.
Başlık: Ynt: Rtos task
Gönderen: yamak - 08 Mayıs 2020, 22:11:54
Doğru olan @Tagli'nin dediği gibi. Mutex ile ya da critical section ile korumanız gerekir.Ama iki task da aynı priority de ise scheduling algoritması priority scheduling ise(Round Robin vs değil ise) yine düzgün çalışması gerekir aslında. Aynı priority de olduklarından dolayı os delay den önce context switching olmaması gerekir.

Ama dediğim gibi doğru olan @Tagli nin dediği gibi olması. Aynı priority de olsa mutex ile korumak gerekir her ihtimale karşı.
Başlık: Ynt: Rtos task
Gönderen: yamak - 08 Mayıs 2020, 22:13:45
Alıntı yapılan: mufitsozen - 08 Mayıs 2020, 22:07:46sorunu yanlis teshis ettiniz, tasklar, suresi vsde bir problem yok. dizi boyutu olarak " sizeof(pcTaskName)" yazmissiniz. Bu degisken pointer ve boyuda 4 byte. Buraya dizinin boyunu (mesela strlen fonksiyonu ile) vermelisiniz. Hep ilk 4 karakteri yaziyorsunuz.
Evet. Ben dikkat etmedim açıkçası asıl sorun bu. Eğer algoritma priority scheduling ise düzgün çalışması gerekir.
Başlık: Ynt: Rtos task
Gönderen: mr.engineer - 08 Mayıs 2020, 23:10:55
Alıntı yapılan: mufitsozen - 08 Mayıs 2020, 22:07:46sorunu yanlis teshis ettiniz, tasklar, suresi vsde bir problem yok. dizi boyutu olarak " sizeof(pcTaskName)" yazmissiniz. Bu degisken pointer ve boyuda 4 byte. Buraya dizinin boyunu (mesela strlen fonksiyonu ile) vermelisiniz. Hep ilk 4 karakteri yaziyorsunuz.


Evet, asıl hata buradaymış, teşekkürler. Pointerı diziye çevirince düzeldi. Şu an doğru bir şekilde çalışıyor.


Alıntı yapılan: Tagli - 08 Mayıs 2020, 21:41:40Muhtemelen hayır, yine olmaz. Kendi fonksiyonunu her seferinde 1 byte gönderecek şekilde yazarsan belki. Ama uğraşmaya değmez. Mutex kullanmak gözde büyütülecek bir şey değil.
Hayır, bu şekilde çalışmıyor. Mutex bir critical section tanımlamanı sağlıyor. O bölgeye ilk varan thread (A diyelim) işini bitirip oradan çıkana kadar başka bir thread (B diyelim) aynı bölgeye giremiyor. A işini bitirmeden B çalışmaya başlayabilir belki, ama kritik bölgeye vardığında ilerleyemez ve RTOS tarafından bloklanır, yerine bir başka thread çalışır (belki tekrar A, veya belki C).

Teşekkürler, şimdilik burada çalıştığına göre  mutexe ihtiyaç kalmadı bu örnek için.

Hatayı çözmeye çalışırken şöyle bir şey düşündüm. Aşağıdaki define tick periodu veriyor, yani periodum 1 ms. Yolladığım string uzunluğu ise 18 byte ve baud rate 38400. Yani bu stringin tamamen iletilmesi yaklaşık 4ms sürüyor, fakat benim tick periodum 1ms yani bu string gönderilmeden diğer taske geçmem gerekir ve outputun hatalı olması gerekir. Şu an outputu doğru alıyorum ama bu hesaba göre düzgün çalışmaması gerekiyor bana göre :)
Yanlış bildiğim yer nedir burada?


#define configTICK_RATE_HZ   ((TickType_t)1000)
Başlık: Ynt: Rtos task
Gönderen: yamak - 08 Mayıs 2020, 23:18:28
Alıntı yapılan: mr.engineer - 08 Mayıs 2020, 23:10:55Evet, asıl hata buradaymış, teşekkürler. Pointerı diziye çevirince düzeldi. Şu an doğru bir şekilde çalışıyor.


Teşekkürler, şimdilik burada çalıştığına göre  mutexe ihtiyaç kalmadı bu örnek için.

Hatayı çözmeye çalışırken şöyle bir şey düşündüm. Aşağıdaki define tick periodu veriyor, yani periodum 1 ms. Yolladığım string uzunluğu ise 18 byte ve baud rate 38400. Yani bu stringin tamamen iletilmesi yaklaşık 4ms sürüyor, fakat benim tick periodum 1ms yani bu string gönderilmeden diğer taske geçmem gerekir ve outputun hatalı olması gerekir. Şu an outputu doğru alıyorum ama bu hesaba göre düzgün çalışmaması gerekiyor bana göre :)
Yanlış bildiğim yer nedir burada?


#define configTICK_RATE_HZ   ((TickType_t)1000)
Hocam yukarıda bundan bahsettim aslında.
İki taskın priority si eşit olduğu için bu dediğiniz olmuyo. Priority ler değiştirirseniz bu durumu yaşarsınız.

Aslında her 1 ms de bir scheduler çalışıyo. Ama iki task aynı önceliğe sahip olduğu için context switching olmuyo.
Başlık: Ynt: Rtos task
Gönderen: mr.engineer - 08 Mayıs 2020, 23:39:31
Alıntı yapılan: yamak - 08 Mayıs 2020, 23:18:28Hocam yukarıda bundan bahsettim aslında.
İki taskın priority si eşit olduğu için bu dediğiniz olmuyo. Priority ler değiştirirseniz bu durumu yaşarsınız.

Aslında her 1 ms de bir scheduler çalışıyo. Ama iki task aynı önceliğe sahip olduğu için context switching olmuyo.

Bunu bilmiyordum kitapta yazılan şey her time slice da yani her tick interrupt da schedular diğer task a geçtiğini söylüyor. Peki neye göre ya da ne zaman diğer task'a geçiyor?
Yukarıda osdelay'den önce switching olmaz demişsiniz. Yani osdelay'den sonra fonksiyon(task) tamamen bittikten sonra mı diğer task a geçiş yapılıyor?
Başlık: Ynt: Rtos task
Gönderen: yamak - 08 Mayıs 2020, 23:51:02
Preemptive Scheduling için konuşuyorum,

Hocam her tick interruptı ile scheduler çalışır.Scheduler, bekleyen tasklara(Ready List'teki tasklara) bakar,eğer o an çalıştırılan tasktan daha yüksek öncelikli bir task varsa onu çalıştırır.

osDelay fonksiyonu çağırıldığında tick interruptı gelmemiş olsa bile, osDelay'i çağıran task, suspend edilir ve scheduler çağırılır. Yine Ready List'teki tasklara bakılır en yüksek öncelikli olan çalıştırılır.Eğer Ready List boşsa, Ready List'te bir task eklenene kadar Idle Task çalıştırılır.
Başlık: Ynt: Rtos task
Gönderen: mufitsozen - 09 Mayıs 2020, 00:10:07
Hangi rtos'u kullaniyorsunuz.

Son mesajlarda timer/priority ile aciklamalar dogru degil.

referansiniz nedir?
Başlık: Ynt: Rtos task
Gönderen: mr.engineer - 09 Mayıs 2020, 00:13:25
Anladım hocam bizde priorityler aynı. Şu an bir task1'in içine 3 string daha ekleyip onları da uart ile yollayarak çalıştırmayı denedim ve oldu. Tüm stringler başarılı bir şekilde yollanıyor. Hangi scheduling'i kullandığımı bilmiyorum ama priorityler aynıyken her task bitene kadar bekleniyor ve diğerine geçiliyor.

Yani dediğiniz gibi frekans değiştirme olayı schedular çalışma şeklinden dolayı, aynı prioritye sahip taskler için bir şey değiştirmiyor.
Başlık: Ynt: Rtos task
Gönderen: mr.engineer - 09 Mayıs 2020, 00:13:58
Alıntı yapılan: mufitsozen - 09 Mayıs 2020, 00:10:07Hangi rtos'u kullaniyorsunuz.

Son mesajlarda timer/priority ile aciklamalar dogru degil.

referansiniz nedir?

FreeRtos
Mastering the FreeRTOS™ Real Time Kernel kitap da bu yani ben anladığımı yazdım fakat burada tartıştığımız kısımla ilgili bir şey yazılmamış ama tüm kitabı okumadım.
Başlık: Ynt: Rtos task
Gönderen: yamak - 09 Mayıs 2020, 00:22:22
Alıntı yapılan: mufitsozen - 09 Mayıs 2020, 00:10:07Hangi rtos'u kullaniyorsunuz.

Son mesajlarda timer/priority ile aciklamalar dogru degil.

referansiniz nedir?
Bana mı soruyosunuz hocam?
Başlık: Ynt: Rtos task
Gönderen: yamak - 09 Mayıs 2020, 00:29:24
Alıntı yapılan: mr.engineer - 09 Mayıs 2020, 00:13:58FreeRtos
Mastering the FreeRTOS™ Real Time Kernel kitap da bu yani ben anladığımı yazdım fakat burada tartıştığımız kısımla ilgili bir şey yazılmamış ama tüm kitabı okumadım.
Hocam µC/OS-III ün User's Manual'ini okumanızı tavsiye ederim.Piyasadaki,Rtos hakkında en iyi kaynaklardan birisi bu kitap bana göre.
Başlık: Ynt: Rtos task
Gönderen: mr.engineer - 09 Mayıs 2020, 00:59:41
Alıntı yapılan: yamak - 09 Mayıs 2020, 00:29:24Hocam µC/OS-III ün User's Manual'ini okumanızı tavsiye ederim.Piyasadaki,Rtos hakkında en iyi kaynaklardan birisi bu kitap bana göre.

Ben herkes freeRtos u öneriyor diye freertos'a başladım ve kaynak olarak da kendi kaynaklarını kullanıyorum. Bu söylediğiniz kitapta ismi geçen "µC/OS" başka bir rtos çeşidi galiba. Şu an okuduğum kaynakda basit şekilde güzelce anlatıyor aslında ama bu dediğinizi de indireyim.
Ben bu rtos dünyasına biraz yabancıyım ama tüm rtos çeşitleri birbirine benziyor heralde:)
Başlık: Ynt: Rtos task
Gönderen: yamak - 09 Mayıs 2020, 02:17:40
Hocam Micrium 10 numara RTOS dur.Bana göre FreeRtos ile karşılaştırılamaz.Source kodunun sadeliği,dökümantasyonu çok iyidir.Kod MISRA uyumludur. Ayrıca DO-178B sertifikasyonu vardır.
Bu kadar şeye rağmen bir kaç ay önce Open Source oldu.

Kendine ait bir çok stack'i de mevcut.Tcp/ip,USB,MQTT,FS ...

Github sayfası:
https://github.com/SiliconLabs?q=uC-&type=&language=

Başlık: Ynt: Rtos task
Gönderen: Tagli - 09 Mayıs 2020, 08:47:24
@mufitsozen'in de dediği gibi, task öncelikleri aynı bile olsa, scheduler çalıştığı zaman mevcut task'ı durdurup ("sen artık yeterince çalıştın" diyerek) aynı öncelikteki bir başkasına zaman vermeli. Zaten kesme, blok çözülmesi vs. gibi bir sebeple daha yüksek öncelikli bir task hazır (ready) durumuna gelirse, scheduler 1 ms süreyi beklemeden devreye girip task'ı değiştirir.

Bu davranış kullanılan RTOS'a ve ayarlara göre değişebilir ama genelde böyledir.

Başlık: Ynt: Rtos task
Gönderen: yamak - 09 Mayıs 2020, 10:23:27
Alıntı yapılan: Tagli - 09 Mayıs 2020, 08:47:24@mufitsozen'in de dediği gibi, task öncelikleri aynı bile olsa, scheduler çalıştığı zaman mevcut task'ı durdurup ("sen artık yeterince çalıştın" diyerek) aynı öncelikteki bir başkasına zaman vermeli.

  Hocam,Priorty Based Scheduling algoritmasında  böyle olmaz aslında. Eğer iki taskın öncelikleri aynı ise bir task'ın durması için event beklemesi,delay ile bekletme vs gibi bir şey ile suspend edilmesi gerekir. Aksi halde 2. task hiç çalışmaz. Fakat Round Robin gibi bir algoritma kullanılıyorsa, bu durum oluşmaz, scheduler eşit zaman aralıkları ile taskları çalıştırır.

  Yani Priority Based Scheduling kullanılırken bu gibi durumları hesaba katarak tasarım yapmak gerekir.

Edit: Yukarıda bahsettiğim şey, sistemde aynı öncelikte, sadece 2 task varsa geçerli. Eğer bu iki tasktan daha yüksek öncelik başka task(lar) varsa; scheduler ın davranışı bu şekilde olmayabilir.
Başlık: Ynt: Rtos task
Gönderen: Tagli - 09 Mayıs 2020, 13:26:06
Haklısın @yamak hocam. Sanırım bahsettiğim genelleme hatalı oldu. Ancak FreeRTOS için konuşursak, varsayılan ayar benim dediğim gibi. Bunu configUSE_TIME_SLICING parametresi ile değiştirmek mümkün.

Alıntı YapconfigUSE_TIME_SLICING
By default (if configUSE_TIME_SLICING is not defined, or if configUSE_TIME_SLICING is defined as 1) FreeRTOS uses prioritised preemptive scheduling with time slicing. That means the RTOS scheduler will always run the highest priority task that is in the Ready state, and will switch between tasks of equal priority on every RTOS tick interrupt. If configUSE_TIME_SLICING is set to 0 then the RTOS scheduler will still run the highest priority task that is in the Ready state, but will not switch between tasks of equal priority just because a tick interrupt has occurred.
Başlık: Ynt: Rtos task
Gönderen: mr.engineer - 09 Mayıs 2020, 16:02:37
Alıntı yapılan: Tagli - 09 Mayıs 2020, 13:26:06Haklısın @yamak hocam. Sanırım bahsettiğim genelleme hatalı oldu. Ancak FreeRTOS için konuşursak, varsayılan ayar benim dediğim gibi. Bunu configUSE_TIME_SLICING parametresi ile değiştirmek mümkün.


Hocam bu dediğiniz kafamı karıştırdı. Aşağıdaki iki değer de set edilmiş.Paylaştığınız açıklamaya göre her tick interrupta task değişmesi gerekiyor ama bende bu şekilde çalışmıyor. Bir task tamamen bittikten sonra diğer task'a geçiyor. Her interruptta değişse aşağıda paylaştığım gibi bir output alamam.

#define configUSE_PREEMPTION  1
#define configUSE_TIME_SLICING 1
#define configTICK_RATE_HZ              ((TickType_t)1000)

Not: UART baud rate 38400

void vTask1( void *pvParameters )
{
const char pcTaskName[] = "Task 1 is running\r\n";
const char pcTaskName2[] = "12345\r\n";
const char pcTaskName3[] = "6789\r\n";
volatile uint32_t ul; /* volatile to ensure ul is not optimized away. */
/* As per most tasks, this task is implemented in an infinite loop. */
for( ;; )
{
/* Print out the name of this task. */
HAL_UART_Transmit(&huart2, (uint8_t*)pcTaskName, sizeof(pcTaskName),100);
HAL_UART_Transmit(&huart2, (uint8_t*)pcTaskName2, sizeof(pcTaskName2),100);
HAL_UART_Transmit(&huart2, (uint8_t*)pcTaskName3, sizeof(pcTaskName3),100);
//HAL_UART_Transmit_IT(&huart2,(uint8_t*)pcTaskName, sizeof(pcTaskName));
/* Delay for a period. */
osDelay(100);
}
}


void vTask2( void *pvParameters )
{
const char pcTaskName[] = "Task 2 is running\r\n";
volatile uint32_t ul; /* volatile to ensure ul is not optimized away. */
/* As per most tasks, this task is implemented in an infinite loop. */
for( ;; )
{
/* Print out the name of this task. */
HAL_UART_Transmit(&huart2, (uint8_t*)pcTaskName, sizeof(pcTaskName),100);
/* Delay for a period. */
osDelay(100);
}
}


Output aynen şu şekilde:
Task 1 is running
12345
6789
Task 2 is running
Task 1 is running
12345
.
.
.
Başlık: Ynt: Rtos task
Gönderen: Tagli - 09 Mayıs 2020, 18:26:01
İlginç gerçekten de, ben de çözemedim bu durumu. Bu şekilde olabilmesi için task'ların 1 ms içinde tüm karakterleri yollayabilmeleri lazım ki bu da pek mümkün gözükmüyor.

HAL_UART_Transmit() içinde bir üç kağıt olabilir mi acaba?

Düşük de olsa aklıma bir ihtimal geliyor: Task'lardan biri osDelay(100) içinde bloklanmışken diğeri işini bitirebilir. Task'ların her birinin kabaca 5-10 ms'ye ihtiyacı var gibi. Zamanlama uygun şekilde denk gelirse birbirleri ile çakışmadan çalışabilirler belki.
Başlık: Ynt: Rtos task
Gönderen: mr.engineer - 09 Mayıs 2020, 18:42:24
Alıntı yapılan: Tagli - 09 Mayıs 2020, 18:26:01İlginç gerçekten de, ben de çözemedim bu durumu. Bu şekilde olabilmesi için task'ların 1 ms içinde tüm karakterleri yollayabilmeleri lazım ki bu da pek mümkün gözükmüyor.

HAL_UART_Transmit() içinde bir üç kağıt olabilir mi acaba?

Düşük de olsa aklıma bir ihtimal geliyor: Task'lardan biri osDelay(100) içinde bloklanmışken diğeri işini bitirebilir. Task'ların her birinin kabaca 5-10 ms'ye ihtiyacı var gibi. Zamanlama uygun şekilde denk gelirse birbirleri ile çakışmadan çalışabilirler belki.

Hocam osDelay içinde bloklanma ihtimali ile demek istediğinizi tam anlayamadım. Bana çakışmadan çalışması pek mümkün gelmedi çünkü osDelay(10) yapınca da düzgün çalışıyor. Tek değişen daha hızlı çalışması.

HAL_UART_Transmit()

Benim aklıma gelen de bu fonksiyon. Sanki bu fonksiyona girince diğer task blocklanıyor gibi duruyor.
Başlık: Ynt: Rtos task
Gönderen: mr.engineer - 09 Mayıs 2020, 19:08:10
osdelay'i kaldırıp for döngüsü ile delay yaratınca da çalışıyor. Osdelay ile de ilgisi yok görünüyor.
Başlık: Ynt: Rtos task
Gönderen: yamak - 09 Mayıs 2020, 21:16:59
Hocam siz söyleyince baktım.Stm32 HAL fonksyionları thread safe miş.Ondan dolayı problem olmuyo.Yani HAL_UART_Transmit() _HAL_LOCK adındaki macro ile bir mutexi lock ediyo.O yüzden race condition oluşmuyor.

Edit: _HAL_LOCK un nasıl implement edilidiğine baktığımda aslında buna thread safe denemez. Yani bir mutex kullanımı söz konusu değil. Basit şekilde bi flag set ediliyor reset edilene kadar aynı uartta n başka bir transmit işlemi yapılamıyor.

__HAL_LOCK:
#if (USE_RTOS == 1)
  #error " USE_RTOS should be 0 in the current HAL release "
#else
  #define __HAL_LOCK(__HANDLE__)                                           \
                                do{                                        \
                                    if((__HANDLE__)->Lock == HAL_LOCKED)  \
                                    {                                      \
                                       return HAL_BUSY;                    \
                                    }                                      \
                                    else                                   \
                                    {                                      \
                                       (__HANDLE__)->Lock = HAL_LOCKED;    \
                                    }                                      \
                                  }while (0)

  #define __HAL_UNLOCK(__HANDLE__)                                          \
                                  do{                                       \
                                      (__HANDLE__)->Lock = HAL_UNLOCKED;   \
                                    }while (0)
#endif /* USE_RTOS */

HAL_UART_Transmit:

HAL_StatusTypeDef HAL_UART_Transmit(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size, uint32_t Timeout)
{
  uint16_t *tmp;
  uint32_t tickstart = 0U;

  /* Check that a Tx process is not already ongoing */
  if (huart->gState == HAL_UART_STATE_READY)
  {
    if ((pData == NULL) || (Size == 0U))
    {
      return  HAL_ERROR;
    }

    /* Process Locked */
    __HAL_LOCK(huart);

    huart->ErrorCode = HAL_UART_ERROR_NONE;
    huart->gState = HAL_UART_STATE_BUSY_TX;

    /* Init tickstart for timeout managment */
    tickstart = HAL_GetTick();

    huart->TxXferSize = Size;
    huart->TxXferCount = Size;

    /* Process Unlocked */
    __HAL_UNLOCK(huart);

    while (huart->TxXferCount > 0U)
    {
      huart->TxXferCount--;
      if (huart->Init.WordLength == UART_WORDLENGTH_9B)
      {
        if (UART_WaitOnFlagUntilTimeout(huart, UART_FLAG_TXE, RESET, tickstart, Timeout) != HAL_OK)
        {
          return HAL_TIMEOUT;
        }
        tmp = (uint16_t *) pData;
        huart->Instance->DR = (*tmp & (uint16_t)0x01FF);
        if (huart->Init.Parity == UART_PARITY_NONE)
        {
          pData += 2U;
        }
        else
        {
          pData += 1U;
        }
      }
      else
      {
        if (UART_WaitOnFlagUntilTimeout(huart, UART_FLAG_TXE, RESET, tickstart, Timeout) != HAL_OK)
        {
          return HAL_TIMEOUT;
        }
        huart->Instance->DR = (*pData++ & (uint8_t)0xFF);
      }
    }

    if (UART_WaitOnFlagUntilTimeout(huart, UART_FLAG_TC, RESET, tickstart, Timeout) != HAL_OK)
    {
      return HAL_TIMEOUT;
    }

    /* At end of Tx process, restore huart->gState to Ready */
    huart->gState = HAL_UART_STATE_READY;

    return HAL_OK;
  }
  else
  {
    return HAL_BUSY;
  }
}

__HAL_LOCK, UART_HandleTypeDef structure ı içindeki LOCK elemanını HAL_LOCKED state ine çekiyor.Aynı UART_HandleTypeDef structure ı ile işlem yapmak isteyen başka bir task __HAL_LOCK çağırdığında zaten HAL_LOCKED olduğu için HAL_UART_Transmit fonksiyonu hiçbir şey yapmadan HAL_BUSY ile return ediyor.
Başlık: Ynt: Rtos task
Gönderen: MrDarK - 09 Mayıs 2020, 23:22:08
Bu hal library derinlerinde amma da iş yapıyor:)

Desenize binary semafor kullanmışlar.

Picproje de daha fazla böyle başlıklar olmalı artık güzel sorular.
Başlık: Ynt: Rtos task
Gönderen: yamak - 10 Mayıs 2020, 00:07:07
Hocam tam binary semaphore değil de ona benzer bi şey yapmaya çalışmışlar.Binary semaphore'da lock edilemediğinde scheduler  çağırılıp context switching yapılıyor.Ama burda sadece transmit fonksiyonundan return ediyo.Yani o taskın içinde transmitten başka bir iş varsa onları yapmaya devam eder.

Ama adamlar
#if (USE_RTOS == 1)
  #error " USE_RTOS should be 0 in the current HAL release "
kısmını yazarak ileride gerçek thread safe e geçiş yapacaklar diye anlıyorum.Şu an USE_RTOS define edilirse compile time'da error alırız.
Başlık: Ynt: Rtos task
Gönderen: mr.engineer - 10 Mayıs 2020, 00:13:18
@yamak hocam size de diğer uğraşan arkadaşlara da teşekkür ediyorum. Bu sefer tam olarak anladım galiba:)
O zaman @Tagli nın da söylediği gibi her tick interrupta schedular diğer taska geçiyor ama UART'ı çalıştıramadığı için bir şey yapamıyor ve diğer task kaldığı yerden devam ediyor.
Başlık: Ynt: Rtos task
Gönderen: mr.engineer - 10 Mayıs 2020, 00:25:57
Hocam aslında HAL_UART_Transmit fonksiyonunda HAL_LOCK'dan önce test edilen bir ifade daha var.

UART ilk çalıştığında gstate busy yapılıyor.

huart->gState = HAL_UART_STATE_BUSY_TX;

İkinci task tekrar UART kullanmak isterse karşısına şu test ifadesi çıkıyor ve fonksiyondan çıkmak zorunda kalıyor.

if (huart->gState == HAL_UART_STATE_READY)
Başlık: Ynt: Rtos task
Gönderen: yamak - 10 Mayıs 2020, 00:30:03
Evet Hocam tam olarak böyle oluyo.İlk Lock eden gstate'i tekrar HAL_UART_STATE_READY'e çekene kadar ikinci UART transmit edemiyor.