Перейти к содержанию
    

Потоки в программе - как лучше всего организовать атомарность

Всем привет!

Ситуация такая:

1. Устройство через АЦП производит измерения, потом кое-как их обрабатывает, и в итоге получается штук 15 переменных с актуальными значениями.

2. К устройству периодически обращаются по уарту, чтобы забрать значения этих переменных.

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

Я программирую stm32 под freertos. Вот как выглядит момент получения запроса по уарт:

xSemaphoreTake(semphr_uart_received_new_command, portMAX_DELAY);
		
while(measure_process)
{
	taskYIELD();
}

measure_process - это глобальная переменная, которую я выставляю в 1, пока обновляю данные, и выставляю там 0, когда обновления закончено.

У меня как-то с универских времен сидит на подкорке, что глобальные переменные - это чаще всего плохо.

Какое решение в данном случае наиболее "тру"?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

31 minutes ago, termik said:

Какое решение в данном случае наиболее "тру"?

Делаю такие вещи через кольцевые буферы: сбор данных, связь и т.п. Один процесс (АЦП) пишет в буфер, другой (связь) - читает. В моём случае АЦП пишет данные не заботясь о том, что буфер может быть переписан. Это проблема, допустим связного модуля, забрать данные быстрее, как только они там появятся. Естественно, буфер защищён средсвами синхронизации, т.е. чтобы одновременно к нему имел доступ только один процесс. Давно так делаю, всё работает.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

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

Наиболее "тру"  это защитить доступ к данным мьютексом (mutex).

Захватили мьютекс, поработали, освободили. Вместо глобальной measure_process будет глобальный мьютекс :)

 

А самый простой - просто запрещать прерывания на время копирования данных в буфер или из буфера.

Буфер небольшой, 15 слов копируются меньше чем за микросекунду, на вызовах планировщика больше потеряется.

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

37 minutes ago, SSerge said:

А самый простой - просто запрещать прерывания на время копирования данных в буфер или из буфера.

Я использую критические секции и объекты синхронизации: семафоры, к примеру. Естественно делаю это оптимально задаче. Недавно возникла проблемка: отлаженный и проверенный в проектах код для копирования данных из буфера в задачу стал тормозить всю систему, и вылетать с таймаутом. Но время, выдаваемое на копирование уменьшилось раз в 10 по сравнению с предыдущими проектами. Пришлось лезть в ассемблерный листинг, и тюнинговать по нему. Но в итоге я нашёл более оптимальный алгоритм копирования. Переписав код, и для полной гармонии проверил листинг, получли рабочий вариант.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

3 hours ago, termik said:

Какое решение в данном случае наиболее "тру"?

Использовать сервисы RTOS для защиты доступа к одной переменной - это слишком накладно, непроизводительное расходование ресурсов процессора. 
Использовать запрет прерываний можно, но не грубо всех прерываний,  а повышением уровня вытеснения до уровня ядра. 
Это хорошо работает на ARM-ах. Но порт операционки должен тогда поддерживать такую возможность. 
В этом случае можно еще сохранить детерминированные процессы с джитером меньше 1 мкс

Но в качественных операционках типа ThreadX под ARM предусмотрен еще 3-й способ - использование аппаратных блокировок на основе команд    LDREXB , STREXB, CLREX.
Блокировки требуют всего пару тактов, но не запрещают никакие прерывания и не вызывают сервисы RTOS.
Повсеместно используются в ThreadX на уровне драйверов и для доступа к периферии.

ThreadX - самая распространенная в мире операционка, используется в космических аппаратах и во всех современных десктопах с процессорами Intel.
Доступна бесплатно в составе Renesas Synergy   
 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

2 hours ago, AlexandrY said:

всех современных десктопах с процессорами Intel.

Простите, а чем она там заправляет?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.

Гость
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...