Kali ini kita akan menjajal development board Nucleo F429ZI yang kebetulan sedang mampir di meja saya. Secara spesifikasi board ini sudah sangat jauh meninggalkan kecepatan arduino sehingga pantas untuk dilirik untuk project2 yang membutuhkan proses pengolahan yang lebih cepat. Board ini menggunakan STM32F429ZIT6 dengan LQFP144 package. Penampakan board nucleo 144 F429ZI dapat dilihat pada gambar di bawah ini.
Board ini dilengkapi dengan 3 buah user LED yang terhubung dengan pin PB0 (led hijau), PB7 (led biru), dan PB14 (led merah) yang nanti akan kita coba mainkan dengan RTOS. RTOS sendiri adalah kependekan dari Real Time Operating System, penggunaan RTOS pada sistem embedded umumnya bertujuan untuk memastikan waktu eksekusi dari setiap task atau ingin menghasilkan respon eksekusi yang deterministik dari suatu event yang ada. Free RTOS ini disediakan oleh STM32F4 yang dapat kita download dari website ST dan nantinya akan bertindak sebagai middleware. STM32cubef4 terbaru yang berisi hal driver, stacks middleware ketika artikel ini ditulis adalah versi 1.14.0.
Untuk memulai develop stm32 kita dapat menggunakan software stm32 cubemx. STM32CubeMX merupakan software berbasis grafis yang akan membantu kita dalam menghasilkan source codes initialisasi dalam bahasa C. Untuk itu kita perlu jalankan STM32CubeMX dan pilih New project, kemudian kita pilih MCU yang sesuai dengan board yang kita miliki dalam hal ini adalah Nucleo 144 – F429ZI.
Selanjutnya kita perlu melakukan configurasi pinout MCU tersebut. Pilih Pin PB0, PB7 dan PB14 dan set menjadi GPIO output. Pin-pin ini terhubung dengan LED yang nanti akan kita kontrol dengan RTOS. Centang pula kotak enable FREERTOS pada bagian MiddleWares.
Kemudian pada bagian peripherals pilih RCC dan aktifkan HSE dengan Crystal/Ceramic Resonator serta pada bagian SYS, ubah Timebase Source dari Systick menjadi TIM1. Pengubahan RCC dan SYS ini bersifat opsional akan tetapi saya anggap penting karena pemilihan HSE dan TIMER 1 jauh lebih baik daripada menggunakan HSI dan Systick 1 (default) karena lebih akurat. Untuk menghasilkan clock output yang sesuai karena kita telah memilih HSE dengan input eksternal crystal sebesar 8 MHZ maka pada tab clock configuration kita perlu ubah seperti pada gambar di bawah ini
Pada latihan kali ini kita akan berlatih menggunakan Message, semaphore dan OS timer pada RTOS sehingga kita perlu untuk mensetup free RTOS yang akan kita gunakan dengan cara memilih tab configuration dan mengklik freertos hingga muncul jendela konfigurasi. Aktifkan (enabled) USE_TIMERS pada tab config parameters dan tambahkan timers pada tab Timers and Semaphores dengan cara mengklik add
Pilih Tab Project -> Project Settings kemudian masukkan nama Project dan pilih Toolchain / IDE MDK-ARM V5 (dalam kesempatan ini kita gunakan keil), klik ok dan pilih generate code. Seteleh digenerate maka buka project file pada folder MDK-ARM (uVision5 Project file). Pada contoh ini kita akan membuat 4 buah thread, 1 buah semaphore, 1 buah message queue dan 1 buah timer os. 4 Buah thread terbagi atas sepasang thread yang saling berkomunikasi dengan semaphore dan sepasang thread yang saling berkomunikasi dengan message queue.
Sepasang thread yang saling berkomunikasi dengan message akan bertugas untuk menyalakan led hijau (PB0). Cara untuk mensetup dua buah thread dengan message adalah sebagai berikut
/* Create message communication */
osMessageQDef(osqueue, 1, uint16_t);
osQueue = osMessageCreate (osMessageQ(osqueue), NULL);
/* Create a pairs of thread for message communication */
osThreadDef(QCons, MessageQueueConsumer, osPriorityBelowNormal, 0, configMINIMAL_STACK_SIZE);
osThreadDef(QProd, MessageQueueProducer, osPriorityBelowNormal, 0, configMINIMAL_STACK_SIZE);
osThreadCreate(osThread(QCons), NULL);
osThreadCreate(osThread(QProd), NULL);
Code diatas akan menghasilkan 2 buah thread yaitu QCons dan QProd dengan fungsinya yaitu MessageQueueConsumer dan MessageQueueProducer dengan message yaitu osQueue. QProd akan mengirim pesan (osQueue) dengan isi adalah variable ProducerValue. Thread QCons akan menerima message dan membandingkan nilai yang dikirim oleh message (ProducerValue) dengan ConsumerValue, apabila sesuai maka akan mentogel pin 0 (led hijau). Apabila tidak sesuai maka ConsumerValue akan mengupdate nilai dirinya dengan ProducerValue. Detil source code dapat dilihat pada link berikut main
Untuk mengatur nyala LED biru (PB7) akan digunakan sebuah semaphore dan 2 buah thread yaitu LEDThread1Handle dan LEDThread2Handle. semaphore dan kedua thread tersebut dapat dibuat dengan code sebagai berikut
/* Define used semaphore */
osSemaphoreDef(SEM);
osSemaphore = osSemaphoreCreate(osSemaphore(SEM) , 1);
osSemaphoreRelease(osSemaphore);
/* Create a pairs of thread to light up BLUE LED */
osThreadDef(ThreadA, LED_Thread1, osPriorityLow, 0, configMINIMAL_STACK_SIZE);
osThreadDef(ThreadB, LED_Thread2, osPriorityIdle, 0, configMINIMAL_STACK_SIZE);
LEDThread1Handle = osThreadCreate (osThread(ThreadA), (void *) osSemaphore);
LEDThread2Handle = osThreadCreate (osThread(ThreadB), (void *) osSemaphore);
Semaphore yang digunakan oleh kedua thread menyebabkan hanya akan salah satu dari thread tersebut yang dapat menyalakan LED biru pada waktu tertentu. Apabila semaphore sudah diambil oleh LEDThread1Handle maka LEDThread2Handle tidak dapat mentogel LED biru dan begitu juga sebaliknya. LEDThread1Handle memiliki prioritas yang lebih tinggi dibandingkan LEDThread2Handle. Maka selain harus memiliki semaphore untuk menyalakan LED biru, maka LEDThread1Handle harus dalam keadaan tidak aktif sehingga perlu disuspend terlebih dahulu.
TimerOS digunakan untuk mentogel LED merah, untuk menghasilkan timer os dilakukan dengan code di bawah ini
/* Create the timer(s) */
osTimerDef(myTimer01, Callback01);
myTimer01Handle = osTimerCreate(osTimer(myTimer01), osTimerPeriodic, NULL);
osTimerStart(myTimer01Handle, 500);
setiap terjadi interrupt Timer OS maka LED merah akan ditogel.