Перейти к содержанию
    

STM32F407 + прерывание + время реакции

Дорогие коллеги!

Сталкивался ли кто нибудь с такой тонкой и непонятной мне проблемой - значительным изменением времени входа в обработчик прерывания по внешнему событию в зависимости от команд, выполняемых в этот момент в основной программе?

Конкретная ситуация: В микроконтроллере 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 не используется)! :wacko:

 

В чём причина этого явления и как с ним бороться?

Буду признателен за любые идеи или информацию.

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

...никак не должно зависеть от содержания прерываемой программы (DMA не используется)! :wacko:

В некоторой степени все же зависит.

 

В чём причина этого явления и как с ним бороться?

Буду признателен за любые идеи или информацию.

Непредсказуемую задержку может вносить работа кэш контроллера флеш-памяти.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Может, нестабильную задержку создает перезапуск таймера, а не вход в прерывание. Задайте в прерывании дергание ножкой порта, для проверки.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

В некоторой степени все же зависит.

 

 

Непредсказуемую задержку может вносить работа кэш контроллера флеш-памяти.

 

Интересная мысль - а сколько может вносить, и чем можно на эту задержку влиять?

Вообще в STM32F4, если верить описанию, время отклика на событие прерывания составляет 12 тактов - если прерывается фоновая программа, 6 тактов - если прерывается другое низкоприоритетное прерывание, 18 тактов - если прерывание произошло в момент выхода из другого прерывания (выход из прерывания занимает 12 тактов). В итоге имеем максимально возможный шум (или биения) на выходе до: 18 - 6 = 12 тактов. Для тактовой частоты 168 МГц это составит 0,072 мкс. И это максимум! А у меня в реале - 0,2 мкс. Причём даже с отключёнными другими прерываниями.

Что касается зависимости от фоновой программы. Учитывая, что в STM32F407 организован аппаратный конвейер, влияние фоновой программы на обработчик, вернее на время его вызова, не должно быть вообще! А у меня оно есть, да ещё какое сильное!

Я уж даже думал, что столь короткий цикл в фоновой программе так меняет ток потребления МК, что не выдерживает стабилизатор питания, и поэтому сбивается PLL в STM32F4. Но это не подтвердилось - обвешанный большими ёмкостями МК ведёт себя точно также, как и в стандартном включении.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

а если умножить на 5 тактов ожидания, то получится даже хуже вашего, или ваше в среднем

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Может, нестабильную задержку создает перезапуск таймера, а не вход в прерывание. Задайте в прерывании дергание ножкой порта, для проверки.

 

Нет, это исключено. Период внешнего события - 64 мкс, а период перезапуска таймера вдвое больше (я по нему идентифицирую исчезновение внешнего сигнала). Сброс таймера в единственном месте - вторая команда обработчика прерывания.

Да и потом - даже если таймер что-то там делает, влияние на задержку реакции оказывает именно содержание фоновой программы. Это проверено: когда я закомментировал цикл очистки памяти в фоновой программе, это явление исчезло!

 

а если умножить на 5 тактов ожидания, то получится даже хуже вашего, или ваше в среднем

 

Не понял кто кого ждёт.

Все команды фоновой программы занимают по 1 такту. DMA нет. Реакция на внешнее событие определяется укладкой в стек информации о возврате и занимает от 6 до 18 тактов. Я отключал все другие прерывания, в этом случае реакция должна быть максимально стабильной - 12-13 тактов. Т.е. нестабильность реакции - 1 такт! А у меня в реальности ничего не меняется - фоновая программа непостижимым образом изменяет время реакции на прерывания до 34 тактов!

 

 

а если умножить на 5 тактов ожидания, то получится даже хуже вашего, или ваше в среднем

 

Не понял кто кого ждёт.

Все команды фоновой программы занимают по 1 такту. DMA нет. Реакция на внешнее событие определяется укладкой в стек информации о возврате и занимает от 6 до 18 тактов. Я отключал все другие прерывания, в этом случае реакция должна быть максимально стабильной - 12-13 тактов. Т.е. нестабильность реакции - 1 такт! А у меня в реальности ничего не меняется - фоновая программа непостижимым образом изменяет время реакции на прерывания до 34 тактов!

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Попробуйте сделать следующее:

1. Внешнее прерывание замените на прерывание от таймера с высокой тактовой частотой (84МГц). При входе в прерывание считывайте CNT. Так получите значительно более точное измерение времени входа.

2. Перенесите обработчик в RAM, сравните результаты.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Попробуйте сделать следующее:

1. Внешнее прерывание замените на прерывание от таймера с высокой тактовой частотой (84МГц). При входе в прерывание считывайте CNT. Так получите значительно более точное измерение времени входа.

