termik 0 19 мая, 2019 Опубликовано 19 мая, 2019 · Жалоба Всем привет! Ситуация такая: 1. Устройство через АЦП производит измерения, потом кое-как их обрабатывает, и в итоге получается штук 15 переменных с актуальными значениями. 2. К устройству периодически обращаются по уарту, чтобы забрать значения этих переменных. Проблема в том, что запрос из уарта может прилететь в процессе обновления переменных,и тогда половина значений уйдет актуальных, половина - неактуальных. Проблема стара как мир, и я конечно решил ее. Но мне кажется, что мое решение не самое лучшее, а сейчас появилось время задуматься о прекрасном, и хочется понять, как это решается правильнее всего. Я программирую stm32 под freertos. Вот как выглядит момент получения запроса по уарт: xSemaphoreTake(semphr_uart_received_new_command, portMAX_DELAY); while(measure_process) { taskYIELD(); } measure_process - это глобальная переменная, которую я выставляю в 1, пока обновляю данные, и выставляю там 0, когда обновления закончено. У меня как-то с универских времен сидит на подкорке, что глобальные переменные - это чаще всего плохо. Какое решение в данном случае наиболее "тру"? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
haker_fox 60 19 мая, 2019 Опубликовано 19 мая, 2019 · Жалоба 31 minutes ago, termik said: Какое решение в данном случае наиболее "тру"? Делаю такие вещи через кольцевые буферы: сбор данных, связь и т.п. Один процесс (АЦП) пишет в буфер, другой (связь) - читает. В моём случае АЦП пишет данные не заботясь о том, что буфер может быть переписан. Это проблема, допустим связного модуля, забрать данные быстрее, как только они там появятся. Естественно, буфер защищён средсвами синхронизации, т.е. чтобы одновременно к нему имел доступ только один процесс. Давно так делаю, всё работает. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
SSerge 4 19 мая, 2019 Опубликовано 19 мая, 2019 · Жалоба У Вас есть два процесса, каждому из которых нужен эксклюзивный доступ к некому ресурсу, в данном случае это буфер в памяти. Наиболее "тру" это защитить доступ к данным мьютексом (mutex). Захватили мьютекс, поработали, освободили. Вместо глобальной measure_process будет глобальный мьютекс :) А самый простой - просто запрещать прерывания на время копирования данных в буфер или из буфера. Буфер небольшой, 15 слов копируются меньше чем за микросекунду, на вызовах планировщика больше потеряется. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
haker_fox 60 19 мая, 2019 Опубликовано 19 мая, 2019 · Жалоба 37 minutes ago, SSerge said: А самый простой - просто запрещать прерывания на время копирования данных в буфер или из буфера. Я использую критические секции и объекты синхронизации: семафоры, к примеру. Естественно делаю это оптимально задаче. Недавно возникла проблемка: отлаженный и проверенный в проектах код для копирования данных из буфера в задачу стал тормозить всю систему, и вылетать с таймаутом. Но время, выдаваемое на копирование уменьшилось раз в 10 по сравнению с предыдущими проектами. Пришлось лезть в ассемблерный листинг, и тюнинговать по нему. Но в итоге я нашёл более оптимальный алгоритм копирования. Переписав код, и для полной гармонии проверил листинг, получли рабочий вариант. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
AlexandrY 3 19 мая, 2019 Опубликовано 19 мая, 2019 · Жалоба 3 hours ago, termik said: Какое решение в данном случае наиболее "тру"? Использовать сервисы RTOS для защиты доступа к одной переменной - это слишком накладно, непроизводительное расходование ресурсов процессора. Использовать запрет прерываний можно, но не грубо всех прерываний, а повышением уровня вытеснения до уровня ядра. Это хорошо работает на ARM-ах. Но порт операционки должен тогда поддерживать такую возможность. В этом случае можно еще сохранить детерминированные процессы с джитером меньше 1 мкс Но в качественных операционках типа ThreadX под ARM предусмотрен еще 3-й способ - использование аппаратных блокировок на основе команд LDREXB , STREXB, CLREX. Блокировки требуют всего пару тактов, но не запрещают никакие прерывания и не вызывают сервисы RTOS. Повсеместно используются в ThreadX на уровне драйверов и для доступа к периферии. ThreadX - самая распространенная в мире операционка, используется в космических аппаратах и во всех современных десктопах с процессорами Intel. Доступна бесплатно в составе Renesas Synergy Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
haker_fox 60 19 мая, 2019 Опубликовано 19 мая, 2019 · Жалоба 2 hours ago, AlexandrY said: всех современных десктопах с процессорами Intel. Простите, а чем она там заправляет? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
arhiv6 14 19 мая, 2019 Опубликовано 19 мая, 2019 · Жалоба Обслуживает Intel Management Engine. Правда с версии ME11 используется другая ОС - MINIX3. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться