3 Eylül 2021 Cuma

ARINC 653 GET_TIME metodu - Monotonic Saat

GET_TIME
Sistemin belli bir anından itibaren başlatılan monotonic bir saattir. Çözünürlüğü nanosaniye seviyesinde. Bazı sistemlerde GET_TIME metodu allta sysTimestampGet64 metodunu çağırıyor. Bu metod Intel 8253 Time kütüphanesinde tanımlı (i8253Timer.c dosyası).8253 için açıklama şöyle
The 8253 is a timer circuit, containing three timers able to generate timed interrupts or square waves output with programmed frequencies. 
Bu metodun açıklamasında
"By default, the system clock is based on Time Base Register (TBR)"
cümlesi geçiyor. TBR'nin aynı Windows'taki QueryPerformanceCounter mantığıyla çalışır. Yani tick count saniye başına olması gereken bir sabite (frekansa) bölünüyor.
The TB register is incremented periodically with an implementation-dependent frequency, which may not be constant
Bu metod iki farklı bölümlemede tarafından çağrılsa bile, en alt seviyedeki ortak TBR okunduğu için problem olmaz.

24 Kasım 2015 Salı

GNU Binary Araçları

Giriş
GNU projesi kapsamında binary dosyalarla çalışmayı kolaylaştıran bazı araçlar geliyor.

nm
nm komutu yazısına taşıdım.

objdump
objdump komutu yazısına taşıdım

strings
-t seçeneği
-t ile string'in offset değeri bulunur. test isimli bir uygulamamız olsun. Bu uygulama içinde belli bir string şöyle aranılır.
$ strings -t d test | grep /usr/tmp
1460 /usr/tmp
addr2line
Elimizde gdb yoksa ve hata adresini biliyorsak bu aracı kullanabiliriz.

Bu aracı addr2line -f -C -s -e parametreleri ile çalıştırmak lazım
-f : Show function names
-C : demangle function names
-s : strip directory names
-e : set the input file name

Örnek:
addr2line -f -C -s -e ..\..\mybin\debug\mytest.sm 0xHATAADDRESS


30 Ocak 2015 Cuma

Aviyonik Mimariler

Giriş
Havacılıkta kullanılan mimariler tarihsel gelişim sırasıyla şöyle
1. Distributed Analogue Architecture

Bu mimaride ana bileşenler kablolar ile bağlanıyor. Veriyolu (bus) kullanılmıyor. Neticede tam bir kablo yumağı ortaya çıkıyor. Araca değişiklik yapmak son derece güç oluyor. 1950 ve 1960'larda üretilen bir çok hava aracı bu mimari ile yapılmış durumda. Bu yazdıklarım sistemin tasarımcılarına eleştiri mahiyetinde anlaşılmamalı. O zamanki çalışanlar ellerindeki teknoloji ile gayet başarılı işler çıkartmışlar. Bu mimariyi kullanan bazı araçlar şunlar: Boeing 707 , VC10, BAC 1-11, DC-9 ve ilk Boeing 737'ler.

Boeing 707'den türetilen E-3,E-4,E-6 gibi araçlar, VC-10, KC-135 halen kullanımdalar.
2. Distributed Digital Architecture
Bilgisayarların analog cihazların yerini almaya başlaması bu mimarinin kabul görmesine sebep oldu. Bu mimaride her ana bileşen kendi bilgisayarına sahiptir. Ana bileşenler birbirlerine bir veriyolu (bus) ile bağlanırlar. Sivil uçaklarda genellikle ARINC 429 kullanılır. Bu mimariyi kullanan bazı araçlar şunlar: Boeing 737 ve 767, Bombardier Global Express, Jaguar, Nimrod MR2, Tornado, Sea Harrier.
3. Federated Digital Architecture

Bu mimaride MIL-STD-1553B veriyolu kullanılır. Bu mimariyi kullanan bazı araçlar şunlar: F-16, SAAB Gripen, Boeing AH-64 C/D. Sivil araçlar bu mimariyi hemen hiç kullanmadılar. Onun yerine ARINC 629 standardını geliştirdiler. Askeri araçlar da ARINC 629'u kullanmazlar.

ARINC 629'u şu ana kadar kullan tek sivil araç Boeing 777 oldu.

4. Integrated Modular Architecture

Ve günümüze geldik.

Integrated Moduler Avionics (IMA) yeni gelişmekte olan bir kavram. Havacılıkta sıkça görülen "Federated" mimarinin yerine almaya başladı. Federated mimaride her üretici kendi Line Replaceable Unit (LRU) veya Line Replaceable Module (LRM) birimi ile geliyor ve bunlar hava aracından birleştiriliyor. Ancak bu yöntemde her birim kendi işlemcisi, kartı ve donanımı ile geldiği için, hem aracın ağırlığı hem de güç tüketimi artıyor. Yani kaynaklar verimsiz kullanılıyor. IMA yapısında donanım - yani bellek, işlemci gibi kaynaklar - bir nevi sanallaştırılarak, farklı emniyet seviyesindeki uygulamaların aynı donanım üzerinde koşabilmesi sağlanıyor. Tek bir uygulama tüm belleği, kaynakları ve işlemciyi (cpu starvation) tüketemiyor.

Aşağıdaki şekilde durum görülebilir.

IMA yapısının bir diğer artısı ise yazılımı donanımdan soyutlaması. Donanım eskise bile, kolaylıkla değiştirilebiliyor.

IMA ile ilgili ilk fikirler ARINC 650 ve ARINC 651 belgelerinde bulunabilir (General purpose hardware and software standards) . ARINC 653 ile yazılım arayüzleri standartlaştırıldı.

IMA Mimarisinden Önce İşletim Sistemleri Nasıldı ?
İşletim sistemi çekirdeği (kernel) ve uygulama aynı adres alanı (address space) içinde koşuyordu. Sağlamlık (Robustness) için farklı kutular koymaktan başka çare kalmıyordu. Kutuları koşturmak için bir çok firma ya kendi gerçek zamanlı işletim sistemini geliştirmiş ya da gerçek zamanlı bir işletim sistemini sertifikasyona uygun olacak hale getirmişti.

19 Ocak 2015 Pazartesi

Windows'ta ARINC 653 Gerçekleştirimi - Queuing Port

UDP Socket ile gerçekleştirimi
Tüm kodlarda kullanılan bir std::map veriyapımız olsun.

std::map<int,SOCKET> dataMap;

CREATE_QUEUING_PORT
Socket açılır ve bir map içinde saklanır.

CREATE_QUEUING_PORT (
    QUEUING_PORT_NAME_TYPE dummy1,
    MESSAGE_SIZE_TYPE dummy2,
    MESSAGE_RANGE_TYPE dummy3,
    PORT_DIRECTION_TYPE portDirection,
    QUEUING_DISCIPLINE_TYPE dummy4,
    QUEUING_PORT_ID_TYPE portID,
    RETURN_CODE_TYPE * result) {
        SOCKET s = socket (AF_INET,SOCK_DGRAM,IPPROTO_UDP);
        if (portDirection == DESTINATION){ 
            //Bind UDP server
            struct sockaddr_in sAddr = {};
            sAddr.sin_family = AF_INET;
            sAddr.sin_port = portID;
            sAddr.sin_addr.s_add = inet_addr ("127.0.0.1");
            bind (sock,(struct sockaddr *) &sAddr, sizeof(sAddr));
         }
         //Save socket handle portID as key
         map [portID] = s;
         result = SUCCESS;
    }

SEND_QUEUING_MESSAGE
Veri socket üzerinden gönderilir.

SEND_QUEUING_MESSAGE (
    QUEUING_PORT_ID_TYPE portID,
    SYSTEM_TIME_TYPE dummy1,
    MESSAGE_ADDR_TYPE data,
    MESSAGE_SIZE_TYPE dataLength,
    RETURN_CODE_TYPE * result) {
        SOCKET s = dateMap [ portID ];
        int bytesSent = sendto (s, (char*) data, dataLength , 0);
        result = bytesSent < 0 ? FAIL : SUCCESS;
}

