Удержание времени с помощью таймера прерывает встроенный микроконтроллер - PullRequest
4 голосов
/ 21 мая 2009

Этот вопрос касается программирования небольших микроконтроллеров без ОС. В частности, на данный момент меня интересуют PIC, но этот вопрос носит общий характер.

Я несколько раз видел следующую схему хранения времени:

Код прерывания таймера (скажем, таймер срабатывает каждую секунду):

...
if (sec_counter > 0)
  sec_counter--;
...

Основной код (без прерывания):

sec_counter = 500; // 500 seconds

while (sec_counter)
{
  // .. do stuff
}

Код основной линии может повторяться, устанавливать счетчик на различные значения (не только секунды) и т. Д.

Мне кажется, здесь есть условие гонки, когда присвоение sec_counter в основном коде не является атомарным. Например, в PIC18 назначение переводится в 4 оператора ASM (загрузка каждого байта за раз и выбор правильного байта из банка памяти перед этим). Если код прерывания находится в середине этого, окончательное значение может быть повреждено.

Любопытно, что если присвоенное значение меньше 256, присваивание является атомарным, поэтому проблем нет.

Прав ли я об этой проблеме? Какие шаблоны вы используете для правильной реализации такого поведения? Я вижу несколько вариантов:

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

Есть еще идеи?

Ответы [ 11 ]

0 голосов
/ 21 мая 2009

Ну, как выглядит код сборки сравнения?

Принимая во внимание, что он считает вниз и что это просто нулевое сравнение, должно быть безопасно, если сначала проверяется MSB, а затем LSB. Может быть повреждение, но не имеет значения, находится ли оно между 0x100 и 0xff, а искаженное значение сравнения равно 0x1ff.

...