Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: STM32F407 + прерывание + время реакции
Форум разработчиков электроники ELECTRONIX.ru > Микроконтроллеры (MCs) > ARM
Страницы: 1, 2, 3
ШСА
Наконец сегодня дошли руки проверить хоть какие-то гипотезы. Собственно, рабочих гипотез осталось две.
Начну с первой. jcxz предположил, что причиной влияния фоновой программы на время реакции обработчика и является сохранение в стеке регистров FPU и предложил его запретить. Такой запрет не помешал бы работе системы, поскольку FPU в обработчиках прерываний не используется, а значит и состояние FPU от прерывания не изменилось бы.
В STM32F4 это делается просто: FPU->FPCCR &= ~((1U << FPU_FPCCR_ASPEN_Pos) | (1U << FPU_FPCCR_LSPEN_Pos));
В результате явление не исчезло, ну существенно уменьшилось. Т.е влияние фоновой программы на прерывания осталось, но флуктуации времени запуска обработчика прерываний снизились не менее чем в два раза.
Мораль: Количество сохраняемых в стеке регистров ЦП при прерывании зависит не от того, выполняло или нет в этот момент FPU какую нибудь команду, а от того, что записано в регистре CONTROL с помощью FPU->FPCCR.
Поэтому запрещая сохранение регистров FPU можно изменить среднее время реакции обработчиков на внешние события и изменить интенсивность использования стека. Но к флуктуациям времени вызова обработчика в зависимости от команды, выполняемой в этот момент фоновой программой, это не имеет отношения.

Осталась вторая гипотеза. scifi полагал, что время реакции обработчика зависит от длины кэша команд МК. Т.е. механизм такой: если фоновая программа выполняет длительный короткий цикл, в течение которого происходит несколько прерываний, то после первого прерывания из кэша не вытесняется начало обработчика прерывания и все последующие прерывания происходят быстрее.
Чтобы проверить эту идею нужно было очистить кэш команд перед выходом из обработчика.
Я не нашёл (да пока и не искал) такой команды, но чтобы проверить эту идею в фоновой программе внутри короткого цикла вставил вызов небольшой функции, которая ничего полезного не делала, но и ничего не портила. Фактически, цикл перестал быть коротким. Результат - эти флуктуации исчезли!
Мораль сногсшибательная: кэш команд в STM32F4, который так здорово "разгоняет" ЦП, может быть причиной непредсказуемых флуктуаций времени реакции обработчиков на внешние события. Причём флуктуаций весьма чувствительных - до 400 нс, когда используется FPU и включено сохранение его регистров в стеке (это происходит по умолчанию при включении FPU), и когда различные прерывания конкурируют между собой. А управлять этой непредсказуемостью будет фоновая программа!

Так что мой обработчик придётся выбросить.
Всем, кто принял участие в этом мозговом штурме ОГРОМНОЕ СПАСИБО!
И, конечно, jcxz и scifi от меня особая благодарность, за активизацию моих мозгов.


Цитата(jcxz @ Jul 30 2015, 08:09) *
Советую поискать там что-нить типа Quad-SPI или SDIO. Они позволяют до 4 линий параллельно выводить.


У STM32F407 есть одна неприятная особенность - пины SDIO пересекаются с пинами видеокамеры DCMI. Придётся выбирать. А Quad-SPI там нет.
jcxz
Цитата(ШСА @ Jul 30 2015, 23:13) *
Мораль: Количество сохраняемых в стеке регистров ЦП при прерывании зависит не от того, выполняло или нет в этот момент FPU какую нибудь команду, а от того, что записано в регистре CONTROL с помощью FPU->FPCCR.

Думаю что всё-же зависит если включено Lazy context save. При этом если FPU не использовался, то место просто резервируется в стеке без реальной записи, а на это такты не тратятся, только память.
SasaVitebsk
Цитата(ШСА @ Jul 30 2015, 20:13) *
Мораль: Количество сохраняемых в стеке регистров ЦП при прерывании зависит не от того, выполняло или нет в этот момент FPU какую нибудь команду, а от того, что записано в регистре CONTROL с помощью FPU->FPCCR.

