синхронизация между двумя задачами - PullRequest
3 голосов
/ 03 августа 2009

Это на самом деле вопрос дизайна для прошивки во встроенной системе У меня есть два ISR (с одинаковым приоритетом), выполненные независимо. Эти ISR запускаются, когда ч / б генерирует данные. Я хочу механизм, который должен быть установлен для синхронизации между task1 и task2. Задача 2 должна знать об определенных значениях, вычисленных в задаче 1, которые затем необходимо учитывать при вычислении определенных значений в задаче 2. У меня нет примитивов ОС для использования, т.е. в системе нет операционной системы. Задача 1 выполняется в контексте ISR1, а задача 2 в контексте ISR2. Используемый нами процессор - контроллер STMicroelectronics 32

РЕДАКТИРОВАТЬ: дополнительная информация Процессор подключен к определенным IP-адресам, которые запускают прерывания, когда они готовы к данным. Эти IP-адреса действуют как тип аккумуляторов для входных потоковых данных кадра.

Ответы [ 4 ]

4 голосов
/ 03 августа 2009

Я бы не стал выполнять тяжелую обработку в контексте прерываний, просто прочитал бы данные и установил флаг.

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

Задача также может установить такой флаг, чтобы активировать другую задачу. Например. Task1 может активировать Task2, потому что Task2 нужны значения из Task1.

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

2 голосов
/ 03 августа 2009

Я подхожу к этому с точки зрения отсутствия ОС, реальной платформы, кроме C, регистров и тому подобного. Я бы сделал так, чтобы для каждого ISR была переменная состояния, которую может видеть другой ISR. Затем, когда вы входите в ISR1, вы просто проверяете состояние задачи ISR2 и работаете по мере необходимости. Затем вызывается ISR2 и проверяет свое собственное состояние и состояние ISR1 и работает так, как считает нужным. Я бы использовал ENUM в заголовочном файле, чтобы перечислить состояния для ясности (INIT, WAITONDATA и т. Д.), А затем переключатель в ISR для обработки каждого состояния. Тогда вам просто нужно убедиться, что данные, которые должны быть переданы, могут быть видны обоим ISR, и вы настроены.

Конечно, как говорили другие, вы не хотите делать много вычислений в ISR. Вы просто хотите установить флаг, что событие произошло или какие-то данные присутствуют, а затем обрабатывать данные в основном цикле. Тогда ваша система не будет заблокирована слишком долго для обработки ISR. Вы делаете это таким же образом - переменная состояния, которую можно увидеть в основном цикле (или, по крайней мере, в функции, которую вы вызываете для манипулирования данными из основного цикла) и ISR. Измените его состояние в ISR и проверьте это состояние в функции основного цикла. Делайте по дому по мере необходимости.

Не забудьте - если вы обновляете переменные в ISR, они должны быть определены как volatile!

изменчивое состояние uint8 = INIT;

например.

2 голосов
/ 03 августа 2009

Я постараюсь дать вам ответ, основываясь на ограниченной информации, предполагая:

  • простой, доморощенный планировщик используется для вызова task1 и task2 на основе простого criterea
  • задача1 и задача2 выполняются до конца (т.е. не выгружают друг друга)
  • данные - это байтовый поток (для пакетов требуется немного другая реализация)

Что я обычно пытаюсь при проектировании встраиваемых систем - это минимизировать использование семафоров и моделировать потоки данных без блокировки. Я проиллюстрирую это ниже:

асинхронные (без блокировки) очереди связи http://www.freeimagehosting.net/uploads/477741db06.gif ISR могут быть отделены от задач, используя потокобезопасную очередь FIFO. Пример можно найти в http://msmvps.com/blogs/vandooren/archive/2007/01/05/creating-a-thread-safe-producer-consumer-queue-in-c-without-using-locks.aspx

Такая реализация (без блокировок) не имеет зависимостей от ОС и должна легко поддерживаться. Это также дает четкий дизайн производителя и потребителя, который не имеет тупиков.

Предполагая, что задачи запускаются самодельным планировщиком, вы можете выбрать проверку событий (непустых fifo) там. то есть if (TRUE == fifo_filled (my_read_queue)) {вызвать задачу 1}

Теперь о синхронизации задачи1 и задачи2. Если задача 1 просто создает данные, можно использовать тот же механизм: если у вас есть очередь (fifo), в которую задача 1 может записывать данные, которые могут быть прочитаны задачей 2, тогда задачи разделяются. Опять же, это может быть проверено в вашем планировщике (if (TRUE == fifo_filled (task1_to_2_queue ()) {invoke task2)}

Если вам нужно больше (т. Е. Если задачи не выполняются до конца, но имеют приоритет), вам потребуется какой-то механизм для синхронизации. Варианты включают в себя: - все равно используйте (бесплатную) операционную систему или простой планировщик - заварить свой (мой опыт: должно быть сделано, только если это так же просто, как цикл for и несколько операторов if) - использовать простой планировщик (гораздо более легкий, чем полноценная ОСРВ) - код рефакторинга для объединения задач 1 и 2 в одном. В этом случае вы фактически сделаете планировщик частью кода своего приложения.

Примечание: пример функции, которую я использовал в этом объяснении (fifo_filled ()), не является частью кода примера. Должен вернуть true если (читай! = Напиши) Кроме того, пример кода использует глобальные переменные read и write; Вы можете либо добавить в Google функцию, способную обрабатывать несколько очередей, либо переместить переменные чтения / записи и буфера в структуру, а также обратиться к структуре в параметрах.

Альтернативный способ - создать критический раздел с помощью отключения прерывания. Однако я стараюсь ограничить это, так как это часто создает сильную системную связь, и код становится все труднее повторно использовать.

2 голосов
/ 03 августа 2009
  • Отключить прерывания перед чтением или записью в общие значения
  • Повторное включение прерываний после чтения или записи в общие значения
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...