2008-10-22 2 views
1

Я хочу знать, как события используются во встроенном системном коде.Обработка событий во встроенном коде

Основная цель состоит в том, чтобы знать, как точно установить флаги событий или сбросить их в коде. и как определить, какая задача использует, какой флаг события и какие биты флага получаются/сброшены каждой задачей.

Пожалуйста, внесите ваши предложения или комментарии по этому поводу.

Заранее благодарен.


(редактировать 1: скопировано из разъяснений в ответ ниже)

Извините за не уточняя детали, необходимые. На самом деле меня интересует анализ любого приложения, написанного на языке C, с использованием операционной системы vxworks/Itron/OSEK. Например, в vxworks есть библиотека eventLib для поддержки обработки событий. Я хочу знать, как можно использовать такие системные процедуры для обработки событий в задаче. Что такое флаг события (он глобальный/локальный ... или что?), Как устанавливать биты любого флага события и которые могут быть возможной зависимостью между флагами задач и событий?

Как задача может ждать нескольких событий в режиме AND и OR? Я наткнулся на один пример, в котором приведенный ниже сценарий выглядит опасным, но почему?

  Scenarios is ==> *[Task1 : Set(e1), Task2 : Wait(e1) and Set(e2), Task3 : Wait(e2) ]*            

Я знаю, что несколько флагов событий ждали одной задачи или круговой зависимостью между несколькими задачами (тупиковой) опасные случаи в отношениях проблемно-событий, но как выше сценарий опасно, я не получаю его ... .Подробнее объясните.

   (Are there any more such scenarios possible in task-event handling which should be reviewed in code ??) 

Я надеюсь, что выше информация является достаточно ....

ответ

1

Этот вопрос должен обеспечить больше контекста. Встроенные системы могут быть созданы с использованием широкого спектра языков, операционных систем (в том числе без операционной системы), фреймворков и т. Д. Нет ничего универсального в том, как создавать события и обрабатывать их во встроенной системе, так же как нет ничего универсального в том, как события созданных и обработанных в вычислительных системах в целом.

2

Многие встроенные системы используют процедуры обслуживания прерываний (ISR) для обработки событий. Вы должны определить ISR для данного «флага» и сбросить этот флаг после обработки события.

Например, у вас есть устройство, выполняющее аналого-цифровые преобразования (АЦП). На устройстве у вас может быть ISR, который срабатывает каждый раз, когда ADC завершает преобразование, а затем обрабатывает его в ISR или уведомляет о какой-либо другой задаче, доступной данным (если вы хотите отправить ее по некоторому протоколу связи). По завершении этого вы сбросите флаг ADC, чтобы он мог снова запустить его при следующем преобразовании.

Обычно в руководстве по устройствам имеется набор ISR. Иногда они предоставляют флагов общего назначения, которые вы также можете обрабатывать по своему усмотрению. Каждый раз сброс флага, вызвавшего запуск этой программы.

0

Извините, что не указали необходимую информацию. На самом деле меня интересует анализ любого приложения, написанного на языке C, с использованием операционной системы vxworks/Itron/OSEK. Например, в vxworks есть библиотека eventLib для поддержки обработки событий. Я хочу знать, как можно использовать такие системные процедуры для обработки событий в задаче. Что такое флаг события (он глобальный/локальный ... или что?), как устанавливать биты любого флага события и которые могут быть возможной связью между флажками задач и событий?

Я надеюсь, что выше информация является достаточно ....

+0

Пожалуйста, удалите это и поместите разъяснение в вопрос (вы можете отредактировать свой вопрос для этой цели). – Ilya 2008-10-22 05:51:37

1

eventLib в VxWorks похожа на сигнал() в UNIX - это может указывать на другую нить, что-то произошло. Если вам необходимо передать данные с событием, вместо этого вы можете использовать очереди сообщений.

События являются «глобальными» между отправителем и получателем. Поскольку каждый отправитель указывает, для какой задачи предназначен событие, в системе может быть несколько масок событий, причем каждая пара отправителя/получателя имеет свою собственную интерпретацию.

Основной пример:

#define EVENT1  0x00000001 
#define EVENT2  0x00000002 
#define EVENT3  0x00000004 
... 
#define EVENT_EXIT 0x80000000 

/* Spawn the event handler task (event receiver) */ 
rcvTaskId = taskSpawn("tRcv",priority,0,stackSize,handleEvents,0,0,0,0,0,0,0,0,0,0); 
... 

/* Receive thread: Loop to receive events */ 
STATUS handleEvents(void) 
{ 
    UINT32 rcvEventMask = 0xFFFFFFFF; 

    while(1) 
    { 
     UINT32 events = 0; 

     if (eventReceive(rcvEventMask. EVENTS_WAIT_ANY, WAIT_FOREVER, &events) == OK) 
     { 
      /* Process events */ 
      if (events & EVENT1) 
       handleEvent1(); 
      if (events & EVENT2) 
       handleEvent2(); 
      ... 
      if (events & EVENT_EXIT) 
       break; 
     } 
    } 

    return OK; 
} 

