Достаточно ли floating point при доступе к переменной из ISR?
Допустим, я хочу изменить глобальную переменную внутри процедуры обслуживания прерываний. Я должен убедиться, что любые переменные, которые я изменяю, изменчивы. Работает ли использование летучего указателя на данные, которые я хочу изменить, если сами данные не являются летучими?
В моем случае данные-это структура, но меняется ли ответ, если данные являются классом, массивом или просто переменной?
#include <Arduino.h>
#define PIN_INTERRUPT 2
typedef struct MyStruct
{
int a_field;
} MyStruct;
MyStruct struct_data;
int array_data[32];
volatile bool _flag_ISR = false;
volatile MyStruct *_struct_ISR = &struct_data;
void myISR()
{
// просто некоторые примеры
int read = digitalRead(PIN_INTERRUPT);
_struct_ISR->a_field = read;
_arr_data_ISR[4] = read;
_flag_ISR = true;
}
void setup()
{
attachInterrupt(digitalPinToInterrupt(PIN_INTERRUPT), myISR, CHANGE);
}
void loop()
{
if (_flag_ISR)
{
// сделайте обработку здесь...
_flag_ISR = false;
}
}
@M. Werezak, 👍2
Обсуждение1 ответ
Во-первых, помните, что то, что вы написали, не является изменчивым указателем, это
указатель на изменчивые данные. Если вы всегда обращаетесь к объекту через этот
указатель, вы должны быть в порядке. Если вы используете указатель в ISR, но
получаете доступ к данным непосредственно в главном коде (минуя volatile
квалификатор), то программа может потерпеть неудачу.
Рассмотрим следующее:
void loop()
{
if (_flag_ISR) {
_flag_ISR = false;
Serial.println(struct_data.a_field);
}
}
Как только компилятор вводит вызов loop()
из main()
,
основная программа выглядит так
int main()
{
init(); // Настройка инициализации ядра Arduino
setup();
for (;;) { // встроенный loop()
if (_flag_ISR) {
_flag_ISR = false;
Serial.println(struct_data.a_field);
}
}
}
И теперь, поскольку struct_data
не изменчива, компилятор может
законно оптимизировать код, избегая повторного доступа к одному и тому же
Расположение оперативной памяти:
int main()
{
init(); // Настройка инициализации ядра Arduino
setup();
register int data_copy = struct_data.a_field;
for (;;) { // встроенный loop()
if (_flag_ISR) {
_flag_ISR = false;
Serial.println(data_copy);
}
}
}
И теперь программа печатает только нули.
Голосовать за тебя. Мне кажется, я слишком буквально воспринял их "летучий указатель". Предполагая, что они подтверждают это понимание того, что они имели в виду, ваш ответ имеет почти все, что я должен сказать об этом в любом случае. Я немного удивлен, что вы используете ключевое слово register., @timemage
@timemage: Ключевое слово "register" редко используется в реальном коде. Здесь я использую его только для выражения идеи о том, что компилятор может выбрать сохранение копии данных во внутреннем регистре процессора (или наборе регистров)., @Edgar Bonet
Это вторая половина того, что я искал. Знаешь, тебе даже не разрешают использовать его в 17-м., @timemage
- Использование millis() и micros() внутри процедуры прерывания
- Подсчет импульсов с прерыванием
- Устранение дребезга кнопки с помощью прерывания
- Программа arduino выдаёт ошибку expected //primary-expression before ')' token error: //expected ';' before '}' token E
- Почему необходимо использовать ключевое слово volatile для глобальных переменных при обработке прерываний в ардуино?
- Как сгенерировать аппаратное прерывание в mpu6050 для пробуждения Arduino из режима SLEEP_MODE_PWR_DOWN?
- Использование поворотных энкодеров с прерываниями смены контактов
- Arduino непрерывно считывает значение АЦП с помощью прерывания
Я думаю, что неправильно понял ваш вопрос, через который проходит первая пара, вероятно, потому, что (я предполагаю) под "изменчивым указателем" вы действительно имели в виду "указатель на изменчивый", и это различие очень важно. Итак, вы спрашиваете: "что касается связи между ISR и основной линией исполнения, достаточно ли использовать указатель НА volatile*, если* указываемая вещь сама по себе не является volatile квалифицированной?", @timemage