Как справиться с стойкой обертывания в встроенном C

StackOverflow https://stackoverflow.com/questions/3095623

  •  29-09-2019
  •  | 
  •  

Вопрос

Мне нужно разобраться с счетчиком, который дает мне галочки для моего приложения. Счетчик 32бит, так что мне нужно знать, - это то, как иметь дело с этим, когда он обернутся. Например:

У меня есть функция, которая возвращает (Timestamp + ShiftteTime), и у меня есть другая функция, которая вернет 1 или 0 в зависимости от того, прошло ли время, но может ли возможность того, что мой счетчик обернет, как я могу иметь дело с этим? Отказ

Спасибо

Большое спасибо за все ответы, ребята. Я даю более подробно в этом редактировании.

Я использую Cortex-M3 STM32. Я хочу использовать счетчик RTC, чтобы использовать его в качестве тика для моего приложения для планирования задач, которые должны происходить через определенные промежутки времени. RTC может генерировать прерывание переполнения, поэтому не является проблемой обнаружения прерывания. Основная проблема, которую я имею (или, по крайней мере, я думаю, что это проблема), заключается в том, что определенные задачи получают (смену временного лампа+сдвиг), т.е.


int main( void )
{
FlashLedTimeStamp = ReturnCounter( 20 );  // currentcounter value + a shift of 20
StatusLedTimeStamp = ReturnCounter( 3 );  // currentcounter value + a shift of 3

//then later on ....
while(1)
{
    /* other tasks could go here */

    if( HasTimeElapsed( FlashLedTimeStamp );
    {
       /* do something and get another timestamp value */
       FlashLedTimeStamp = ReturnCounter( 20 );  // currentcounter value + a shift of 20
    }

    if( HasTimeElapsed( StatusLedTimeStamp );
    {
       /* do something and get another timestamp value */
       FlashLedTimeStamp = StatusLedTimeStamp( 3 );  // currentcounter value + a shift of 3
    }
}   
}

Предположим, что мой счетчик RTC длиной всего 8 бит, чтобы сделать математику.

Если мой текущий счетчик находится в 250, когда я получаю свои временные метки, что означает, что flashledtimestamp = 14 и statureledtimestamp = 253 Как бы я проверил, чтобы увидеть, что FlashledTimestamp истек ??

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

Это было полезно?

Решение

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

Это, однако, не обнаружено, если счетчик завернут несколько раз или случай, когда счетчик обернул и происходит больше, чем первое чтение. Поскольку вы сказали, что это была встроенная система, и ваше описание делает ваш «счетчик» звук как часы, см. Если вы можете установить прерывание, когда часы достигают ноль (так что вы получите прерывание каждый раз, когда часы сбрасываются). Когда это прерывает огни, увеличивайте отдельный счетчик. Это должно эффективно добавить дополнительную точность к вашим часам и позволить вашему счетчику обернуть, не вызывая проблем.

Другие советы

Это не будет вопросом, что разница между началом и конечным количеством меньше, чем (2 ^ 32) / 2, и при условии, что выполняется 2-дюймовая арифметика дополнения 2 (почти универсально), даже если значение счетчика охватывает точку обертывания Отказ Например:

Start count: 0xfffffff
End Count:   0x00000002 (incremented through 0,1,2 - i.e. three counts)

End - Start == 0x00000002 - 0xfffffff == 0x00000003

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

Если вам нужен больший подсчет по другим причинам, или если разница между последовательными временными метками слишком велика, вы можете просто использовать другое целое число, которое увеличивается, когда счетчик нижнего порядка. Это целое число сформирует биты высокого порядка большего целого числа, поэтому LSB второго целого числа является 33-й бит этого более крупного целого числа.

Если вы используете неподписанные переменные для хранения вашего счетчика и времени истечения таймера, то вы можете просто использовать этот тест:

if (current_time - expiry_time < 0x80000000UL)
    /* timer has expired */

Это предполагает, что вы тестируете на срок действия, по крайней мере, один раз каждые тика 0x80000000, и что ваш самый длинный таймер срок действия истекает менее 0x80000000 в будущем.

Вопрос немного расплывчат. Одна возможность состоит в том, чтобы установить флаг, когда вы впервые заметите, что время прошло. Конечным образом будет добавить второй счетчик, который увеличивается при переполнении первого счетчика. Это действительно создаст 64 -битный счетчик, который не переполнится.

Отправить результат беспигнированного вычитания для подписания и сравнения с нулем. Следует обрабатывать переполнение, когда вы проверяете его достаточно часто (и ваш тайм -аут меньше половины диапазона вашего таймера).

uint32_t timer( void);             // Returns the current time value
uint32_t timeout;

timeout = timer() + offset;

// wait until timer() reaches or exceeds timeout value
while ((int32_t)(timeout - timer()) > 0);

Самый простой способ сделать это - сделать «счетчик эпохи», что явно подсчитывает роллы. (Пример: у вас есть аппаратный счетчик, который подсчитывает секунды 0..59. Ваша эпохальная счетчик будет подсчитывать минуты, увеличивая каждый раз, когда он заметил, что счетчик секунды перевернулся.)

Затем ваша функция foot_scheduler затем читает текущую эпоху и время и вычисляет новую эпоху и время для вашего мероприятия.

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

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

Давайте предположим, что счетчик подсчитывает (многие подсчитывают, чтобы сохранить на воротах в логике).

Вам нужно сначала узнать период времени, необходимое для достижения 2^32 клещей, и вам нужно застраховать, что вы хорошо разбираете это.

Если вы хотите найти период времени между двумя событиями, скажем, начало и конец

Start = Timer Timer Time Tasttime = Start Rollover = 0

В ожидании того, что произойдет

nowtime = read timer if (сейчас время> в прошлое время) Rollover+= 1 (это счетчик вниз) в прошлое = сейчас время

Событие происходит: end = чтение таймер

Общее время = начало - конец (это счетчик вниз и обратите внимание, что эта математика работает даже при продвижении)

Общее время = общее время/коэффициент масштабирования, чтобы добраться от клещей до секунд, минут, в любое время += Rollover * секунды/минуты/что угодно на 2^32 счета

Если у вас есть счетчик, то сейчас время

Если вы можете гарантировать, что ваше мероприятие произойдет в течение 2 ^ 32, вам не нужно делать ролоса сейчас время в последний раз, что вам нужно только начать и конец, и общие галочки = начало - END будет работать, даже если счетчик ролики от 0x00000000 0xFFFFFFFFFFF между началом и концом.

Предполагая, что вы имеете дело с типами без подписи, вы можете легко проверить обертку -

if (timestamp + shifftime < timestamp) 
    it_wrapped();

Когда вы встроены, у вас может быть доступ к переполнению процессора. Это будет установлено, когда добавление переполнения, это регистр. Полезно для добавления addcarry цепочки.

Я думаю, что одним из самых простых способов сделать это было бы иметь еще один счетчик (давайте назовем его счетчик, пусть это будет статичным глобальным для модуля таймера), каждый раз, когда ваш первоначальный счетчик 32 бит обернут.

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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top