Вы хотя бы задумались. А как может быть по другому?!
Какая разница где именно в фоновой задече используется FPU? Если имеется шанс запортить используемые регистры, то их надо сохранять!
Здесь на крайняк, может компилятор грамотно обсчитывать имеется ли в Ваших прерываниях работа с FPU. Но учитывая как работает компилятор, и этого не получается.
Например Вы можете вызвать из прерывания ф-цию, которая использует FPU. Или Вы можете написать обработчик на ассемблере и компилятор даже знать не будет о том, что Вы в прерывании используете FPU. Поэтому действия разработчиков процессора единственно верны.

Цитата
Мораль сногсшибательная: кэш команд в STM32F4, который так здорово "разгоняет" ЦП, может быть причиной непредсказуемых флуктуаций времени реакции обработчиков на внешние события. Причём флуктуаций весьма чувствительных - до 400 нс, когда используется FPU и включено сохранение его регистров в стеке (это происходит по умолчанию при включении FPU), и когда различные прерывания конкурируют между собой. А управлять этой непредсказуемостью будет фоновая программа!

А здесь Вы просто капитан очевидность! biggrin.gif
Именно за счёт этого и получен выигрыш в быстродействии. Я вообще не понимаю что Вас удивляет? Так работают все процы CISC, в частности. И совершенно очевидно, что в Cortex-M7 джитер будет ещё выше.
Он будет в любом процессоре. В процах без кэша он будет меняться на разницу в времени исполнения команд, которые Вы используете в фоновой задаче. Например в AVR, при применении умножения +1 такт.

Поэтому Вам несколько раз настойчиво советуют использовать аппаратные средства либо самого процессора либо внешнего устройства.
ШСА
Цитата(SasaVitebsk @ Jul 31 2015, 07:46) *
Поэтому действия разработчиков процессора единственно верны.
Именно за счёт этого и получен выигрыш в быстродействии. Я вообще не понимаю что Вас удивляет?


А кто говорит, что разработчики из ST что-то сделали неправильно? STM32F4 - серия шикарных микроконтроллеров! Но, как всё шикарное, требуют аккуратного обращения.
А удивляет меня не задержка вызова прерываний, и не джиттер при разборках обработчиков между собой. Это всё общеизвестно. А вот то, что на время вызова обработчика может влиять содержимое фоновой программы - для меня открытие. Я с таким никогда не встречался и не читал о таком. Результат проведённого исследования - понимание механизма взаимовлияния фона на реактивность системы, которое позволит осознаннее выбирать программные средства. Правильно заметил jcxz, что от AVR-ные подходы для ARM-ов не всегда годятся.
И понять это явление помогло именно включённое FPU, которое на порядок увеличило этот эффект, и заставило разбираться до конца.
scifi
Цитата(ШСА @ Jul 31 2015, 10:04) *
А вот то, что на время вызова обработчика может влиять содержимое фоновой программы - для меня открытие...
Правильно заметил jcxz, что от AVR-ные подходы для ARM-ов не всегда годятся.

Нет-нет, рано класть AVR-ные подходы на дальнюю полку. Возьмите многоядерный МК типа LPC4370. Там 3 процессора. Один из них можно натравить на узкую задачу с жёсткой времянкой - и дело в шляпе :-)
Golikov A.
любой проц можно поставить на жесткую времянку, только для этого надо правильно написать программу.

У вас проц молотит на частое за 100 МГц, при этом из флеши можно выбирать команды на частоте порядка 20 МГц, и должно стать ежу понятно что никакие увеличения шины выбора команд не смогут решить эту разность частот, за исключением линейных участков кода....

А обдумав этот факт становиться понятно что вид программы с точки зрения переходов, должен влиять на времянку выполнения программы.

АВР просто не превысила по своей скорости, скорость флешь, потому там такого и не было. Возьмите АРМ, перепихайте всю программу в ОЗУ и погнали...
jcxz
Цитата(scifi @ Jul 31 2015, 14:05) *
Возьмите многоядерный МК типа LPC4370. Там 3 процессора. Один из них можно натравить на узкую задачу с жёсткой времянкой - и дело в шляпе :-)

Кстати - всё хотелось узнать поподробнее про эти многоядерные LPC: а как там память программ и данных организована?
Общая или для каждого ядра своя? И как шины к памяти проложены?
Можно-ли написать ПО так, чтобы каждое ядро работало со своим набором регионов памяти/шин доступа к ним, оставив только один общий регион для межпроцессорного обмена?
Если всё-таки там ядра конкурируют за какие-либо ресурсы (регионы памяти, шины), или программа так написана, что имеется много
конфликтов по ресурсам, то ядра будут влиять друг на друга (на скорость выполнения кода друг друга).
scifi
Цитата(jcxz @ Jul 31 2015, 13:05) *
Кстати - всё хотелось узнать поподробнее про эти многоядерные LPC: а как там память программ и данных организована?
Общая или для каждого ядра своя? И как шины к памяти проложены?