Отправитель события обычно представляет собой аппаратный драйвер (БСП) или другой поток. Когда возникает желаемое действие, драйвер создает маску всех соответствующих событий и отправляет их в задачу получателя.

Отправитель должен получить идентификатор taskID приемника. TaskId может быть глобальным,

int RcvTaskID = ERROR; 
... 
eventSend(RcvTaskID, eventMask); 

он может быть зарегистрирован с задачей водителя/отправителя приемником,

static int RcvTaskID = ERROR; 

void DRIVER_setRcvTaskID(int rcvTaskID) 
{ 
    RcvTaskID = rcvTaskID; 
} 
... 
eventSend(RcvTaskID, eventMask); 

или задача водителя/отправитель может вызвать метод приемника API для отправки событие (обертка).

static int RcvTaskID; 
void RECV_sendEvents(UINT32 eventMask) 
{ 
    eventSend(RcvTaskID, eventMask); 
} 
+0

handleEvents - это функция, которая обрабатывает все события вашей системы? Если это так, я считаю, что это не очень полезно, поскольку вы дублируете работу, которая может быть выполнена в ISR, на мой взгляд, если мы работаем с ОС ISR должны устанавливать события, а задачи всегда готовы обрабатывать новое предстоящее событие, нет необходимости в задаче, которая прослушивает события и назначает задачу выполнять задание. – fedi 2016-07-11 14:53:09

0

Если вы спрашиваете, как устанавливать, очищать и проверять различные биты, представляющие события, этот пример может помочь. Основная стратегия - объявить (обычно глобальную) переменную и использовать один бит для представления каждого условия.

unsigned char bit_flags = 0; 

Теперь мы можем назначить события битам:

#define TIMER_EXPIRED 0x01 // 0000 0001 
#define DATA_READY  0x02 // 0000 0010 
#define BUFFER_OVERFLOW 0x04 // 0000 0100 

И мы можем установить, ясно, и проверить биты с поразрядными операторами:

// Bitwise OR: bit_flags | 00000001 sets the first bit. 
bit_flags |= TIMER_EXPIRED; // Set TIMER_EXPIRED bit. 

// Bitwise AND w/complement clears bits: flags & 11111101 clears the 2nd bit. 
bit_flags &= ~DATA_READY;  // Clear DATA_READY bit. 

// Bitwise AND tests a bit. The result is BUFFER_OVERFLOW 
// if the bit is set, 0 if the bit is clear. 
had_ovflow = bit_flags & BUFFER_OVERFLOW; 

Мы можем также установить или очистить комбинации бит:

// Set DATA_READY and BUFFER_OVERFLOW bits. 
bit_flags |= (DATA_READY | BUFFER_OVERFLOW); 

Вы часто будете видеть эти операции реализованы в виде макросов:

#define SET_BITS(bits, data) data |= (bits) 
#define CLEAR_BITS(bits, data) data &= ~(bits) 
#define CHECK_BITS(bits, data) (data & (bits)) 

Кроме того, примечание о прерываниях и обслуживания прерывания: они должны работать быстро, поэтому типичный ISR будет просто установить флаг, приращение счетчик или скопировать некоторые данные и немедленно выйти. Затем вы можете проверить флаг и посетить мероприятие на досуге. Вы, вероятно, делаете не хотите предпринять длительные или подверженные ошибкам действия в вашем ISR.

Надеюсь, это полезно!

0

В одном семействе встроенных систем, которые я разработал (для микросхемы PIC18Fxx со вспышкой ~ 128 КБ и оперативной памятью 3,5 КБ), я написал библиотеку для обработки до 16 таймеров с разрешением 1/16 секунды (измеренный импульсом 16 Гц вход в ЦП).Код настроен так, чтобы определить, находится ли какой-либо таймер в состоянии «Истек», или какой-либо выделенный выделенный сигнал пробуждения, а если нет, спящий режим до истечения следующего таймера или изменения состояния входа в режим пробуждения. Довольно удобный бит кода, хотя я должен в ретроспективе, вероятно, разработал его для работы с несколькими группами из восьми таймеров, а не с одним набором из 16.

Ключевой аспект моих процедур синхронизации, которые, как я считаю, полезными, что в основном они не прерываются прерываниями; вместо этого у меня есть «опрос, когда удобная» процедура, которая обновляет таймеры с 16-мегагерцового счетчика. В то время как иногда кажется странным иметь таймеры, которые не запускаются через прерывание, делая что-то таким образом, избегает необходимости беспокоиться о прерываниях, происходящих в нечетные времена. Если действие, контролируемое таймером, не сможет произойти в прерывании (из-за вложенности стека и других ограничений), нет необходимости беспокоиться о таймере в прерывании - просто отслеживайте, сколько времени прошло.

0

Если вы заинтересованы в использовании программирования на основе событий на встроенном уровне, вы должны действительно изучить QP. Это отличная облегченная структура, и если вы получите книгу «Практические UML-диаграммы состояний в C/C++» от Miro Samek, вы найдете все, от того, как обрабатывать системные события во встроенном ядре Linux (ISR и т. Д.) Для обработки и создания их в сборке с помощью QP в качестве среды. (Here - ссылка на примерное событие).

Смежные вопросы