Gömülü sistemlerde OOP

Başlatan kimlenbu, 20 Mart 2020, 11:31:44

kimlenbu

Selamlar,

Projelerimde henüz RTOS kullanmıyorum, çok fazla döküman okudum, teorik olarak kullanabilecek durumdayım ama derdime derman olur mu emin değilim.

Şu an kodlarımı standart "Super Loop" yani while(1) içinde koşturuyorum. Ama yeri geliyor binlerce satırlık kod yazıyorum ve Flag'lar ile bütün mekanizma ayakta duruyor.

Delay kullanımından elimden geldiğince kaçınıyorum, yeri geliyor interrupt, yeri geliyor dma, yeri geliyor systick ile kontrol ederek bir nevi kendi rtos'umu oluşturuyorum.

Kod tekrar kullanılabilirliği açısından kodu fonksiyonlara bölüyorum. Misal veriyi al, veriyi gönder, veriyi ayrıştır, veriyi buffer'a at. Fonksiyon isimlerini ve açıklamalarını yazıyorum, değişken isimlerini adına bakınca anlaşılabilecek şekilde koyuyorum ve "PascalCase" kullanıyorum.

Sensör, sd kart, ekran vs için olan kodları kütüphanelere bölüyorum, sonraki projelerime kolayca dahil edebiliyorum ve main içinde kalabalık etmiyorlar.

Ama debug etmek oldukça sıkıntılı bir hal alıyor. Misal usarttan veri geliyor, ne verisi gelmiş diye flag kontrol ediyorsun, veriyi ayrıştırıyorsun, başka bir flag set ediliyor, bunu kullanıyorsun, o duruma göre başka bir şey tetikleniyor, "extern" kullanılmış değişkenler nerede tanımlanmış, boyutu neydi derken kendi yazdığım koda 1 ay sonra bakınca bazen sadece bir verinin gelişinden işlenişine kadar olan kısmı hatırlayıp anlamam 1 saatimi alıyor.

Siz bu işin altından nasıl kalkıyorsunuz ? RTOS büyük projelerde hayat kurtarır mı ? Yoksa artık flowchart da hazırlama zamanım gelmiş mi ? Program yazarken yapı kafamda şekillenir direkt koda aktarabilirim ama sonradan bakarken ızdırap oluyor.


mufitsozen

Sordugunuz sorunun OOP ile alakasi yok maalesef.
Aptalca bir soru yoktur ve hiç kimse soru sormayı bırakana kadar aptal olmaz.

foseydon

super loop(round-robin) ve RTOS sistem kaynaklarının kullanımı ile alakalı. birisinde kaynakları programcı elle(kurduğu algoritma ile) ayarlar, diğerinde scheduler var kaynakları öncelik sırasına göre o paylaştırır. ikisininde avantajı dezavantajı var. bunların kod okunulabilrliği ile alakası yok.

RTOS zaman ayarlaması yapman gereken, zaman kritik işlerde hayat kurtarıyor. misal kontrol loop'un var, belirli zamanlarda ölçüm alıp, hesap yaptıktan sonra bir iş yapman gerekiyor, bu noktada RTOS işine yarıyor. Özellikle sistem birçok iş yapıyorsa programci olarak ne ne zaman çağrılıyor takip etmen zor. Delay kullananı her koşulda dövüyorlar.

Şahsi kanaatim, gömülü sistemlerde kod yeniden kullınabilirliği fazla değil. elbette birşeyler aktarıyorsun ama en optimum durumda bile kodun %70-80ini yazman gerekiyor.

Kod okunulabilirliği direk yazımla alakalı. Önce değişken ve fonksiyon isimleri. İsimleri güzel koyarsan işin yarısı tamam. Eksik gördüğün yeride comment ile tamamlayacaksın. İsimlerden sonra kodlama şekli de ne yapıldığını anlatmada etkili. Misal modbus iletişimi yapıyorsun

void modbusProcess() {
  if( modbus.RXFrameReady ) {
	modbus.state = PROCESSING;
    if ( verifyDeviceAddress() ) {
        if( verifyFunctionCode() ) {
          if( verifyDataAddress() ) {
            if ( verifyDataValue() ) {
              if ( verifyCRC() ) {
                modbus.function();
		modbus.state = TX;
              }else {
                  // invalid CRC
              }
            }else {
              modbusSetError(ILLEGAL_DATA_VALUE);
            }
          }else {
            modbusSetError(ILLEGAL_DATA_ADDRESS);
          }
        }else {
          modbusSetError(ILLEGAL_FUNCTION);
        }
      }
    }
}

gibi yazarsan ne yapıldığını 1 sene sonra da baksan anımsarsın. işin güzeli senden sonra bakan da anlar.

tüm bunların OOP ile de alakası yok. programlama dilleri insanlar içindir, makineler için değildir. makine 1 ve 0 dan anlar. programlama dilleri insanlar ne yapıldığını anlasın diyedir.

brandice5

#3
Benim nacizane tavsiyem kodu bu şekilde yazmanın okunurluğu arttıracağı yönündedir.

void modbusProcess()
{
    if (!modbus.RXFrameReady)
        return;
  
    modbus.state = PROCESSING;

    if (!verifyDeviceAddress())
        return;
		
    if (!verifyFunctionCode()) {
        modbusSetError(ILLEGAL_FUNCTION);
        return;
    }
			
    if (!verifyDataAddress()) {
        modbusSetError(ILLEGAL_DATA_ADDRESS);
        return;
    }
			  
    if (!verifyDataValue()) {
        modbusSetError(ILLEGAL_DATA_VALUE);
        return;
    }
		
    if (!verifyCRC()) {
        // invalid CRC
        return;
    }
		
    modbus.function();
    modbus.state = TX;
}

foseydon

@brandice5 yoğurt yiyiştir hocam. saygı duyarım. ben de misal tek expression'lı bile olsa blockları kapatıyorum.

    
if (!modbus.RXFrameReady)
    return;
yerine
if (!modbus.RXFrameReady){
    return;
}
şeklinde. dediğim gibi bunlar yoğurt yiyiştir biraz. önemli olan, bence, 3. bir göz okuduğu zaman hangi fonksiyon ne iş yapıyor, program ne yapıyor fazla zorlanmadan anlayabilmesi.

volkanunal

İlgili başlık için takip edilebilecek bir kanal bırakıyorum.

https://www.youtube.com/user/StateMachineCOM
Primum nil nocere

qeek

Hocam bende kütüphane yazarken dediğiniz zorluğu çekiyordum. Ne nereden nasıl gelmiş gibi ama bir süre sonra dediğiniz gibi kafa karıştırıyor. Bende kütüphanelerime fazla yorum satırı yazıp sonrada bunları doxygen adlı programa veriyorum. O bana ne nereye bağlı nereden geliyor gibi şeylerin hepsini çıkartıyor aynı zamanda da elimde bir dökümantasyon olmuş oluyor sonra kullanan arkadaşlar rahat ediyor. Sizde bir bakabilirsiniz işinizi görebilir belki.