Миландр

Ключевым подразделением нашей компании
является Центр Проектирования интегральных микросхем
Текущее время: 2021-ноя-28 02:50

Часовой пояс: UTC+03:00




Начать новую тему  Ответить на тему  [ 8 сообщений ] 
Автор Сообщение
СообщениеДобавлено: 2020-ноя-18 19:28 
Не в сети

Зарегистрирован: 2019-апр-11 19:37
Сообщения: 4
Организация: НПЦАП
Здравствуйте!

Возникла странная ситуация с потерей прерываний от таймера при специфических условиях.

Таймер в режиме захвата.
На два канала таймера приходят две последовательности импульсов с одинаковым периодом.
В ходе работы временной сдвиг между этими последовательностями изменяется.
Задача измерять этот временной сдвиг.

Частота заполнения счетчика 20МГц. Период следования входных импульсов 1024 мкс.
Временной сдвиг между последовательностями изменяется от 0 до 1024 мкс.

Схема работает нормально, как и ожидалось, за исключением одного особого случая.

По приходу очередного импульса в обработчике прерывания считывается CCR соответствующего канала
и сбрасывается флаг прерывания этого канала в регистре STATUS примерно так:
const uint32_t stat = MDR_TIMER1->STATUS;
if (stat & TIMER_STATUS_CCR_CAP_CH1) {
	t1 = MDR_TIMER1->CCR1;
}
if (stat & TIMER_STATUS_CCR_CAP_CH2) {
	t2 = MDR_TIMER1->CCR2;
}
MDR_TIMER1->STATUS &= ~stat;
Данная схема работает отлично. Даже если два импульса приходят одновременно на два канала,
потерь не происходит и фиксируются корректные отсчеты таймера.

Однако, если во время обработки прерывания, в момент сброса флага прерывания в регистре STATUS,
приходит импульс по второму каналу, то его прерывание теряется.
Такой сбой происходит только если второй импульс приходит в пределах плюс-минус 100 нс от момента
вызова MDR_TIMER1->STATUS &= ~stat. В других случаях схема работает корректно.


Вернуться к началу
СообщениеДобавлено: 2020-ноя-18 20:05 
Не в сети

Зарегистрирован: 2018-янв-05 23:41
Сообщения: 355
Организация: ФГУП "РФЯЦ-ВНИИЭФ"
sdpark писал(а): *
если во время обработки прерывания, в момент сброса флага прерывания в регистре STATUS,
приходит импульс по второму каналу, то его прерывание теряется.
Такой сбой происходит только если второй импульс приходит в пределах плюс-минус 100 нс от момента
Код
MDR_TIMER1->STATUS &= ~stat;
не является потоковобезопасным.
Сброс битов этой строкой не атомарен. Это операция чтение-модификация-запись. В вашем случае в короткий промежуток времени, где-то между чтением и записью, происходит аппаратное изменение регистра STATUS. Взводится ещё один флаг. Вы же этого не видите и не знаете об этом. И при последней записи затираете аппаратно взведенный флаг предыдущим значением, прочитанным из регистра до его установки.
Решение - делать сброс отдельных битов регистра STATUS через запись нуля в bit-band регион.


Вернуться к началу
СообщениеДобавлено: 2020-ноя-18 20:09 
Не в сети

Зарегистрирован: 2018-мар-18 15:49
Сообщения: 273
Организация: StartMilandr.ru
Попробуйте поставить бит 4 в регистрах CHx_CNTRL2.
Если поможет, то это не прерывание пропадает, а не успевает обновляться регистр CCR. Если вы по нему отслеживаете наличие прерываний.
https://github.com/StartMilandr/Bugs/tr ... ncChannels

PS, IMHO: Bitband - это фича ядра, оно так-же читает регистр периферии, меняет значение и записывает назад. Только делает это не отпуская шину, поэтому операция атомарна для исполнения кода. Но периферия про BitBand ничего не знает.


Вернуться к началу
СообщениеДобавлено: 2020-ноя-18 20:39 
Не в сети

Зарегистрирован: 2019-апр-11 19:37
Сообщения: 4
Организация: НПЦАП
StartMilandr писал(а): *
Попробуйте поставить бит 4 в регистрах CHx_CNTRL2.
Эти разряды выставляются при инициализации, чтобы в обработчике прерывания не дожидаться появления флага.


Вернуться к началу
СообщениеДобавлено: 2020-ноя-18 20:42 
Не в сети

Зарегистрирован: 2019-апр-11 19:37
Сообщения: 4
Организация: НПЦАП
Спасибо. Про потокобезопасность и bit-band я не подумал. Завтра попробую


Вернуться к началу
СообщениеДобавлено: 2020-ноя-18 22:21 
Не в сети

Зарегистрирован: 2010-сен-21 12:57
Сообщения: 770
Откуда: г. Санкт-Петербург
Вместо MDR_TIMER1->STATUS &= ~stat; вставьте MDR_TIMER1->STATUS = ~stat;
Потому что запись единичных бит в MDR_TIMER1->STATUS его содержание не изменяет.
p.s. bit-band в вашем случае не поможет.


Вернуться к началу
СообщениеДобавлено: 2020-ноя-19 12:30 
Не в сети

Зарегистрирован: 2019-апр-11 19:37
Сообщения: 4
Организация: НПЦАП
Спасибо всем ответившим.

Действительно, дело было в том, что я не атомарно сбрасывал флаги в регистре STATUS таймера.


Вернуться к началу
СообщениеДобавлено: 2021-апр-02 18:01 
Не в сети

Зарегистрирован: 2018-фев-11 17:46
Сообщения: 57
Организация: ФГБУ «ИПГ»
vasili писал(а): *
Вместо MDR_TIMER1->STATUS &= ~stat; вставьте MDR_TIMER1->STATUS = ~stat;
Потому что запись единичных бит в MDR_TIMER1->STATUS его содержание не изменяет.
p.s. bit-band в вашем случае не поможет.
Дополню, если переменная stat далее используется в процедуре обработке прерываний (одно прерывание на все события по таймеру) добавить
stat &=MDR_TIMER1->IE;


Вернуться к началу
Показать сообщения за:  Поле сортировки  
Начать новую тему  Ответить на тему  [ 8 сообщений ] 

Часовой пояс: UTC+03:00


Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и 3 гостя


Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете добавлять вложения

Перейти: 

cron
Создано на основе phpBB® Forum Software © phpBB Limited
Русская поддержка phpBB