Несколько переменных, разделяемых между потоками?

У меня есть 4 потока, работающих на ESP32 (двухъядерном ядре):

  • 1 поток работает на 1-м ядре, которое связано с Wi-Fi.
  • 1 поток работает на 2-м ядре, которое связано с сенсорным экраном.
  • 1 поток работает на 2-м ядре, которое связано с дисплеем.
  • 1 нить работает на 2-м сердечнике, который связан с датчиками.

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

Во всяком случае, с ростом программы в передаче данных между ядрами стало участвовать много переменных, и поскольку все это вот-вот будет переделано, у меня есть следующие вопросы, чтобы прояснить для себя ситуацию, так как я нашел довольно много запутанной, даже противоречивой информации в примерах и объяснениях в Интернете:

  • Действительно ли ключевого слова "volatile" достаточно для обмена данными между потоками (без ISR)?
  • Должен ли "volatile" всегда находиться между"noInterrupts() " и "interrupts()", даже если нет функции ISR?
  • Какие подходы следует использовать при обмене большим количеством переменных между потоками (в настоящее время около 40 переменных, но их число, вероятно, будет расти)?
  • Блокируется ли xQueueSend / xQueueReceive в случае, если он помещается вокруг всех потоков с разными переменными?

, 👍0

Обсуждение

вероятно, это произошло во время копирования., @Yordan Yanakiev


1 ответ


2

Действительно ли ключевое слово "volatile" достаточно для обмена данными между потоками (без ISR)?

Нет - "volatile" просто говорит компилятору, что переменная может изменить значение из-за чего-то другого, чем непосредственно генерируемый код, и сообщает генератору кода, чтобы он не полагался на значение, остающееся статическим, когда он иначе ожидал бы этого. Например, при копировании значения в регистр обычно ожидается, что значение регистра будет продолжать представлять значение переменной в памяти, но если переменная изменчива, это предположение не выполняется. Это будет использоваться, чтобы указать, что ISR может изменить его в любое время; что переменная является входным регистром и может быть изменена извне в любое время; или что другой поток может изменить его, снова, в любое время (предполагая упреждающее многопоточность или многозадачность).

Should "volatile" always be between "noInterrupts()" and "interrupts()", even when there is no ISR function?

No - volatile просто описывает атрибут переменной с течением времени

Какие подходы следует использовать при обмене большим количеством переменных между потоками

Используйте здесь семафор. Поток, который хочет получить доступ к одной из или коллекции общих переменных, запрашивает семафор. RTOS либо возвращает его немедленно, либо (поскольку другой поток уже держит его) приостанавливает задачу до тех пор, пока она не станет доступной, и возвращает ее затем. Поток, удерживающий семафор, может обращаться к переменным (или к любому общему ресурсу, которым управляет этот семафор), а затем возвращает семафор по завершении. Семафоры обычно встроены в ОСРВ.

(Поскольку я не знаком с вашими конкретными ОСРВ, я оставлю ваш четвертый вопрос для тех, кто знаком).

,

Спасибо Вам за очки, ЖРоберт. Я использую ФРИТОС ( Espriff IDF ), @Yordan Yanakiev