Perancangan Aplikasi Real Time (2): Solusi Tanpa RTOS

SINOPSIS

Melanjutkan artikel sebelumnya, perlu diketahui bahwa tidak setiap aplikasi membutuhkan sistem operasi atau tepatnya RTOS. Hmmm, jadi langsung saja, artikel ini memberikan gambaran tentang solusi tanpa menggunakan sistem operasi, yang nantinya kita evaluasi dan simpulkan baik buruknya, kelebihan kelemahannya. Okey, take a deep breath, ambil napas yang dalem,…. Tahan…. dan jangan dikeluarkan… what?! he he he just kidding… ya silahkan dilepaskan pelan-pelan… (maksudnya supaya santai dulu relaks)

IMPLEMENTASI

Solusi yang dibahas kali ini menggunakan pendekatan kalang (loop approach), dimana setiap komponen aplikasi dinyatakan dalam bentuk fungsi yang harus dijalankan hingga selesai. Idealnya digunakan pewaktu perangkat keras untuk melakukan penjadwalan fungsi-fungsi kontrol yang kritis. Namun, menunggu datangnya data dan perhitungan data yang begitu kompleks menyebabkan fungsi kontrol tidak cocok untuk dijalankan dalam batasan rutin layanan interupsi. Seberapa banyak dan urutan komponen mana yang dikerjakan dalam kalang tak-hingga dapat diatur dengan memasukkan unsur prioritas, silahkan perhatikan pembahasan dalam contoh nantinya.

FUNGSI KONTROL PROSES (PLANT)

Perhatikan kode pseudo berikut…

void PlantControlCycle( void )
{  
  TransmitRequest();
  WaitForFirstSensorResponse();
  if( terima data dari sensor pertama )
  {
    WaitForSecondSensorResponse();
    if( terima data dari sensor kedua )
    {
      PerformControlAlgorithm();
      TransmitResults();
    }
  }
}

FUNGSI ANTARMUKA PENGGUNA Fungsi ini meliputi antarmuka keypad, LCD, komunikasi RS232 dan server WEB tertanam. Perhatikan kode pseudo berikut…

int main( void ) 
{
  Initialise();
  for( ;; )
  {
    ScanKeypad();
    UpdateLCD();
    ProcessRS232Characters();
    ProcessHTTPRequests();
  } 
// seharusnya tidak pernah sampai disini 
  return 0; 
}

Ada dua asumsi: Pertama, masukan/luaran komunikasi di-buffer melalui rutin layanan interupsi, sehingga periferal yang terkait tidak perlu melakukan polling (proses menunggu terus menerus). Kedua, fungsi pemanggilan fungsi dalam kalang dikerjakan secepat mungkin sehingga semua syarat pewaktuan dipenuhi.

PENJADWALAN FUNGSI KONTROL PROSES

Ingat kembali bahwa kontrol proses dilakukan dalam batasan waktu 10md, perhatikan kode pseudo berikut ini…

// Flag digunakan untuk menandai waktu 
// saat siklus kontrol dimulai. 
int TimerExpired;
// Rutin layanan untuk interupsi pewaktu. 
// Dikerjakan setiap 10md. 
void TimerInterrupt( void ) 
{ 
  TimerExpired = true; 
}
// main() masih mengandung kalang tak-hingga 
// dimana pemanggilan fungsi kontrol proses 
// ditambahkan 
int main( void ) 
{ 
  Initialise(); 
  for( ;; ) 
  { 
    if( TimerExpired ) 
    { 
      PlantControlCycle();
      TimerExpired = false; 
      ScanKeypad(); 
      UpdateLCD(); 
// LED dapat menggunakan layanan interupsi 
// atau pewaktu lain yang berbeda 
      ProcessLEDs(); 
// Buffer untuk komunikasi harus cukup besar 
// agar bisa menampung data 10md. 
      ProcessRS232Characters(); 
      ProcessHTTPRequests(); 
    } 
// mikrokontroler bisa dibuat 'tidur' 
// disini dan akan dibangunkan dengan 
// adanya interupsi. 
  } 
// seharusnya tidak pernah sampai disini 
  return 0; 
}

Hmm… solusi awal ini belum bisa diterima, karena beberapa hal:

  • Misalnya ada jeda atau kegagalan pada fieldbus akan menyebabkan penambahan waktu eksekusi dari fungsi PlantControlSycle(), sehingga eksekusinya menjadi lebih lama, artinya syarat pewaktuan akhirnya tidak dipenuhi (tidak bisa selesai dalam kurun waktu kurang dari 10md).
  • Semua fungsi yang dijalankan untuk tiap siklus juga bisa mengakibatkan pewaktuan siklus kontrol bisa tidak dipenuhi (sekali lagi hal ini karena ada batasan 10md harus dilakukan pengulangan proses kontrol dari awal.
  • Ada beberapa hal yang bisa dijalankan jika ada permintaan. Misalnya, eksekusi untuk fungsi ProcessHTTPRequest() dapat diabaikan jika tidak ada permintaan HTTP, tetapi akan memakan waktu lama jika ada permintaan sehingga bisa menganggu yang lain.
  • Tidak mampu dipertahankan – adanya ketergantungan pada setiap fungsi yang sedang dikerjakan dalam rentang waktu maksimum.
  • Penyangga (buffer) komunikasi hanya dilayani sekali setiap siklus yang mengharuskan ukurannya sepadan dengan data setara waktu yang dibutuhkan

STRUKTUR ALTERNATIF

Okey, ternyata ada beberapa masalah dalam solusi awal tersebut, khususnya berkaitan dengan syarat-syarat pewaktuan – ini yang sebenarnya merupakan latar mengapa akhirnya dibutuhkan sistem operasi (akan dibahas dalam artikel-artikel berikutnya). Ada dua faktor yang dapat diidentifikasi berkaitan dengan pendekatan kalang tersebut:

1. Lamanya pemanggilan dan eksekusi setiap fungsi Setiap fungsi bisa jadi dikerjakan dalam waktu yang cukup lama. Untuk itu dapat dicegah dengan memisahkan setiap fungsi dalam beberapa kondisi. Hanya ada satu fungsi yang boleh dikerjakan pada suatu waktu, perhatikan kode pseudo berikut…

/ Mendefinisikan kondisi untuk fungsi siklus kontrol.
typdef enum eCONTROL_STATES 
{ 
  eStart, 
// Kondisi Awal siklus baru. 
  eWait1, 
// Kondisi Menunggu tanggap sensor pertama. 
  eWait2 
// Kondisi Menunggu tanggap sensor kedua. 
} eControlStates;
void PlantControlCycle( void ) 
{ 
  static eControlState eState = eStart; 
  switch( eState ) 
  { 
    case eStart : TransmitRequest(); 
                  eState = eWait1; 
                  break; 
    case eWait1 : if( Got data from first sensor ) 
                  { eState = eWait2; } 
                    break; 
    case eWait2 : if( Got data from first sensor ) 
                  { PerformControlAlgorithm(); 
                    TransmitResults(); 
                    eState = eStart; } 
                    break; } 
   }

Nah… fungsi ini sekarang strukturnya semakin kompleks karena menggunakan sistem mesin kondisi (state machine) dan mengakibatkan adanya masalah baru dalam hal penjadwalan. Kode-kodenya sendiri akan menjadi sulit dipahami seiring dengan semakin banyak kondisi yang ditambahkan, misalnya untuk menangani timeout atau kondisi gagal dan lain sebagainya.

2. Granularitas pewaktu Interval waktu yang dibuat semakin kecil akan memberikan fleksibelitas yang lebih. Implementasi fungsi kontrol sebagai sebuah mesin kondisi (agar setiap pemanggilan menjadi lebih cepat) membolehkan pemanggilan dalam rutin layanan interupsi pewaktu. Interval pewaktuan harus sependek mungkin untuk memastikan fungsi dipanggil dengan frekuensi yang memenuhi kriteria atau syarat pewaktuan yang diinginkan. Hmmm, opsi ini tentunya penuh dengan masalah pewaktuan dan pemeliharaan. Alternatifnya, solusi kalang tak-hingga dapat dimodifikasi untuk memanggil fungsi-fungsi yang berbeda pada setiap pengulangan – dengan fungsi kontrol yang mendapat prioritas lebih tinggi akan dipanggil lebih sering. Perhatikan kode pseudo berikut…

int main( void ) 
{ 
  int Counter = -1; 
  Initialise(); 
// Masing2 fungsi diimpelmentasikan dalam sebuah mesin kondisi 
// sehingga ada garansi dijalankan secepat 
// mungkin - namun harus sering dipanggil. 
// Catatan: frekuensi pewaktu dinaikkan. 
  for( ;; ) 
  { if( TimerExpired ) 
    { 
      Counter++; 
      switch( Counter ) 
      { case 0 : ControlCycle(); 
                 ScanKeypad(); 
                 break; 
        case 1 : UpdateLCD(); 
                 break; 
        case 2 : ControlCycle(); 
                 ProcessRS232Characters(); 
                 break; 
        case 3 : ProcessHTTPRequests(); 
                 Counter = -1; 
                 break; 
      } 
      TimerExpired = false; 
    } 
  } 
  return 0; 
}

Jika diperhatikan, fungsi dengan prioritas rendah bisa dipanggil hanya pada saat ada kejadian yang membutuhkan fungsi tersebut, antara lain UpdateLCD() yang bergantung pada ScanKeypad(), ProcessRS232Characters() dan ProcessHTTPRequests(). Sehingga dibutuhkan sebuah fungsi EventStatus() untuk memeriksa event sejak pengulangan atau iterasi terakhir. Perhatikan modifikasi pada listing berikut…

for( ;; ) 
{ 
  if( TimerExpired ) 
  { 
    Counter++; 
// Memproses siklus kontrol setiap pengulangan lainnya. 
    switch( Counter ) 
    { case 0 : ControlCycle(); 
               break; 
      case 1 : Counter = -1; 
               break; 
    } 
// Memproses hanya satu fungsi saja. Hanya memproses 
// sebuah fungsi jika ada sesuatu yang dikerjakan. 
    EventStatus() 
// memeriksa setiap event sejak iterasi terakhir. 
    switch( EventStatus() ) 
    { case EVENT_KEY : ScanKeypad(); 
                       UpdateLCD(); 
                       break; 
      case EVENT_232 : ProcessRS232Characters(); 
                       break; 
      case EVENT_TCP : ProcessHTTPRequests(); 
                       break; 
    } 
    TimerExpired = false; 
  } 
}

EVALUASI KELEBIHAN

  • Ukuran kode program tetap kecil
  • Tidak bergantung pada kode sumber lainnya
  • Tidak dipusingkan dengan masalah RAM, ROM dan proses yang biasa dijumpai dalam implementasi RTOS

EVALUASI KELEMAHAN

  • Tidak mampu menangani persyaratan pewaktuan yang semakin kompleks
  • Tidak terskala dengan baik, artinya semakin kompleks semakin bikin mual saja (maksudnya makin rumit programnya)
  • Pewaktuan sulit dievaluasi maupun dijaga berkaitan dengan interdependensi antar fungsi yang berbeda

KESIMPULAN Pendekatan kalang sederhana sangat baik untuk aplikasi sederhana dan aplikasi dengan persyaratan pewaktuan yang fleksibel. Solusi dengan pendekatan ini akan menjadi semakin kompleks, sulit di analisis dan dipelihara untuk sistem-sistem yang semakin besar. Bergabunglah dengan GROUP PINTAR EMBEDDED SYSTEM di Facebook.

[bersambung]

This entry was posted in Mikrokontroler and tagged , , , , , . Bookmark the permalink.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s