Использование millis() несинхронизированным образом

Я предполагаю, что millis() является функцией ISR таймера. Если так : При использовании millis (), как указано в справочнике Arduino : unsigned long currentMillis = millis(); Что произойдет, если ISR асинхронно изменит значение, считываемое в функции. Я имею в виду, если я прочитал один байт в currentMillis, но millis изменил значение, прежде чем остальные 7 байтов будут прочитаны.

Ура и ТИА

, 👍0

Обсуждение

Разработчик встраиваемых систем? загляните в исходный код millis (), прежде чем спрашивать, @Juraj


1 ответ


Лучший ответ:

2

Я предполагаю, что millis() является функцией ISR таймера.

Это функция, которая извлекает значение, которое обновляется и ISR.

Что произойдет, если ISR асинхронно изменит значение , считываемое в функции.

Не может произойти: значение считывается с отключенными прерываниями.

См., например, в ядре AVR:

// disable interrupts while we read timer0_millis or we might get an
// inconsistent value (e.g. in the middle of a write to timer0_millis)
cli();
m = timer0_millis;
SREG = oldSREG;

Я имею в виду, если я прочитал один байт в currentMillis, но миллис изменил значение до того, как были прочитаны оставшиеся 7 байтов.

unsigned long составляет всего 4 байта. То есть до тех пор, пока кто-то не придет с 64-битной платформой Arduino.

,

Конечно, 64-битный Arduino с 2 кб оперативной памяти :-), @PMF

@Edgar Bonet ,Просто в качестве отступа ( я на самом деле пишу функцию millis() like для другого uC ) : Допустимо ли, скажем , использовать бит блокировки для предотвращения чтения во время обновления переменной по таймеру вместо отключения прерывания? Большое спасибо !, @EmbSysDev

@EmbSysDev: Нет необходимости “предотвращать чтение во время обновления переменной таймером”: ISR не прерывается, поэтому ничто не может прочитать переменную во время ее обновления. Вам необходимо предотвратить обновление, пока основная программа его читает., @Edgar Bonet

@EdgarBonet: cli() отключает все прерывания, поэтому слишком много вызовов millis() повлияет на все события, основанные на прерываниях.Разве не было бы достаточно отключить только TIM0 ? В функции они, похоже, снова не включают прерывания, выполняется ли это в другом месте(в противном случае прерывание не было бы включено).Имело бы смысл снова включить прерывания перед выходом из millis() ? Спасибо, что уделили мне время !, @EmbSysDev

@EmbSysDev: Вы действительно можете выборочно отключить TIM0, хотя это займет на несколько циклов больше, чем " cli ()". Этот критический раздел очень короткий, поэтому здесь подойдет глобальное отключение прерываний. Повторите “ _ они, похоже, больше не включают прерывания”: именно это делает " SREG = oldSREG;": повторно включите прерывания, но только если они были изначально включены при вызове функции., @Edgar Bonet