|
|
  |
STM32F407 + прерывание + время реакции, Меняется время реакции на внешнее событие |
|
|
|
Jul 26 2015, 19:07
|
Местный
  
Группа: Участник
Сообщений: 291
Регистрация: 11-04-14
Из: Саратов
Пользователь №: 81 335

|
Дорогие коллеги! Сталкивался ли кто нибудь с такой тонкой и непонятной мне проблемой - значительным изменением времени входа в обработчик прерывания по внешнему событию в зависимости от команд, выполняемых в этот момент в основной программе? Конкретная ситуация: В микроконтроллере STM32F407 в main-е крутится некая большая программа. Когда наступает внешнее событие, а именно - отрицательный фронт на EXTI_Line1, вызывается обработчик прерывания void EXTI1_IRQHandler(void). В нём обнуляется таймер TIM6, тактируемый частотой 84 МГц, и начинается вывод информации в виде набора импульсов, привязанных к значениям TIM6. Когда вывод закончен - выходим из обработчика (TIM6 оставляем молотить впустую). Замечено следующее: Время от момента внешнего события до появления первого импульса на выходе нестабильно и меняется (по осциллографу) более чем на 0,2 мкс при тактировании ядра 168 МГц. Иными словами, время вызова обработчика может увеличиваться (или уменьшаться) аж на 34 такта! Причём меняется оно в зависимости от кода, выполняемого в данный момент в main-е. Самое большое изменение этого времени (в сторону уменьшения) происходит при выполнении (в main-е) цикла очистки области памяти: for(i = 0; i < 60768; i++) *j++ = Сonst; А согласно описанию на Cortex-3 время вызова обработчика прерывания составляет от 6 до 11 тактов ядра. И уж никак не должно зависеть от содержания прерываемой программы (DMA не используется)! В чём причина этого явления и как с ним бороться? Буду признателен за любые идеи или информацию.
|
|
|
|
|
Jul 27 2015, 05:46
|
Местный
  
Группа: Участник
Сообщений: 291
Регистрация: 11-04-14
Из: Саратов
Пользователь №: 81 335

|
Цитата(aaarrr @ Jul 26 2015, 22:29)  В некоторой степени все же зависит.
Непредсказуемую задержку может вносить работа кэш контроллера флеш-памяти. Интересная мысль - а сколько может вносить, и чем можно на эту задержку влиять? Вообще в STM32F4, если верить описанию, время отклика на событие прерывания составляет 12 тактов - если прерывается фоновая программа, 6 тактов - если прерывается другое низкоприоритетное прерывание, 18 тактов - если прерывание произошло в момент выхода из другого прерывания (выход из прерывания занимает 12 тактов). В итоге имеем максимально возможный шум (или биения) на выходе до: 18 - 6 = 12 тактов. Для тактовой частоты 168 МГц это составит 0,072 мкс. И это максимум! А у меня в реале - 0,2 мкс. Причём даже с отключёнными другими прерываниями. Что касается зависимости от фоновой программы. Учитывая, что в STM32F407 организован аппаратный конвейер, влияние фоновой программы на обработчик, вернее на время его вызова, не должно быть вообще! А у меня оно есть, да ещё какое сильное! Я уж даже думал, что столь короткий цикл в фоновой программе так меняет ток потребления МК, что не выдерживает стабилизатор питания, и поэтому сбивается PLL в STM32F4. Но это не подтвердилось - обвешанный большими ёмкостями МК ведёт себя точно также, как и в стандартном включении.
|
|
|
|
|
Jul 27 2015, 06:09
|
Местный
  
Группа: Участник
Сообщений: 291
Регистрация: 11-04-14
Из: Саратов
Пользователь №: 81 335

|
Цитата(ViKo @ Jul 27 2015, 06:03)  Может, нестабильную задержку создает перезапуск таймера, а не вход в прерывание. Задайте в прерывании дергание ножкой порта, для проверки. Нет, это исключено. Период внешнего события - 64 мкс, а период перезапуска таймера вдвое больше (я по нему идентифицирую исчезновение внешнего сигнала). Сброс таймера в единственном месте - вторая команда обработчика прерывания. Да и потом - даже если таймер что-то там делает, влияние на задержку реакции оказывает именно содержание фоновой программы. Это проверено: когда я закомментировал цикл очистки памяти в фоновой программе, это явление исчезло! Цитата(Огурцов @ Jul 27 2015, 08:53)  а если умножить на 5 тактов ожидания, то получится даже хуже вашего, или ваше в среднем Не понял кто кого ждёт. Все команды фоновой программы занимают по 1 такту. DMA нет. Реакция на внешнее событие определяется укладкой в стек информации о возврате и занимает от 6 до 18 тактов. Я отключал все другие прерывания, в этом случае реакция должна быть максимально стабильной - 12-13 тактов. Т.е. нестабильность реакции - 1 такт! А у меня в реальности ничего не меняется - фоновая программа непостижимым образом изменяет время реакции на прерывания до 34 тактов! Цитата(Огурцов @ Jul 27 2015, 08:53)  а если умножить на 5 тактов ожидания, то получится даже хуже вашего, или ваше в среднем Не понял кто кого ждёт. Все команды фоновой программы занимают по 1 такту. DMA нет. Реакция на внешнее событие определяется укладкой в стек информации о возврате и занимает от 6 до 18 тактов. Я отключал все другие прерывания, в этом случае реакция должна быть максимально стабильной - 12-13 тактов. Т.е. нестабильность реакции - 1 такт! А у меня в реальности ничего не меняется - фоновая программа непостижимым образом изменяет время реакции на прерывания до 34 тактов!
|
|
|
|
|
Jul 27 2015, 06:41
|
Местный
  