RECEIVE_QUEUING_MESSAGE
Veri socket üzerinden alınır.

RECEIVE_QUEUING_MESSAGE (
    QUEUING_PORT_ID_TYPE portID,
    SYSTEM_TIME_TYPE dummy1,
    MESSAGE_ADDR_TYPE data,
    MESSAGE_SIZE_TYPE dataLength,
    RETURN_CODE_TYPE * result) {
        SOCKET s = dateMap [ portID ];
        int bytesRcvd = recv (s, (char*) data, dataLength , 0);
        result = bytesRcvd < 0 ? FAIL : SUCCESS;
}


1 Aralık 2014 Pazartesi

cpuMonitorLib

Bu kütüphane ile bölümlemelerin ne kadar işlemci kullandıkları görülebilir.

PuTTy üzerinde
[coreOS]-> yazısı görününce

cpuMonitorStart ile ölçüm başlatılır.
cpuMonitorReport ile rapor PuTTy ile görülür
cpumonitorStop ile ölçüm durdurulur

Eğer coreOS cpuMonitorLib bileşenini içermiyorsa ekranda
No symbol "cpuMonitorStart" in protection domain "coreOS" yazısı çıkar.

13 Ekim 2014 Pazartesi

ARINC 653 Bölümlenmeler Arası İletişim

Not : VxWorks 563 ve Portlar yazısına da bakabilirsiniz.

Giriş
ARINC 653 bir işletim sistemi API'si. Aynen POSIX'te olduğu gibi metod imzalarını tanımlıyor. Metodların gerçekleştirilmesi işletim sistemi üreticilerine bırakılmış.

Nasıl ki POSIX'te Inter Process Communication yöntemleri varsa, ARINC 653'te Inter Partition Communication - yani Bölümlenmeler Arası İletişim - yöntemleri tanımlıyor.

Bölümlenmeler Arası (Interpartition) İletişim Yapıları
Bu iletişim yapılarını genel ismi "port". Queeing Port  ve Sampling Port olarak iki türü var.
İki veya daha fazla portu birbirine bağlayan yapıya ise Channel deniliyor.

Broadcast, Multicast and Unicast Messages
This standard provides support for broadcast, multicast and unicast messages. A broadcast message is sent from a single source to all destinations. A multicast message is sent from a single source to more than one destination. A unicast message is sent from a single source to a single destination. For queuing port ony unicast messages are required.

Overflow
Application software is responsible for handling overflow when the queuing port is full.

Queuing Port
Bir çeşit FIFO kuyruk. Kuyruk dolarsa yazan taraf bloke olabiliyor. Bir port ile çalışmak için toplam 5 tane metod var:
  1. CREATE_QUEUING_PORT
  2. SEND_QUEUING_MESSAGE
  3. RECEIVE_QUEUING_MESSAGE
  4. GET_QUEUING_PORT_ID
  5. GET_QUEUING_PORT_STATUS
CREATE_QUEUING_PORT ile ismi olan bir port yaratılır. Bu metod isme karşılık bir port ID'si döner. Geri kalan tüm SEND, RECEIVE, GET metodlarında bu port ID'si kullanılır.

CREATE_QUEUING_PORT metodu
Yeni bir port yaratır. Metodun imzası şöyledir.

extern void CREATE_QUEUING_PORT (
   /*in */ QUEUING_PORT_NAME_TYPE    QUEUING_PORT_NAME, //Portun ismi
   /*in */ MESSAGE_SIZE_TYPE         MAX_MESSAGE_SIZE,  //Bir mesajın büyüklüğü
   /*in */ MESSAGE_RANGE_TYPE        MAX_NB_MESSAGE,    //Toplam mesaj sayısı
   /*in */ PORT_DIRECTION_TYPE       PORT_DIRECTION,    //Source veya Destination
   /*in */ QUEUING_DISCIPLINE_TYPE   QUEUING_DISCIPLINE,//FIFO veya PRIORITY
   /*out*/ QUEUING_PORT_ID_TYPE      *QUEUING_PORT_ID,  //Port ID'si
   /*out*/ RETURN_CODE_TYPE          *RETURN_CODE       //Çağrı sonucu
);

