Я постараюсь дать вам ответ, основываясь на ограниченной информации, предполагая:
- простой, доморощенный планировщик используется для вызова 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 функцию, способную обрабатывать несколько очередей, либо переместить переменные чтения / записи и буфера в структуру, а также обратиться к структуре в параметрах.
Альтернативный способ - создать критический раздел с помощью отключения прерывания. Однако я стараюсь ограничить это, так как это часто создает сильную системную связь, и код становится все труднее повторно использовать.