Health Monitoring etiketine sahip kayıtlar gösteriliyor. Tüm kayıtları göster
Health Monitoring etiketine sahip kayıtlar gösteriliyor. Tüm kayıtları göster

22 Haziran 2014 Pazar

VxWorks 653 Health Monitor

Health Monitor Nedir?

Health Monitor ARINC 653 standardından geliyor.Health Monitor herhangi bir hata durumunda ne yapılması gerektiğini belirten bir tablo gibi düşünülebilir. 


Hangi zamanda hangi seviye HM tablosunun kullanılacağı SystemState olarak anılan sistemin durumuna göre belirlenir. Örneğin partition normal mode'a gelmeden hata verirse module os seviyesindeki error handler çağırılır. Eğer bir hata, oluştuğu seviyede ele alınmaz ise, bir üst seviyeye çıkarılır ve bu seviyedeki error handler tarafından işlenir.

XML ile ayarlanabilen 3 seviyede mevcut. Bunlar "Process Seviyesi", "Partition Seviyesi", "Module Seviyesi". Process seviyesi haricindeki diğer tablolar XML ile giriliyor.

Aşağıda tüm XML'i kapatılmış olarak gösteren bir örnek var. ARINC 653 standardında olmayan SystemHMTable tablosunu da aşağıda açıkladım.
<HealthMonitor>
   <SystemHMTable/>

   <ModuleHMTable/>
   <PartitionHMTable>
</HealthMonitor>

Process Seviyesi Health Monitor Ayarları
Konuyu Process Seviyesi Health Monitor başlıklı yazıya taşıdım.

Partition Seviyesi Health Monitor Ayarları
Aşağıda bölümleme (partition) için XML örneği var.ErrorAction alanının karşısında yazan isim, hataya oluşunca çalıştırılması istenen kod parçasını belirtmek için kullanılıyor.

Her partition için ayrı bir HM tablosu bulunabilir. Eğer istenirse tüm partition'lar için aynı tablo da kullanılabilir.

Örnektede açıklandığı gibi, hmDefaultHandler partition'ı yeniden başlatır.hmDbgDefaultHandler ise partition'ı durdurur. Geliştirme aşamasında HME_HM_DEADLINE_MISSED hatası alınırsa partition'ın yeniden başlatılmasının sebebi budur.

<PartitionHMTable Name="partition1Hm">
 <SystemState>
  <ErrorIDAction Error Identifier="HME_UNKNOWN" ErrorAction="hmDefaultHandler"/>
  <ErrorIDAction Error Identifier="HME_NUMERIC_ERROR" ErrorAction=""/>
  <ErrorIDAction Error Identifier="HME_POWER_FAIL" ErrorAction="hmDH_HME_POWER_FAIL"/>
  <ErrorIDAction Error Identifier="HME_KERNEL" ErrorAction="hmDH_HME_KERNEL"/>
  <ErrorIDAction Error Identifier="HME_CONFIG_ERROR" ErrorAction="hmDH_EventLog"/>
  <ErrorIDAction Error Identifier="HME_INIT_ERROR" ErrorAction="hmDH_HME_INIT_ERROR"/>
  <ErrorIDAction Error Identifier="HME_PARTITION_OVERFLOW" ErrorAction="hmDefaultHandler"/>
  <ErrorIDAction Error Identifier="HME_PARTITION_MODE_SET" ErrorAction="hmDH_HME_PARTITION_MODE_SET"/>
  <ErrorIDAction Error Identifier="HME_APEX_INTERNAL_ERROR" ErrorAction="hmDefaultHandler"/>
  <ErrorIDAction Error Identifier="HME_HM_INTERNAL_ERROR" ErrorAction="hmDefaultHandler"/>
  <ErrorIDAction Error Identifier="HME_PORT_INTERNAL_ERROR" ErrorAction="hmDefaultHandler"/>
  <ErrorIDAction Error Identifier="HME_LOST_TICKS" ErrorAction="hmDM_LOST_TICKS"/>
  <ErrorIDAction Error Identifier="HME_HM_ERROR" ErrorAction="hmDefaultHandler"/>
  <ErrorIDAction Error Identifier="HME_HMQ_OVERFLOW" ErrorAction="hmDefaultHandler"/>
  <ErrorIDAction Error Identifier="HME_DATA_LOSS" ErrorAction=""/>
   <ErrorIDAction Error Identifier="HME_HM_DEADLINE_MISSED" ErrorAction="hmDefaultHandler"/>
  <ErrorIDAction Error Identifier="HM_MSG" ErrorAction="hmDH_EventLog"/>
  <ErrorIDAction Error Identifier="HME_DEFAULT" ErrorAction=""/>
 <Settings maxQueueDepth="34" queueThresHold="32" stackSize="16384" maxLogEntries="100" logEntriesThreshold="98" attributesMask="0x00000001" notificationHandler ="" notificationMaxQueueDepth="0" eventFilterMask="0xFFFFFFFF" maxErrorHandlerQueueDepth="128" errorHandlerQueueThreshold="126"
  </Settings>
  </SystemState>