QUEUING_DISCIPLINE parametresinin varlığı aynı porta partition içindeki farklı thread'lerin yazabileceğini gösterir. Kuyruk doluysa thread bekletilir. İlk yer açıldığında beklemekte olan hangi threadin devreye gireceğini bu parametre belirler.

Dikkat edilmesi gereken nokta portlara yazılabilecek mesaj sayısının üst sınırının olması. Yani portları sınırsız kuyruk gibi düşünmek doğru değil. Mesaj sayısının üst sınırı
#define SYSTEM_LIMIT_NUMBER_OF_MESSAGES        512    /* module scope */
ile tanımlı.Dolayısıyla MAX_NB_MESSAGE, yukarıdaki sabiti geçemez.


SEND_QUEUING_MESSAGE metodu
Kuyruğa yeni bir eleman ekler. Metodun imzası şöyledir. Bu metodu kullanabilmek için CREATE_PORT metodunun QUEUING_DISCIPLINE = SOURCE olarak çağrılmış olması gerekir.

extern void SEND_QUEUING_MESSAGE (
      /*in */ QUEUING_PORT_ID_TYPE      QUEUING_PORT_ID,
      /*in */ MESSAGE_ADDR_TYPE         MESSAGE_ADDR,       /* by reference */
      /*in */ MESSAGE_SIZE_TYPE         LENGTH,
      /*in */ SYSTEM_TIME_TYPE          TIME_OUT,
      /*out*/ RETURN_CODE_TYPE          *RETURN_CODE);

Bu metodun en önemli parametresi TIME_OUT. Metodun blocking veya non-blocking olmasına bu parametre ile karar veririz. TIME_OUT parametresi 0 (sıfır) ise metod yazma işlemini gerçekleştiremezse hemen döner. Bu durumda sonuç NOT_AVAILABLE değerini alır. 0'dan büyük bir değer ise belirtilen süre kadar kuyrukta yer açılmasını bekler. Belirtilen süreden dana önce yer açılırsa sonuç NO_ERROR değeri ile döner. Eğer yer açılmazsa sonuç TIMED_OUT değerini alır.

Örnek'te sonsuza kadar kuyrukta yer açılması bekleniyor.
QUEUING_PORT_ID_TYPE fd;                     //Port ID
char msg[1025] = ... ;                                        //Populate array
MESSAGE_SIZE_TYPE length = sizof(msg);//Length of msg
RETURN_CODE_TYPE rc;                            //Return code
SEND_QUEUING_MESSAGE (fd,
                        (MESSAGE_ADDR_TYPE)msg,//byte array
                        length,
                        INFINITE_TIME_VALUE,
                        &rc
                     );

Tipik ARINC 653 uygulamalarında port ile bir timer beraber kullanılır. Timer expire olunca periyodik göndermesi gereken mesajlar porta yazılır.

Yine tipil ARINC 653 uygulamalarında port yapısı bir channel yapısına bağlı olduğu için aynı port numaralarını kullanan farklı uygulamalar kuyruğa yazabilirler.

Şekilde aynı port numaralarını kullanan farklı uygulamaların kuyruğa yazıp, okuyabildikleri görülebilir.

RECEIVE_QUEUING_MESSAGE metodu

Bu metodu kullanabilmek için CREATE_PORT metodunun QUEUING_DISCIPLINE = DESTINATION olarak çağrılmış olması gerekir.

Tipik bir ARINC 653 uygulaması portları saklanan tüm mesajları bitirinceye kadar okur.