Конкретно в LPC4370 нет наботной флеши, но есть несколько банков ОЗУ, подключенных разнообразными способами к многопортовому шинному коммутатору. Так что да, там есть возможность распределить банки памяти так, чтобы процессоры трудились, не мешая друг другу.
ШСА
Цитата(Golikov A. @ Jul 31 2015, 11:33) *
А обдумав этот факт становится понятно что вид программы с точки зрения переходов, должен влиять на времянку выполнения программы.


Согласен. И хотя вы все будете смеяться, но я опять чего-то недопонимаю.
Чтобы не связываться с DMA, решил попытаться использовать захват сигнала через таймер. Но перед этим, чтобы быть уверенным в конечном результате, решил проверить экспериментально верность нашей "гениальной теории".
Способ мне пришёл в голову очень простой: Вызов обработчика происходит по переднему фронту синхроимпульса, и пусть флуктуации вызова обработчика достигают 0,2 мкс. Поскольку длительность этого внешнего синхроимпульса равна 4,7 мкс, то очевидно, что его задний фронт будет гарантированно в то время, когда обработчик уже будет вовсю работать. Значит, если вставить цикл ожидания окончания синхроимпульса и сбрасывать таймер после этого, я должен получить гарантированное избавление от зависимости от времени вызова обработчика, а значит, и от содержимого фоновой программы.
Но эксперимент (критерий истины) показал, что эффект влияния фоновой программы остался! Хотя, величина флуктуаций фазы первого выводимого импульса стала значительно меньше, чем раньше (на глазок - в 2,5 - 3 раза).


Цитата(scifi @ Jul 31 2015, 13:26) *
Конкретно в LPC4370 нет наботной флеши,


А что это такое "наботная?"
Golikov A.
набортная, на борту проца....
aaarrr
Цитата(ШСА @ Jul 31 2015, 22:00) *
Значит, если вставить цикл ожидания окончания синхроимпульса...

И сколько тактов длится итерация цикла?
Golikov A.
Цитата
Но эксперимент (критерий истины) показал, что эффект влияния фоновой программы остался! Хотя, величина флуктуаций фазы первого выводимого импульса стала значительно меньше, чем раньше (на глазок - в 2,5 - 3 раза).


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

Ну и работу ускорителей для циклов с переходами тоже никто не отменял.... кто его знает как оно там команды выбирает и хеширует, то у него есть кусок куда переход, то нет... Это же не полноценный кэш, там банки строк в 4-8 команд, да еще поди и с выравниванием....

бросайте вы ваши критерии истины%)))) и делайте как говорят, отдавайте контроль железным блокам с более четкой времянкой....



Цитата
И сколько тактов длится итерация цикла?

ну вот пока ехидно разжевывал, опередили%)))))
jcxz
Цитата(ШСА @ Aug 1 2015, 01:00) *
Но эксперимент (критерий истины) показал, что эффект влияния фоновой программы остался! Хотя, величина флуктуаций фазы первого выводимого импульса стала значительно меньше, чем раньше (на глазок - в 2,5 - 3 раза).

Раз такое делаете, располагать это надо в ОЗУ (ещё лучше - CCM, если есть) и писать на ассемблере с учётом межкомандных времянок.
Golikov A.
ассемблер тут не причем, человека беспокоит не время, а девиации времени начала исполнения. Расположить в РАМ - да, ассемблер - нет необходимости
ШСА
Цитата(Golikov A. @ Jul 31 2015, 11:33) *
любой проц можно поставить на жесткую времянку, только для этого надо правильно написать программу.