Группа: Участник
Сообщений: 291
Регистрация: 11-04-14
Из: Саратов
Пользователь №: 81 335

|
Цитата(aaarrr @ Jul 27 2015, 09:27)  Попробуйте сделать следующее: 1. Внешнее прерывание замените на прерывание от таймера с высокой тактовой частотой (84МГц). При входе в прерывание считывайте CNT. Так получите значительно более точное измерение времени входа. 2. Перенесите обработчик в RAM, сравните результаты. Маленькое уточнение - эти два пункта надо сделать одновременно или по одному? Пункт 1, я понял, нужен, чтобы исключить биения внешней частоты и источника тактирования МК. Я это попробую сегодня сделать. А вот пункт 2 - поясните. Я такого никогда не делал и не знаю (пока) как это сделать. Но главное - зачем, ведь в описании на Cortex, насколько я помню, программа из RAM выполняется медленнее, чем из FLASH. А у меня и так МК едва успевает выполнять нужную работу, причём только после оптимизации компилятором. Если замедлить работу обработчика, работа программы развалится и уже ничего невозможно будет измерить.
|
|
|
|
|
Jul 27 2015, 07:12
|
Местный
  
Группа: Участник
Сообщений: 291
Регистрация: 11-04-14
Из: Саратов
Пользователь №: 81 335

|
Цитата(scifi @ Jul 27 2015, 09:49)  Вот тут расписано про задержку на входе в обработчик прерывания у Cortex-M3 и Cortex-M4: "between eight and 32 cycles if the floating point context in a Cortex-M4 with FPU is stacked immediately". Кстати, у вас нигде прерывания не запрещаются? Атомарные операции и всё такое. Спасибо за ссылочку: на первый же взгляд вижу намёк на причину - на возможные такты ожидания при обращении к слову по частям. А ведь у меня этого много. Буду разбираться. Прерывания не запрещаются. Флаги очищаются в конце обработчика, так что вложенные прерывания исключены. Атомарные операции... Наверное, вы правы! Для экономии памяти я сплошь работаю с невыровненными данными в ОЗУ, а ведь это может приводить к аппаратным задержкам! Это похоже на правду, ведь цикл очистки массива у меня идёт по байтовому указателю.
|
|
|
|
|
Jul 27 2015, 07:30
|
Знающий
   
Группа: Участник
Сообщений: 835
Регистрация: 9-08-08
Из: Санкт-Петербург
Пользователь №: 39 515

|
Цитата(ШСА @ Jul 26 2015, 22:07)  Дорогие коллеги! Сталкивался ли кто нибудь с такой тонкой и непонятной мне проблемой - значительным изменением времени входа в обработчик прерывания по внешнему событию в зависимости от команд, выполняемых в этот момент в основной программе? Конкретная ситуация: В микроконтроллере STM32F407 в main-е крутится некая большая программа. Когда наступает внешнее событие, а именно - отрицательный фронт на EXTI_Line1, вызывается обработчик прерывания void EXTI1_IRQHandler(void). В нём обнуляется таймер TIM6, тактируемый частотой 84 МГц, и начинается вывод информации в виде набора импульсов, привязанных к значениям TIM6. Когда вывод закончен - выходим из обработчика (TIM6 оставляем молотить впустую). Если вам надо обеспечить постоянное время реакции на фронт входного сигнала, то следует защёлкнуть этот фронт в capture unit, и привязать выходные сигналы к защёлкнутому времени таким образом, чтобы процессор всегда успевал среагировать. Правда, время реакции получится по-максимуму, зато стабильно. Если нужно совсем быструю реакцию, лучше использовать FPGA. Время входа в прерывание можно сократить, если использовать FIQ, а не IRQ, но его на большинстве кортексов нет.
|
|
|
|
|
Jul 27 2015, 07:49
|
Гуру
     
Группа: Свой
Сообщений: 4 256
Регистрация: 17-02-06
Пользователь №: 14 454

|
Цитата Флаги очищаются в конце обработчика, так что вложенные прерывания исключены. Вроде это как раз гарантия создания повторного прерывания  Вложенные прерывания у вас исключает NVIC, а вот очищенный в конце флаг может вызвать прерывание повторно из-за конвейеров, нужны будут барьеры на выходе. Опять же ускоритель флешь, если вы попадаете не на 16 на 32 битные команды то ему больше 4 команд не выбрать, а частота выборки команд у него в почти 8 раз меньше, так что скакнув прерыванием в не закишированную область, да еще и попав на 32 битную команду, у вас все здорово притормозится, а в след раз вы можете попасть уже в область выбранную и сохраненную в ускорителе, а потом вы ее можете почистить и так по кругу, так что у вас там есть где набрать нестабильность ИМХО... Цитата ремя входа в прерывание можно сократить, если использовать FIQ, а не IRQ, но его на большинстве кортексов нет. Я могу ошибаться, но вроде как в кортексах уже NVIC, и потому деления на быстрое и медленное уже нет ни в большинстве, а во всех кортексах...
|
|
|
|
|
  |
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|