STM32 RTOS Nedir ?
Merhabalar arkadaşlar sizlerle bu makalede STM32 üzerinde temel olarak rtos nasıl çalışır nasıl kullanılır ve uygulanır konularına değineceğim.
RTOS , mikrodenetleyici üzerinde koşacak farklı görevleri, belirtilen önceliklere ve zamanlamalara göre bağımsız olarak gerçekleştirmeyi , görevler arasında haberleşmeyi ve görevlerin anlık olarak yönetimini sağlayan bir gerçek zamanlı bir işletim sistemidir.
STM32 RTOS nasıl kullanacağız ?
STM32CubeMx ile FreeRTOS gelmektedir. FreeRTOS’u kullanabilmek için STM32CubeMx üzerinden FreeRTOS’u aktif edip, ayarlarını projemizin ihtiyacına göre düzenlememiz gerekir.
Uygulamamızda FreeRTOS’un çalışmasını gözlemleyebilmek için STM32 mikrodenetleyicimiz ile UART seri haberleşme işlemi gerçekleştireceğiz.
Haydi Uygulamayı Yapalım!
1) STM32CubeMx’i açarak mikrodenetleyicimizin çevresel birimlerini ihtiyaca göre düzenliyoruz.

2) Mikrodenetleyicinin clock ayarlarının yapılması gerekiyor.

3) Pinout & Configuration sekmesinden SYS‘ye girerek, TimeBase Source‘u SysTick yerine, donanımsal timer’lardan birisi olarak ayarlamak gerekiyor.(TIM1)
stm32 RTOS kullanılmadığında bu zorunluluk olmuyor. FreeRTOS donanımsal bir timer’a ihtiyaç duyduğu için bu ayarı yapmak gerekiyor.

4) Pinout & Configuration sekmesinden stm32 RTOS‘a girilerek , Interface olarak CMSIS_V1 seçiliyor. İşletim sisteminin koşacağı tasklara önceliklendirme yapmak isteyeceğimizden dolayı USE_PREEMPTION parametresini “Enabled” olarak ayarlamalıyız.

5) FREERTOS kurulumu yapıldığında CubeMX , işletim sistemi üzerinde “defaultTask” isminde bir task oluşturur. Taskları görebilmek ve yenisini ekleyebilmek için “Tasks and Queues” sekmesine girmek gerekiyor.

Bu kısımda stm32 RTOS’un çalışmasını daha iyi gözlemleyebilmek amacıyla “Add” butonuna basarak yeni bir task ekleyelim. Task ekleme işlemi yukarıdaki resimde gösterilmiştir.
6) Task ekleme işlemimizden sonra “Generate Code” işlemi yapılabilir. Projenin main.c modülünü açtığımızda “Private Variables” kısmında UART çevresel biriminin yanı sıra, CubeMX üzerinde tanımlı olan 2 taskla ilgili handle tanımlamalarını görüyoruz.
7) Tanımlama kısmından aşağıya doğru devam ettiğimizde, tasklarımızın koşulacağı thread’lerin yaratıldığı tanımlamaları görüyoruz.

osThreadDef(defaultTask, StartDefaultTask, osPriorityNormal, 0, 128);
- Thread tanımlaması yapılıyor.
- Thread’in ilişkilendirildiği task ismi : defaultTask
- Thread çalıştığında koşmasını istediğimiz fonksiyonun adı “StartDefaultTask”
- Thread’in önceliklendirmesi : osPriorityNormal
defaultTaskHandle = osThreadCreate(osThread(defaultTask), NULL);
- Tanimlanan thread’in işletim sistemi üzerinde aktifleştirilmesi sağlanıyor.
- Aktifleştirilen thread’in bilgileri defaultTaskHandler struct’ına yazılıyor.
- defaultTaskHandler struct’ı işletim sistemi çalışırken task’ı yönetmek için kullanılabiliyor.(Bu kısma değineceğim)
8) Thread’lerin çalıştıklarında koşacakları fonksiyon isimlerini belirtmiştik. Şimdi bu fonksiyonları görelim.

- defaultTask çalıştığında StartDefaultTask isimli fonksiyonu çağıracak.
- Fonksiyon çalıştığında UART üzerinden “Default Task Calisti !” stringini basacaktır.
- Task kendini 1000 ms süre ile bloklayacaktır. Task’ın bir sonraki execution işlemi 1000 ms sonra yapılabilecektir.
- Task2 çalıştığında Task2_Init isimli fonksiyonu çağıracak.
- Fonksiyon çalıştığında UART üzerinden “Task2 Calisti !” stringini basacaktır.
- Task kendini 2000 ms süre ile bloklayacaktır. Task’ın bir sonraki execution işlemi 2000 ms sonra yapılabilecektir.
9) UART çıkışlarını terminal ekranından izlediğimizde STM32 RTOS un çalıştığını görüyoruz.

Uygulamayı bu kısma kadar gerçekleştirerek, temel stm32 RTOS kurulumu ve task execution işlemini gözlemlemiş olduk.
Şimdi devam ederek , bazı task yönetim fonksiyonlarını gözlemleyelim. Gözlemleyebilmek için fonksiyonlarımı şu şekilde düzenledim.


İşletim sistemi çalışmaya başladığında, her 2 task da , 1 saniyelik periyotlarla UART’a kendi stringlerini basacaklardır.
Task2_Init içindeki cnt her çalıştığında 1 artacak ve 5 olduğunda, osThreadSuspend(defaultTaskHandle) işlemini yapacaktır. Bu işlem gerçeklendiğinde, defaultTask resume ettirilene kadar geçici olarak çalışmayacaktır.
if(cnt == 5)
{
osThreadSuspend(defaultTaskHandle);
}
cnt değeri 10 olduğunda , osThreadResume(defaultTaskHandle) işlemi yapılacaktır. Bu durumda , defaultTask kaldığı yerden çalışmasına devam edecektir. Fakat istenildiğinde tekrar suspend edilebilir.
if(cnt == 10)
{
osThreadResume(defaultTaskHandle);
}
cnt değeri 20 olduğunda ise osThreadTerminate(defaultTaskHandle) işlemi yapılacaktır. Bu işlem yapıldığında defaultTask , resume ettirilemecek şekilde sonlanacaktır.
if(cnt == 20)
{
osThreadTerminate(defaultTaskHandle);
}
defaultTask’ı tekrar aktifleştirmek istersek, init işlemlerinin tekrar yapılması gerekir. cnt değeri 25 olduğunda defaultTask tekrar init ediliyor. defaultTask periyodik çalışmasına devam edecektir.
if(cnt == 25)
{
osThreadDef(defaultTask, StartDefaultTask, osPriorityNormal, 0, 128);
defaultTaskHandle = osThreadCreate(osThread(defaultTask), NULL);
}
Task’ların yönetimi ile ilgili cmsis_os.c modülündeki diğer fonksiyonları inceleyip , deneyebilirsiniz. Başka özellikler de mevcuttur.
Gelecek makalelerde, FreeRTOS queue ve mutex yapısı gibi diğer özelliklere değineceğiz.
İyi çalışmalar.