while (true) {
  if (ReadPort (...)) {
     ProcessPort (...);
  } else  {
    break;
  }
}

GET_QUEUING_PORT_ID metodu
Açıklama yaz.

GET_QUEUING_PORT_STATUS metodu
Açıklama yaz.

Sampling Port
Tek bir eleman alıyor. Her güncelleme işlemi bir önceki bilginin üzerine yazar. Okuyan taraf her zaman en son bilgiyi çekiyor.
Bir port ile çalışmak için toplam 5 tane metod var:

  1. CREATE_SAMPLING_PORT
  2. WRITE_SAMPLING_MESSAGE
  3. READ_SAMPLING_MESSAGE
  4. GET_SAMPLING_PORT_ID
  5. GET_SAMPLING_PORT_STATUS


CREATE_SAMPLING_PORT metodu
Yeni bir port yaratır. Metodun imzası şöyledir.

extern void CREATE_SAMPLING_PORT ( 
  /*in */ SAMPLING_PORT_NAME_TYPE    SAMPLING_PORT_NAME, //Portun ismi
  /*in */ MESSAGE_SIZE_TYPE          MAX_MESSAGE_SIZE,   //Elemanın büyüklüğü
  /*in */ PORT_DIRECTION_TYPE        PORT_DIRECTION,     //Source veya Destination
  /*in */ SYSTEM_TIME_TYPE           REFRESH_PERIOD,     //Yenilenme süresi (san.)
  /*out*/ SAMPLING_PORT_ID_TYPE      *SAMPLING_PORT_ID,  //Port ID'si
  /*out*/ RETURN_CODE_TYPE           *RETURN_CODE        //Çağrı sonucu
); 

Metod CREATE_QUEUING_PORT metoduna çok benzer. Ancak bu sefer porta kaç tane mesaj yazılacağı belirtmeyiz çünkü bu port türünde sadece tek bir eleman bulunur. Onun yerine bu tek elemanın ne kadar sıklıkta yenilenmesi gerektiğini belirtiriz.

WRITE_SAMPLING_MESSAGE metodu
Porttaki tek elemanı günceller. Kaynak port (source) için Refresh Period değeri anlamsızdır.

READ_SAMPLING_MESSAGE metodu
Metodun imzası aşağıda.
extern void READ_SAMPLING_MESSAGE ( 
       /*in */ SAMPLING_PORT_ID_TYPE      SAMPLING_PORT_ID, 
       /*out*/ MESSAGE_ADDR_TYPE          MESSAGE_ADDR, 
       /*out*/ MESSAGE_SIZE_TYPE          *LENGTH, 
       /*out*/ VALIDITY_TYPE              *VALIDITY, 
       /*out*/ RETURN_CODE_TYPE           *RETURN_CODE ); 

Sampling port'a "Refresh Period" değeri atanır. Bu değer saniye cinsindendir, okunan verinin güncel olup olmadığını belirtir. Örneğin 100 milisaniye vermek için 0.1 yazılır. Eğer hiç süresi dolmayan bir port yaratılmak istenirse, -1 değeri verilir.

Sampling Portu okuyan kod kabaca şöyle çalışır.