</PartitionHMTable>

HME_LOST_TICKS: Such an event is received when system clock interrupts were lost

HME_POWER_FAIL: Such an event is received when the power source of the module failed for an amount of time less than the RAM holding time. This means that when this event is received the power should be back on, and the RAM should not be affected bythis short power loss. However all of the devices on the module have been reset.

XML ve Kod Eşleşmesi
XML'de tanımlanan isimler ile çağrılacak metodlar vxworks653-x.y.z.\target\config\comps\src\usrHm.c dosyasındaki tabloda eşleştiriliyor.

extern STATUS myHandler (HM_EVENT_ID event);

HM_HANDLER_TBL_ENTRY hmHandlerTbl [] =
{
    .....//Original handlers
    {"myHandler" ,myHandler}
};

Kendi Metodumuz
Eğer kendimiz yeni bir handler yazmak istersek, ModuleOS projesine yeni bir metod yazmalıyız ve metodu yukarıdaki tabloya eklemeliyiz. Yeni metodun imzası şöyle:

STATUS myHandler (HM_EVENT_ID event){
 return OK;
}

Module Seviyesi Health Monitor Ayarları
Bu tabl PartitionHMTable ile hemen hemen aynı olduğu için tekrar etmek istemedim.

System Seviyesi Health Monitor Ayarları
Aşağıdaki cümleler önemli
 * Defines the level of an error (Module, Partition, Process) based on the error and the state of the system.
Yani bu tablo bir çeşit dispatcher gibi çalışıyor. Gelen hatayı uygun olan seviyeye yönlendiriyor.

Bu tablo oldukça kısa.
<SystemHMTable Name="systemHm">
    <SystemState SystemState="HM_PARTITION_MODE">
        <ErrorIDLevel ErrorIdentifier="HME_DEFAULT" ErrorLevel="HM_PARTITION_LVL"/>
    </SystemState>
    <SystemState SystemState="HM_MODULE_MODE">
        <ErrorIDLevel ErrorIdentifier="HME_DEFAULT" ErrorLevel="HM_MODULE_LVL"/>
    </SystemState>
    <SystemState SystemState="HM_PROCESS_MODE">
        <ErrorIDLevel ErrorIdentifier="HME_DEFAULT" ErrorLevel="HM_MODULE_LVL"/>
    </SystemState>
</SystemHMTable>

VxWorks 653 Process Seviyesi Health Monitor

Process Seviyesi Health Monitor Ayarları

XML haricinde uygulamamız için Health Monitoring işlevini yerine getiren kod yazmak ta mümkün.
There is potential for a process health monitor for each partition. The application must create the process health monitor by calling hmCreateErrorHandler (bu native API) or for ARINC 653 applications by issuing CREATE_ERROR_HANDLER. The routines create a highest priority task in the partition OS with which to run the process health monitor handler.

Uygulamamız için hata raise edilirse, SystemState uygulamayı belirteceği için kendi kodumuz çalışır.
Aşağıdaki cümleler önemli.
 * The HM will not violate partitioning when handling process level errors.
 * The error handler process is active in NORMAL mode only.

Error Handler Yaratmak

Eğer uygulamamız için de health monitor eklemek istiyorsak CREATE_ERROR_HANDLER metodunu kullanarak kod yazmamız gerekir. Buradaki açıklama önemli
The error handler task is invoked when the RTOS 653 health monitor detects a process level error
Aşağıda error handler yaratmak için örnek kod var:

STACK_SIZE_TYPE stackSize = 1024 // 1 KB
RETURN_CODE_TYPE returnCode;
//Shall create a special process with the highest priority, ENTRY_POINT and STACK_SIZE attributes.for the current partition,
CREATE_ERROR_HANDLER ((SYSTEM_ADDRESS_TYPE)ErrorHandler, stackSize, returnCode);

CREATE_ERROR_HANDLER Metodunun İçi

Metod içeride yeni bir task yaratıp bu task ile haberleşmek için msgQueue oluşturuyor.

CREATE_ERROR_HANDLER (SYSTEM_ADDRESS_TYPE ENTRY_POINT,
                                                       STACK_SIZE_TYPE STACK_SIZE,
                                                       RETURNCODE_TYPE* RETURNCODE) {
      //... do some stuff
   if (hmErrorHandlerCreate ((FUNCPTR)ENTRY_POINT,STACK_SIZE,1) {...}
}

hmErrorHandlerCreate Metodunun İçi

Aşağıdaki kod parçasında msgQCreate metodunun çağırıldığı görülebilir.

STATUS hmErrorHandlerCreate (...) {
   //... do some stuff
   hmCtxId->ehQueueId = msgQCreate (hmCtxId->ehMaxQueueDepth,
                                                                sizeof(HM_EVENT),
                                                                MSG_Q_FIFIO);

  hmCtxId->ehTaskId = taskCreat ("tHmErrorHandler"// task name
                                                        hmCtxId->ehTaskPrio, // 0. priority
                                                        options,
                                                        stackSize,
                                                        errorHandler,
                                                        param,
                                                        0,0,0,0,0,0,0,0,0);
}

Error Handler Metodunda Kullanılabilecek Çağrılar

VxWorks'ün sunduğu kütüphaneler kullanılabildiği gibi ARINC 653 portlarına da erişmek mümkün. Çünkü portlar partition seviyesinde açılıyor.

Error Handler Metoduna Gelen Hata Kodları
Error Handler metodunda yakalamamız gereken hata kodlarını açıklayan şu cümle önemli.
The following are process-level APEX error codes:
  • APPLICATION_ERROR
  • DEADLINE_MISSED
  • HARDWARE_FAULT
  • ILLEGAL_REQUEST
  • MEMORY_VIOLATION
  • NUMERIC_ERROR : Floating point işleminde overflow, sıfıra bölme vb. olursa bu hata gönderilir. 
  • POWER_FAIL
  • STACK_OVERFLOW
Örnek Error Handler Metodu

#include "taskLib.h"
//Hata alan uygulamayı durdurma örneği
void ApplErrorHandler (){
    ERROR_STATUS_TYPE errorStatus;
    RETURN_CODE_TYPE returnCode;

    while (true){
        GET_ERROR_STATUS  (&errorStatus,&returnCode);
        if (returnCode == NO_ERROR){
            switch (errorStatus.ERROR_CODE){
                case APPLICATION_ERROR:{
                    //Log error
                    printf ("Error code : %d %s \n",errorStatus.ERROR_CODE,errorStatus.MESSAGE);
             
                    //veya istenirse loglama amacıyla port'a yazılabilir
                    SEND_QUEUING_MESSAGE (portNo,
                                                                        errorStatus.MESSAGE,
                                                                        strlen(errorStatus.MESSAGE),
                                                                        0 , //timeout
                                                                        &returnCode);

                    //Suspend task for debugging

                    int taskId = taskIdFromProcIdGet (errorStatus.FAILED_PROCESS_ID);
                    taskSuspend (taskId);//tasklib icinde
                    break;
                }//case
            }//switch
        }//if
        STOP_SELF();
    }//while
}

Klasik Bir Error Handler
Klasik bir error handler içinde call stack yazdırılır ve hata veren partition durdurulur. Hata adresini almak için taskInfo kütüphanesindeki taskRegsGet() kullanılabilir.

int taskId = taskIdFromProcIdGet (errorStatus.FAILED_PROCESS_ID);
REG_SET regs;
//Get CPU registers with VxWorks native api
if (taskRegsGet (taskId,&reg) ==  OK){
  printf ("0x%.8x",regs.gpr [1]);//General Purpose Register error address

}

Bir başka örnekte traceLib içindeki trcStack() metodu kullanılmış.

REG_SET regs;
taskRegsGet(taskId, &regs);
trcStack(&regs, (FUNCPTR) wpiCleanTracePrint, taskId);