2. Перенесите обработчик в RAM, сравните результаты.

 

Маленькое уточнение - эти два пункта надо сделать одновременно или по одному?

Пункт 1, я понял, нужен, чтобы исключить биения внешней частоты и источника тактирования МК. Я это попробую сегодня сделать. А вот пункт 2 - поясните. Я такого никогда не делал и не знаю (пока) как это сделать. Но главное - зачем, ведь в описании на Cortex, насколько я помню, программа из RAM выполняется медленнее, чем из FLASH. А у меня и так МК едва успевает выполнять нужную работу, причём только после оптимизации компилятором. Если замедлить работу обработчика, работа программы развалится и уже ничего невозможно будет измерить.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Вот тут расписано про задержку на входе в обработчик прерывания у Cortex-M3 и Cortex-M4: "between eight and 32 cycles if the floating point context in a Cortex-M4 with FPU is stacked immediately".

Кстати, у вас нигде прерывания не запрещаются? Атомарные операции и всё такое.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Интересно сравнить результаты при работе из флеш и RAM.

Про пункты:

1. Чтобы исключить осциллограф прежде всего :)

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

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

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

Всё не так просто. Можно разогнать программу в ОЗУ. Для этого код должен сидеть в куске ОЗУ 112 КБ (начинается с адреса 0x20000000), подключенном к I-bus, ОЗУ надо замапить на адрес 0, а данные расположить в CCM (64 КБ). В этом случае всё должно работать с нулевыми задержками.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Можно разогнать программу в ОЗУ.

Можно, просто для проверки предположения о влиянии "ускорителя" флеш это не нужно.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Вот тут расписано про задержку на входе в обработчик прерывания у Cortex-M3 и Cortex-M4: "between eight and 32 cycles if the floating point context in a Cortex-M4 with FPU is stacked immediately".

Кстати, у вас нигде прерывания не запрещаются? Атомарные операции и всё такое.

 

Спасибо за ссылочку: на первый же взгляд вижу намёк на причину - на возможные такты ожидания при обращении к слову по частям. А ведь у меня этого много. Буду разбираться.

Прерывания не запрещаются. Флаги очищаются в конце обработчика, так что вложенные прерывания исключены.

Атомарные операции... Наверное, вы правы! Для экономии памяти я сплошь работаю с невыровненными данными в ОЗУ, а ведь это может приводить к аппаратным задержкам! Это похоже на правду, ведь цикл очистки массива у меня идёт по байтовому указателю.

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Дорогие коллеги!

Сталкивался ли кто нибудь с такой тонкой и непонятной мне проблемой - значительным изменением времени входа в обработчик прерывания по внешнему событию в зависимости от команд, выполняемых в этот момент в основной программе?

Конкретная ситуация: В микроконтроллере STM32F407 в main-е крутится некая большая программа. Когда наступает внешнее событие, а именно - отрицательный фронт на EXTI_Line1, вызывается обработчик прерывания void EXTI1_IRQHandler(void). В нём обнуляется таймер TIM6, тактируемый частотой 84 МГц, и начинается вывод информации в виде набора импульсов, привязанных к значениям TIM6. Когда вывод закончен - выходим из обработчика (TIM6 оставляем молотить впустую).

Если вам надо обеспечить постоянное время реакции на фронт входного сигнала, то следует защёлкнуть этот фронт в capture unit, и привязать выходные сигналы к защёлкнутому времени таким образом, чтобы процессор всегда успевал среагировать. Правда, время реакции получится по-максимуму, зато стабильно. Если нужно совсем быструю реакцию, лучше использовать FPGA.

Время входа в прерывание можно сократить, если использовать FIQ, а не IRQ, но его на большинстве кортексов нет.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Флаги очищаются в конце обработчика, так что вложенные прерывания исключены.

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

 

Опять же ускоритель флешь, если вы попадаете не на 16 на 32 битные команды то ему больше 4 команд не выбрать, а частота выборки команд у него в почти 8 раз меньше, так что скакнув прерыванием в не закишированную область, да еще и попав на 32 битную команду, у вас все здорово притормозится, а в след раз вы можете попасть уже в область выбранную и сохраненную в ускорителе, а потом вы ее можете почистить и так по кругу, так что у вас там есть где набрать нестабильность ИМХО...

 

ремя входа в прерывание можно сократить, если использовать FIQ, а не IRQ, но его на большинстве кортексов нет.

Я могу ошибаться, но вроде как в кортексах уже NVIC, и потому деления на быстрое и медленное уже нет ни в большинстве, а во всех кортексах...

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Присоединяйтесь к обсуждению

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

Гость
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...