Похоже, я приближаюсь к пониманию причин флуктуаций фазы выходного сигнала моего STM32F407, хотя до конца ещё не понимаю. Я провёл очередной эксперимент, и теперь пытаюсь его интерпретировать.
У этого МК имеется две области ОЗУ - процессорная CCM (64К) и присоединённая SRAM (128К), которая ещё сама поделена на две неравные части SRAM1 и SRAM2.
Сначала расскажу как было до сегодняшнего дня.
Использовалась ОЗУ у меня так: в SRAM находились 3 массива - 2 больших видеостраницы и 1 промежуточный массив поменьше (все они байтовые). Все остальные переменные лежали в CCM и использовались как фоновой программой, так и всеми обработчиками. Так вот, когда происходила очистка одной из видеостраниц в коротком цикле фона, переменная цикла и указатель оказывались в CCM, а очищаемые элементы - в SRAM. В этот момент и происходил бросок фазы выходного сигнала МК. Причём бросок на опережение - изображение на мониторе подёргивалось влево.
Теперь сегодня я изменил использование памяти. Одну видеостраницу отправил в CCM, а в SRAM остались только другая видеостраница с пром. массивом.
Картина радикально поменялась. Теперь изображение на мониторе просто перепрыгивает - то левее, то правее в соответствии с переключением отображаемой страницы! Получается, что задержка вывода из CCM и из SRAM отличается очень сильно, а именно на 190 нс. С похожей проблемой столкнулся ещё один страдалец (http://cliffle.com/article/2015/06/11/matrix/#how-to-mess-up-an-entire-scanline). Он свои проблемы объяснил конфликтом шин в Multi-AHB матрице! Если правильно понимаю - к CCM ЦП имеет доступ непосредственно, а к SRAM - через шину AHB3 и матрицу. А порты подключены к AHB1 и подключаются к ЦП через матрицу. Получается, где-то там какой-то конфликт? В общем, STM32F407 скучать не даёт!

Цитата(aaarrr @ Jul 31 2015, 22:11) *
И сколько тактов длится итерация цикла?


Четыре такта (если Вы о цикле ожидания).
ШСА
Цитата(Golikov A. @ Jul 31 2015, 22:18) *
отдавайте контроль железным блокам с более четкой времянкой....


Это будет последнее средство...
aaarrr
Цитата(ШСА @ Aug 1 2015, 18:39) *
Четыре такта (если Вы о цикле ожидания).

Можно увидеть этот цикл в дизассемблированном виде? Не очень представляю, как он может уложиться в четыре такта.
ШСА
Покажу, но уже не сегодня.
Golikov A.
Взять порт
Взять маску
Если ноль прыгнуть
Прыгнуть на взять порт.
Маски и адреса в регистрах уже, в целом можно, но думаю реально там больше.

Переводить на железо это не последние, а правильное решение. Надо дма подтягивать....

Вы не совсем так как надо используете проц, потому у вас много чего интересного вылезает.

У вас есть осцилограф? Очень рекомендую разные моменты повыводить на ноги и поглядеть реальные времянки, сколько проц выбирает данные из памяти, сколько делает переход по условию. Первый и второй раз. АРМы не так просты, их долго разрабатывали, они хороши
aaarrr
Цитата(Golikov A. @ Aug 1 2015, 21:05) *
Маски и адреса в регистрах уже, в целом можно, но думаю реально там больше.

Загрузка - 2 такта, сравнение - 1, переход - 2. У меня получается минимум 5.
Golikov A.
Не вижу возможности вам не верить), а почему загрузка 2?
ШСА
Цитата(Golikov A. @ Aug 1 2015, 21:05) *
Взять порт
Взять маску
Если ноль прыгнуть
Прыгнуть на взять порт.
Маски и адреса в регистрах...
Очень рекомендую разные моменты повыводить на ноги и поглядеть реальные времянки


Да, что-то такое там и было - все константы и указатели в регистрах, сам цикл в кэше... Скорее всего вы правы.
Вообще-то я не заморачивался на этом и такты по тексту не считал. Включил оптимизацию компилятора, взял осциллограф и измерил. Давно это было. Измеренные значения и показали - флуктуации - до 4 тактов.
jcxz
Цитата(Golikov A. @ Aug 1 2015, 13:10) *
ассемблер тут не причем, человека беспокоит не время, а девиации времени начала исполнения. Расположить в РАМ - да, ассемблер - нет необходимости

Причём. Если уж пошёл считать такты, которые зависят от команд, то надо зафиксировать эту последовательность команд, чего не сделать в си (смена компилятора, ключей оптимизации, изменение соседнего участка кода и т.п.).
А девиация времени начала исполнения (для его алгоритма со входом в ISR по фронту сигнала, и ожиданием в цикле спада сигнала) будет равна длине (в тактах) цикла опроса пина порта.
aaarrr
Цитата(Golikov A. @ Aug 1 2015, 21:28) *
Не вижу возможности вам не верить), а почему загрузка 2?

Одиночная LDR выполняется два такта; последовательность из двух LDR может быть выполнена за три такта (а из трех за четыре и т.д.), если адрес для последующей инструкции не зависит от результата предыдущей.
Golikov A.
Ваша правда, другое дело пока лдр искал, нашел что переходы условные бывают 1 такт, правда не вдавался в чем дело.
Ну значит 5 тактов...
jcxz
Когда дело доходит до подсчёта тактов при работе с периферией, тут однозначно надо искать аппаратные пути решения. Только так, имхо.
ViKo
Цитата(aaarrr @ Aug 1 2015, 21:14) *
Загрузка - 2 такта, сравнение - 1, переход - 2. У меня получается минимум 5.

Кейл показывает, что переход длится 1 такт, недавно смотрел для STM32F303.
aaarrr
Цитата(ViKo @ Aug 2 2015, 10:42) *
Кейл показывает, что переход длится 1 такт, недавно смотрел для STM32F303.

А TRM говорит, что не меньше двух, и ему я почему-то доверяю больше:
Цитата
Branches take one cycle for instruction and then pipeline reload for target instruction. Non-taken branches are 1 cycle total.
Taken branches with an immediate are normally 1 cycle of pipeline reload (2 cycles total). Taken branches with register
operand are normally 2 cycles of pipeline reload (3 cycles total). Pipeline reload islonger when branching to unaligned 32-bit
instructions in addition to accesses to slower memory. A branch hint is emitted to the code bus that permits a slower system
to pre-load. This can reduce the branch target penalty for slower memory, but never less than shown here.
ШСА
Цитата(ШСА @ Jul 31 2015, 22:00) *
Но эксперимент (критерий истины) показал, что эффект влияния фоновой программы остался!


Придётся мне покритиковать самого себя. Неправда это, Явление исчезло!
А этот результат, оказывается, произошёл оттого, что я в процессе экспериментов отключил кэш команд, а потом забыл включить! Извините за дезинформацию.

Цитата(ШСА @ Aug 1 2015, 18:39) *
Теперь изображение на мониторе просто перепрыгивает - то левее, то правее в соответствии с переключением отображаемой страницы! Получается, что задержка вывода из CCM и из SRAM отличается очень сильно, а именно на 190 нс.


Величина "прыжка" однозначно зависит от частоты тактирования шин. Когда я повысил частоту тактирования шины AHB1 вдвое (до 168 МГц), "прыжок" уменьшился ровно вдвое.

Чем больше вожусь с этой системой, тем больше хочется задействовать DMA. Но как в этом случае организовать вывод байтов по тетрадам?
jcxz
Цитата(ШСА @ Aug 3 2015, 00:05) *
Чем больше вожусь с этой системой, тем больше хочется задействовать DMA. Но как в этом случае организовать вывод байтов по тетрадам?

1.Выбрать другой МК со свободным Quad-SPI либо SDIO либо каким другим интерфейсом, на котором можно такое сделать.
2.Сгородить внешнюю схему мультиплексора.
3.Выбрать МК с бОльшим кол-вом ОЗУ и писать тетрадные буфера.
ШСА
Спасибо. Но ведь и здесь пока есть варианты, например такой - На вывод отправлять не не всю видеостраницу, состоящую из тетрад, а только одну строку, уже в виде целых байтов. Главное, успевать за 10 мкс. их обновлять.
Golikov A.
Мы же не знаем куда у вас там подключены ножки, и доступен ли этот адрес из ДМА. Также мы не знаем сколько бит вам надо в паралель выплевывать наружу.

Там даже есть вариант по ДМА грузить интервалы таймера, а тот чтобы ногой дергал, в режиме ШИМ... Более подробно скажите что там куда выпихивается...
ШСА
Цитата(Golikov A. @ Aug 3 2015, 08:50) *
Мы же не знаем куда у вас там подключены ножки, и доступен ли этот адрес из ДМА. Также мы не знаем сколько бит вам надо в паралель выплевывать наружу.


Впараллель надо выплёвывать 4 бита - это видеосигнал (там ещё множество управляющих сигналов, но они однобитовые). А с доступностью то какие проблемы? DMA работает с устройствами и памятью. А у АРМ-ов все порты отображены на адресное пространство. Так что плеваться надо "память - память".
Golikov A.
если 4 биты порта в памяти рядом (в пределах байта) и остальные биты порта неважны. А иначе надо лезть через спец регистры установки снятия бит, и тут встает вопрос есть ли к ним доступ ДМА, скорее всего есть, но надо проверить.

Ну и самое простое это по 4 бита, дополнить до байта 1 и 2 поле, и их выплевывать по очереди. Причем ДМА можно настроить циклически, и тогда он будет просто по кругу гнать картинку, даже не трогая проц, до тех пор пока картинку не поменяете, его даже перезапускать не надо будет.
ШСА
Ну да, а как иначе? В STM32F4 нет никаких видеосредств, все АЦП и ЦАП довольно медленные.

Цитата(Golikov A. @ Aug 3 2015, 10:36) *
Причем ДМА можно настроить циклически, и тогда он будет просто по кругу гнать картинку, даже не трогая проц, до тех пор пока картинку не поменяете, его даже перезапускать не надо будет.


А вот это заманчиво, но хватит ли ОЗУ? Там 2 видеостраницы находятся плотно упакованные, каждая по 58К. Для ещё одной полной видеостраницы в байтовом формате (т.е. по байту на точку) тут нет места. А вот сделать 1-2 строки и обновлять за 10 мкс и переключать их каждые 64 мкс - это можно. Вот как это организовать я и думаю.
Golikov A.
Ну ДМА может гнать по кругу, и оно имеет прерывание половина прошла.
Делаете буфер размером 4 строки, запускаете ДМА, а по прерыванию Половину прошло, все прошло, подменяете данные в первой и второй половине буфере.
А ДМА будет их выпихивать со строгой времянкой.

Размер буфера можно сделать больше строк, чтобы было больше времени на обновление....

а почему там 4 бита? еще какая-то синхронизация что ли? или это 16 уровней сигнала?
ШСА
Цитата(Golikov A. @ Aug 3 2015, 10:55) *
Делаете буфер размером 4 строки, запускаете ДМА, а по прерыванию Половину прошло, все прошло, подменяете данные в первой и второй половине буфере.
А ДМА будет их выпихивать со строгой времянкой.

Размер буфера можно сделать больше строк, чтобы было больше времени на обновление....

а почему там 4 бита? еще какая-то синхронизация что ли? или это 16 уровней сигнала?


Ну, хорошо. Но строка не выводится непрерывно. Из 64 мкс часть времени идёт вывод, а потом заткнуться до прихода следующего синхроимпульса. Это время, я полагал, и можно использовать для подмены строки. А как сделать вывод нескольких строк, каждая из которых то выводится, то нет, что-то я слабо представляю.

4 бита - это цвета раскраски и надписей изображения + тень.
Golikov A.
ДМА запускается по таймеру, таймер запускается по внешнему синхроимпульсу.

Значит ДМА выводит 1 строку, по прерыванию дма отработало, перенастраиваете на следующую строку.
Вывод очередного значение контролирует таймер (интервалы между точками)
Запуск таймера по внешнему синхросигналу
и всех делов.

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

более того можно сделать цепочку таймеров, и несколько каналов ДМА взять, и они смогут даже по сложной схеме друг друга запускать
ШСА
Отлично. Спасибо.
GetSmart
Цитата(aaarrr @ Aug 1 2015, 22:50) *
Одиночная LDR выполняется два такта; последовательность из двух LDR может быть выполнена за три такта (а из трех за четыре и т.д.), если адрес для последующей инструкции не зависит от результата предыдущей.

Подскажите пожалуйста название документа, в котором описаны такие нюансы растактовки.
На сайте ARMа есть что-то вроде для Cortex-M0, в котором почему-то нет зависимостей. Может зависимости (индивидуально к кажому ядру) описываются в другом документе? Интересуют нюансы двух видов - изменение аргумента текущей инструкции в предыдущей инструкции и задержки связанные с обращением к памяти, в том числе чередования чтения/записи, а так же одновременной подгрузке кода, особенно для M0, у которого одна общая шина.
aaarrr
Цитата(GetSmart @ Sep 11 2015, 02:41) *
Подскажите пожалуйста название документа, в котором описаны такие нюансы растактовки.

Cortex-M3 Technical Reference Manual, раздел Load-store timings. У M0, полагаю, такой особенности (pipelined LDR) нет.
GetSmart
Цитата(aaarrr @ Sep 11 2015, 14:22) *
Cortex-M3 Technical Reference Manual, раздел Load-store timings. У M0, полагаю, такой особенности (pipelined LDR) нет.

Другие зависимости (как минимум из мной озвученных) у М3 и М0 Вам известны?

Методом тыка я нашёл кое-что, увеличивающее на такт следующую команду. Настолько неочевидное, что сперва хочется узнать все описанные зависимости М0/М3. На ранее обозначенной таблице таймингов и на этой для М3 она не указана.
aaarrr
Цитата(GetSmart @ Sep 11 2015, 17:26) *
Другие зависимости (как минимум из мной озвученных) у М3 и М0 Вам известны?

Нет, не известны.

Поделитесь наблюдениями, это интересно.
GetSmart
Время до сих пор не нашёл для полноценного тестирования на разных камнях. По результатам отпишусь. Заметил на М0. Думал зависимость от предыдущей инструкции, но оказалась зависимость другая. Для чистоты эксперимента остальные подробности потом.
ШСА
Цитата(GetSmart @ Sep 21 2015, 15:25) *
Время до сих пор не нашёл для полноценного тестирования на разных камнях...


А не проще ли просто описать ситуацию, в которой происходит непонятка? Тестировать, как и "ловить блох", можно бесконечно. Мне же, как и другим, я думаю, интересен практический опыт.
GetSmart
Цитата(ШСА @ Sep 23 2015, 23:32) *
Тестировать, как и "ловить блох", можно бесконечно.

На одном камне всё протестировано. Джиттера нет. Так что если Ваша программа работает, то нервничать не о чем. Программирование с точностью до такта интересует только "параноиков", которые не спешат.
GetSmart
Потестил на LPC4357 и LPC11U37/501. У обоих ядра M0 r0p0. Эффект наблюдается на обоих. У LPC11U37 есть три региона SRAM доступных для исполнения кода и хранения данных. У LPC4357 ещё больше регионов. Если команда STR/STM находится на нечётном адресе (маска 0x02) и адрес записи нах-ся в этом же регионе SRAM, то команда будет исполняться на такт дольше. Для STM добавочный только 1 такт независимо от кол-ва сохраняемых регистров. Отличие у LPC4357 есть в том, что хоть регион 0x20000000..0x2000ffff разбит ещё на 4 региона по 16 КБ и общение с разными этими регионами разных ядер не вызывает тормозов друг друга, но в описываемом выше эффекте весь этот регион для M0 как буд-то один и исполнение кода из допустим 0x200000000 с записью в регион 0x20008000 будет вызывать 1 такт тормозов.

У процессоров с одним регионом SRAM эффект должен наблюдаться всегда.
GetSmart
Цитата(GetSmart @ Oct 25 2015, 12:54) *
У процессоров с одним регионом SRAM эффект должен наблюдаться всегда.

Ессно при исполнении кода из SRAM. Именно так в LPC111x. Этим способом можно было бы косвенно проверять внутреннее разделение рамы на регионы в одноядерных процессорах. Если адресные линии не отключены в логике, как в LPC43xx, у которого, по моему предположению, из-за наличия цельного 40 КБ региона SRAM пришлось отключить линии A14 и A15 при сравнении в M0-ядре адресов кода и данных.

Серьёзный недостаток "эффекта" в том, что он зависит от того, на какой адрес попадает инструкция и даже лёгкие изменения в коде будут менять растактовку отлаженного кода, если регионы кода и данных общие.
GetSmart
Проверил ещё на LPC1227 (M0+ r0p0). Этого эффекта нет. Странно, что по CPUID ядра не отличить M0 от M0+.

Цитата
...из-за наличия цельного 40 КБ региона SRAM...

Вторая возможная причина в отсутствии пустот в регионе адресов 0x2000xxxx LPC43xx.
GetSmart
Цитата(GetSmart @ Oct 29 2015, 23:20) *
Проверил ещё на LPC1227 (M0+ r0p0). Этого эффекта нет. Странно, что по CPUID ядра не отличить M0 от M0+.

Ошибся. LPC1227 это M0 без плюса. Так что CPUID корректный. Но растактовка STR/STM у него отличается от остальных M0 камней NXP. Отличий растактовки LPC1227 от "официальной" ARM пока не нашёл.

Цитата(aaarrr)
Cortex-M3 Technical Reference Manual, раздел Load-store timings. У M0, полагаю, такой особенности (pipelined LDR) нет.

В юзер мануале LPC43xx указано, что pipelined есть и у LDR и у STR.
На бумаге распечатал на всякий случай.
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.