ОСРВ по протоколу UART

Я разрабатываю протокол UART для обеспечения связи между двумя платами (мастер-плата и ведомая плата). Ведомая плата включает в себя множество датчиков и исполнительных механизмов, а главная плата должна управлять этой платой с помощью набора команд, таких как GET_SENSOR_VALUEи SET_MOTOR_SPEEDт. д. В моем проекте должны выполняться многие функции, и должен осуществляться постоянный контроль значений датчиков (пример: главная плата должна получить значение температуры каждые 5 секунд, он будет получать уровень заряда батареи каждые 5 секунд, он должен включать вентиляцию при высокой температуре ...). Все оборудование подключено к плате Slave (датчики и исполнительные механизмы), а основная роль платы Master — мониторинг.

Я прочитал несколько статей о спецификациях и проектировании встроенных систем и понял, что первое, что нужно сделать перед запуском, — это выбрать ядро: RTOS или GPOS (голое железо).

Мой вопрос: в моем случае, если я выберу RTOS (на основной плате), должен ли я реализовать свои потребности в виде отдельных задач/функций?

  • температура_задача
  • влажность_задача
  • battery_task
  • motor_task
  • вентиляция_задача

Если да, поддерживает ли UART время высокоскоростного переключения контекста? пример:

00:00 temperature_task : GET_TEMPERATUREесли температура>порог, отправить START_VENTILATION
00:01 battery_task: GET_LEVELесли уровень <порог отправить TURN_OFF_SYSTEM
00:02 влажность_задача: GET_HUMIDITYесли уровень <порог отправить DO_SOMETHING
00:03 Temperature_task : GET_TEMPERATUREесли температура>порог отправить START_VENTILATION
00:04 battery_task: GET_LEVELесли уровень <порог отправить TURN_OFF_SYSTEM
00:05 влажность_задача: GET_HUMIDITYесли уровень < порога отправитьDO_SOMETHING

это зависит ... вы можете получать данные разными задачами, но тогда вам нужно каким-то образом заблокировать использование uart, когда другая задача использует оборудование uart (например, мьютекс) ... я бы сделал это в та же задача, если каждые данные должны быть получены отдельно, то я бы реализовал конечный автомат .... о переключении контекста, в зависимости от микроконтроллера я бы либо использовал DMA для отправки и получения данных, либо блокировал прерывания в течение короткого времени кадр, он получает данные ... я бы в конечном итоге использовал DMA, это намного проще
Имейте в виду, что наличие большого количества тривиальных потоков будет использовать ОЗУ с уникальным стеком и данными отслеживания для каждого. Если вы можете выполнять несовместимые операции с меньшим количеством потоков, либо с помощью какого-либо более легкого механизма рабочей единицы, либо путем объединения их вместе, вы сэкономите — например, у вас будет только один поток выполнения для всех датчиков. Также вам в значительной степени нужно предоставить UART одному потоку, который опосредует доступ; в противном случае время, необходимое для отправки или получения, либо создаст почти неразрешимый беспорядок согласованности, либо заставит вас замедлиться до сканирования, ожидающего мьютексов.
Вы не оправдываете необходимость в RTOS - я бы отказался, учитывая вашу постановку проблемы. Если это просто для удовольствия, то, во что бы то ни стало, идите, но ваш вопрос должен включать в себя какое-то обоснование. Это поможет вам уточнить фактический вопрос о задачах и разделении интересов.

Ответы (2)

Да, это вообще ОТЛИЧНАЯ идея разделить функциональность таким образом, когда RTOS находится в системе. Необходимо проявлять большую осторожность, чтобы обеспечить взаимное исключение между задачами и общими ресурсами, такими как общая память или периферийные устройства, чтобы избежать условий гонки и непредсказуемого поведения. Обычный подход к этой проблеме заключается в блокировке каждого периферийного устройства за задачей «привратника», которая управляет входящим и исходящим потоком данных, обычно выполняя функцию обратного вызова для вызывающей стороны, когда ожидаемые данные получены. Прочтите эту статью (глава 7 посвящена именно этому) из документации FreeRTOS. При этом подход «голого железа» может быть вполне адекватным, имея более тесную связь между функциональными модулями программного обеспечения.

Если вам нужно заблокировать общий интерфейс, чтобы избежать конфликтного использования разными задачами, какую выгоду вы на самом деле получаете, платя за отдельный стек для каждой задачи датчика? Вы просто добавляете много накладных расходов для воссоздания последовательного выполнения, только с большей сложностью и меньшим детерминизмом. Задачи имеют смысл, когда у вас есть сложная текущая операция, которая редко мешает другим; и когда вы не можете легко реорганизовать его как конечный автомат, управляемый событиями.
Согласитесь, вы всегда должны иметь возможность уменьшить сложность программного обеспечения, чтобы оно соответствовало приложению, и всегда должно быть первым выбором, однако, когда (неизбежно) необходимо добавить новые функции или изменить поведение, подход с отдельными задачами поддается более модульному дизайну и быстрое развитие. Но вы правы в том, что для обеспечения детерминированного поведения вводится много накладных расходов.

Обычно UART является двунаправленным (провод RX + TX), поэтому вы можете отправлять/получать без необходимости переключения.

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

О ваших требованиях к «времени»: секунда — это огромное количество времени даже для простого микроконтроллера, такого как Arduino. Вы, вероятно, можете использовать оба Arduino с голым металлом (если вы не планируете использовать сложные расчеты/схемы), при условии, что вы можете установить все датчики на Arduino (или Mega?).

Если вы сделаете это фиксированным (например, всегда 20 байтов для размещения всех значений датчиков), вам не нужен символ новой строки/конец байта сообщения.

О протоколе: почему бы не отправлять каждые x мс все данные со всех датчиков одним пакетом на контроллер (ведомый к ведущему). И мастер может отправлять при необходимости (на лету для малой задержки) короткие сообщения, такие как «Выключить систему» ​​или определенные команды (включая параметры).

Пример команд от ведомого к ведущему:

Byte   Meaning
0      Temp sensor
1      Humidity level
2      Battery level (?)
3      ... other sensors

Пример команд от Мастера:

Byte 0    Byte 1
Command   Parameter    Meaning
  0         n.a.      Turn off system 
  1         n.a.      Turn on system
  2         0-255     Move servo to loc x (as example)

и т. д.

Задачи сильно отличаются от функций. Функции почти ничего не стоят, потому что компилятор может встроить их там, где это имеет смысл. Напротив, задачи требуют больших затрат памяти - обычно они представляют собой независимые потоки, каждому из которых требуется собственный стек, иногда даже конструкции больше, чем поток, сравнимый с «процессом» настольной ОС.
Помимо этой ошибки, похоже, что это вообще не касается заданного вопроса.
@ChrisStratton Я говорил не о задачах, а о функциях. Однако я изменю свой ответ, чтобы сделать его более понятным. Я думаю, что это хотя бы частично отвечает на вопрос (какой протокол можно было бы использовать), это независимо для задач (достаточно одной задачи).