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>