2016-11-14 4 views
3

Я работаю над встроенным проектом, который работает на микроконтроллере ARM Cortex M3. В некотором коде, предоставленном нашим поставщиком, используется функция задержки, которая устанавливает встроенный таймер аппаратного обеспечения и затем вращается до истечения таймера. Обычно это используется для ожидания от 1 до пары сотен микросекунд. Эти задержки происходят почти потому, что они ждут на каком-то регистре, чипе или шине, чтобы завершить действие, и нужно подождать не менее данного количества микросекунд. Аппаратный таймер также, по-видимому, стоит не менее 6 микросекунд для установки.ARM встроенный таймер аппаратного таймера против счетчика циклов процессора

В многопоточной среде это проблема, потому что есть N потоков, но только 1 аппаратный таймер. Я могу отключить прерывания, когда таймер используется для предотвращения переключений контекста и, следовательно, условий гонки, но кажется немного уродливым. Я думаю о замене функции, которая использует аппаратный таймер, с функцией, которая использует счетчик циклов процессора ARM (CCNT). Есть ли недостатки, которые у меня отсутствуют или другие альтернативы? Очевидно, функция счетчика циклов требует, чтобы она была настроена на правильную частоту процессора, которая никогда не изменится для нашей системы, но я предполагаю, что ее можно было бы программно определить при загрузке аппаратного таймера.

+0

Какой тип ARM M3 имеет единый таймер для оборудования? Вы говорите, что у вас многопоточная среда, поэтому необходим таймер для планировщика: вы говорите, что единственный таймер у вас есть тот, который назначен планировщику? – LPs

+0

На самом деле есть 2 аппаратных таймера, а также прерывание системы, которое срабатывает с интервалом в 1 миллисекунду. Прерывание тика системы не является таймером, вы не можете запросить, сколько времени прошло, вы просто получаете прерывание каждые 1 миллисекунду, которое используется для информирования упреждающего планировщика. Разрешение на 1 миллисекунду также слишком велико для задержек, которые меня интересуют. – satur9nine

+0

Занятое вращение такого долгого времени довольно плохо подходит для современных MCU. Если они будут использовать такие материалы, я бы с подозрением относился к качеству остальных. – Olaf

ответ

6

Установите таймер один раз при запуске и дайте счетчику работать непрерывно. Когда вы хотите начать задержку, прочитайте значение счетчика и запомните это начальное значение. Затем в цикле задержки снова прочитайте значение счетчика и выполните цикл до тех пор, пока значение счетчика минус начальное значение не будет больше или равно запрошенным тикам задержки. (Если вы правильно выполняете вычитание, то опрокидывание будет вымываться, и вам не нужна специальная обработка, чтобы проверить их.)

+2

В качестве примера см. Запись Раймонда Чена: [Использование модульной арифметики, чтобы избежать проблем с переполнением времен] (https://blogs.msdn.microsoft .com/oldnewthing/20050531-22 /? р = 35493). Используйте неподписанные типы, и математика просто работает. –

+0

Другое дело - вы, вероятно, захотите задержать еще один счетчик тиков, чем запрошено (если только запрос не должен ждать нулевых тиков), чтобы справиться с тем фактом, что первый считываемый таймер может быть только наносекундой до того, как отметка таймера увеличивается. –

+0

@kkrambo Это звучит хорошо. Можете ли вы объяснить, почему это решение предпочтительнее использования счетчика циклов процессора? Я предполагаю, что это лучше, потому что это не требует какой-либо регулировки, основанной на частоте процессора. – satur9nine

2

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

Больше внимания вызывает тот факт, что вы спине блокируете поток, ожидающий таймера. Помимо использования ЦП, и в зависимости от того, какая у вас ОС (или если у вас есть ОС), вы можете легко ввести проблемы инверсии потоков или даже полностью заблокировать блокировки. Возможно, лучше использовать примитивы потоков, чтобы любая ОС могла фактически спать ваши потоки и разбудить их, когда это необходимо.

Смежные вопросы