UINT64 curTime = sysTimestamp64Get();
UINT64 diffTime = sysTimestamp64DiffToNSec (curTime,msgTimeStamp,0ull);
if (TA_IS_INFINITE (sportId->refreshPeriod) ||
    TA_LT (diffTime,sportId->refreshPeriod)      ||
    TA_EQ (diffTime,sportId->refreshPeriod) {
  *VALIDITY = VALID;
}else {
   *VALIDITY =INVALID;
}

GET_SAMPLING_PORT_ID metodu
Açıklama yaz.

GET_SAMPLING_PORT_STATUS metodu
Açıklama yaz.


Okuma İşlemini Gerçekleştiren Uygulananın Yavaş Kaldığı Nasıl Anlaşılır?
Queuing Port'u dolduran uygulama kuyruk doldu hatası alırsa boşaltan uygulamanın yeterince hızlı olmadığını anlarız. Sampling Port kullanırken ise port'u okuyan uygulama DEADLINE  MISS hatası alırsa yeterince hızlı olmadığını anlayabiliriz.


9 Ekim 2014 Perşembe

VxWorks 653 ve Portlar

Giriş
Not : ARINC 653 ve Bölümlemeler Arası İletişim yazısı standardı açıklıyor.

Bölümlemeler arasında iletişim için kullanılan en temel yöntem portlar. İki çeşit port var. Bunlar Queuing Port ve Sampling Port.
APEX partitions within VxWorks 653 module communicate with each other by messages, ports and channels. A message can be sent from one source to one or more destination ports. Processes read from these destination ports.

Messages
Bölünemez bellek alanı olarak tanımlı.
APEX messages are contiguous blocks of data
Mesajlar directed veya broadcast olarak tanımlanıyorlar. Burada ARINC 653 standardından daha farklı bir terminoloji kullanılıyor. Standartta Broadcast, Multicast, Unicast mesajlar tanımlı. VxWorks unicast yerine directed kelimesini tercih etmiş.
A message sent to one destination port is called a directed message. A message sent to multiple destination ports is called a broadcast message.
Port Protocols
Arınc 653'te port protocol tanımlı değil ancak VxWorks 653 şu özellikleri sağlıyor. XML içinde Protocol tag'i tanımlı olmalı ve Source Port SENDER_BLOCK veya RECEIVER_DISCARD protokollerinden birini seçmek zorunda. Destination Port ise NOT_APPLICABLE değerini kullanmak zorunda. Aksi halde XML derleyicisi hata verir.

SENDER_BLOCK
Eğer destination portlardan birisi doluysa, göndereni bekletir. Bu protokolün dezavantajı aşağıda belirtilmiş.
The main drawback is that it introduces coupling between partitions. A non-responsive receiving partition blocks the entire channel, affecting the normal behavior of other receiving partitions.

RECEIVER_DISCARD
Eğer destination portlardan birisi doluysa, bu port pas geçilir ve mesaj boş olan diğer portlara yazılır.

Queuing port XML Örneği
Örnek yaz.

Sampling Port XML Örneği
QueuingPort ile ortak olan tag isimleri Direction, MessageSize ve Name. RefreshRate saniye cinsindendir. Örneğin aşağıdaki 0.050 50 milisaniye anlamına gelir.

<Applications>
    <ApplicationDescription Name = "Partition">
        <MemorySize..../>
        <Ports>
            <SamplingPort
                Direction = "Source"
                MessageSize = "90"
                Name = "OutputPort2"
                RefreshRate = "0.050"/>
        <Ports>
     </ApplicationDescription>
</Applications>

Port ve Connection Bağlantısı
Port'lar için Connection'lar aşağıdaki gibi tanımlanıyor. PortNameRef  partition tagleri içinde tanımlı bir porta atıfta bulunmalı. bu port QueuingPort veya Sampling port ile tanımlanmalı.

<Connections>
 <Channel Id="1">
  <Source PartitionNameRef="Partition1" PortNameRef="To_Part2"/>
  <Destination PartitionNameRef="Partition2" PortNameRef="From_Part1"/>
 </Channel>
</Connections>

Pseudo Partition
Pseudo Partition şöyle açıklanıyor :
A partition that is external to the module. 
Genellikle farklı modul'ler arası ileitşim için kullanılır.

<PseudoPartition Name ="pseudoPartition" Id ="4" Type = "IO_PARTITION">
    <PseudoPartitionDescription>
        <Ports>
            <QueuingPort
                  Atrribute="PSEUDO_PORT"
                  Name = "Output"
                  QueueLength="5"
                  MessageSize="100"
                  Direction = "SOURCE"
                  Protocol="SENDER_BLOCK"
                  DriverName="pseudoQPort" />
        <Ports>
    </PseudoPartitionDescription>
 </PseudoPartition>