Во многих приложениях ЦП, выполнение команд которого имеет известную временную зависимость с ожидаемыми входными стимулами, может обрабатывать задачи, для которых потребуется гораздо более быстрый ЦП, если бы эта связь была неизвестна. Например, в проекте, в котором я использовал PSOC для генерации видео, я использовал код для вывода одного байта видеоданных каждые 16 тактовых частот процессора. Поскольку проверка того, готово ли устройство SPI, и разветвление, если нет, IIRC потребует 13 часов, а загрузка и сохранение для вывода данных - 11, невозможно было проверить устройство на готовность между байтами; вместо этого я просто устроил так, чтобы процессор выполнял ровно 16 циклов кода для каждого байта после первого (я думаю, что я использовал реальную индексированную нагрузку, фиктивную индексированную загрузку и хранилище). Первая запись SPI каждой строки произошла до начала видео, и для каждой последующей записи было окно с 16 циклами, в котором запись могла происходить без переполнения или переполнения буфера. Ветвящийся цикл генерировал окно с 13 циклами неопределенности, но предсказуемое выполнение с 16 циклами означало, что неопределенность для всех последующих байтов будет соответствовать тому же окну с 13 циклами (которое в свою очередь вписывается в окно с 16 циклами, когда запись могла быть приемлемой происходит).
Для более старых процессоров информация о сроках выполнения команд была четкой, доступной и однозначной. Для более новых ARM информация о времени кажется гораздо более расплывчатой. Я понимаю, что когда код выполняется из флэш-памяти, поведение при кэшировании может усложнить прогнозирование, поэтому я ожидаю, что любой код с циклическим счетом должен выполняться из ОЗУ. Однако даже при выполнении кода из ОЗУ спецификации кажутся немного расплывчатыми. Является ли использование кода с циклическим счетом все еще хорошей идеей? Если да, то каковы лучшие методы, чтобы заставить его работать надежно? В какой степени можно смело предположить, что производитель чипа не собирается молча вставлять «новый улучшенный» чип, который в определенных случаях сокращает цикл выполнения определенных инструкций?
Предполагая, что следующий цикл начинается на границе слова, как определить, исходя из спецификаций, сколько именно времени потребуется (предположим, Cortex-M3 с памятью с нулевым состоянием ожидания; в этом примере больше ничего не должно иметь значения для системы).
myloop: mov r0, r0; Короткие простые инструкции, позволяющие получать дополнительные инструкции mov r0, r0; Короткие простые инструкции, позволяющие получать дополнительные инструкции mov r0, r0; Короткие простые инструкции, позволяющие получать дополнительные инструкции mov r0, r0; Короткие простые инструкции, позволяющие получать дополнительные инструкции mov r0, r0; Короткие простые инструкции, позволяющие получать дополнительные инструкции mov r0, r0; Короткие простые инструкции, позволяющие получать дополнительные инструкции добавляет r2, r1, # 0x12000000; Инструкция из двух слов ; Повторите следующее, возможно, с другими операндами ; Будет продолжать добавлять значения, пока не произойдет перенос ITCC addcc r2, r2, # 0x12000000; Инструкция из двух слов, плюс дополнительное слово для itcc ITCC addcc r2, r2, # 0x12000000; Инструкция из двух слов, плюс дополнительное слово для itcc ITCC addcc r2, r2, # 0x12000000; Инструкция из двух слов, плюс дополнительное слово для itcc ITCC addcc r2, r2, # 0x12000000; Инструкция из двух слов, плюс дополнительное слово для itcc ; ... и т.д., с более условными инструкциями из двух слов sub r8, r8, # 1 bpl myloop
Во время выполнения первых шести инструкций ядро успевает извлечь шесть слов, из которых будет выполнено три, так что может быть до трех предварительно выбранных. Следующие инструкции состоят из трех слов, поэтому ядро не сможет извлечь инструкции так быстро, как они выполняются. Я ожидал бы, что некоторые из "it" -процессов будут занимать цикл, но я не знаю, как предсказать, какие из них.
Было бы хорошо, если бы ARM мог указать определенные условия, при которых синхронизация команд «it» была бы детерминированной (например, если нет состояний ожидания или конфликта кодовой шины, а предыдущие две инструкции являются 16-битными командами регистра и т. Д.) но я не видел такой спецификации.
Образец заявки
Предположим, что кто-то пытается спроектировать дочернюю плату для Atari 2600, чтобы генерировать компонентный видеовыход с разрешением 480P. 2600 имеет тактовую частоту 3,597 МГц и тактовую частоту процессора 1,19 МГц (точка часов / 3). Для компонентного видео 480P каждая строка должна выводиться дважды, что подразумевает точечный выход 7.158 МГц. Поскольку видеочип Atari (TIA) выводит один из 128 цветов, используя в качестве 3-битного сигнала яркости плюс фазовый сигнал с разрешением примерно 18 нс, было бы трудно точно определить цвет, просто взглянув на выходы. Лучшим подходом было бы перехватывать записи в регистры цвета, наблюдать записанные значения и подавать в каждый регистр значения яркости TIA, соответствующие номеру регистра.
Все это может быть сделано с помощью FPGA, но некоторые довольно быстрые устройства ARM могут быть намного дешевле, чем FPGA с достаточным объемом оперативной памяти для обработки необходимой буферизации (да, я знаю, что для томов такая вещь может быть произведена, цена не реальный фактор). Однако требование ARM следить за входящим тактовым сигналом значительно увеличит требуемую скорость процессора. Предсказуемое количество циклов может сделать вещи чище.
Относительно простой подход к проектированию заключается в том, чтобы CPLD следил за процессором и TIA и генерировал 13-битный сигнал синхронизации RGB +, а затем имел бы ARM DMA, получая 16-битные значения из одного порта и записывая их в другой с надлежащей синхронизацией. Однако было бы интересно узнать, может ли дешевый ARM сделать все. DMA может быть полезным аспектом подхода «все в одном», если его влияние на количество циклов ЦП можно предсказать (особенно если циклы DMA могут происходить в циклах, когда шина памяти в противном случае не используется), но в какой-то момент процесса ARM должен будет выполнять свои функции поиска по таблице и наблюдения за шиной. Обратите внимание, что в отличие от многих видео архитектур, в которых регистры цвета записываются во время интервалов гашения, Atari 2600 часто записывает в регистры цвета во время отображаемой части кадра,
Возможно, наилучшим подходом было бы использовать пару дискретных логических чипов для идентификации записи цвета и принудительно установить младшие биты регистров цвета в надлежащие значения, а затем использовать два канала DMA для выборки входной шины ЦП и выходных данных TIA, и третий канал DMA для генерации выходных данных. В этом случае центральный процессор сможет свободно обрабатывать все данные из обоих источников для каждой строки сканирования, выполнять необходимый перевод и буферизовать его для вывода. Единственным аспектом обязанностей адаптера, который должен был бы выполняться в «реальном времени», было бы переопределение данных, записанных в COLUxx, и об этом можно было бы позаботиться, используя два распространенных логических чипа.
источник
Информация о времени доступна, но, как вы указали, иногда может быть расплывчатой. В Разделе 18.2 и Таблице 18.1 Технического справочного руководства для Cortex-M3 содержится много временной информации , например ( pdf здесь ), и выдержка здесь:
которые дают список условий для максимального времени. Время для многих инструкций зависит от внешних факторов, некоторые из которых оставляют неясности. Я выдвинул на первый план каждую неясность, которую я нашел в следующем отрывке из этого раздела:
Для всех случаев использования он будет более сложным, чем «Эта инструкция - один цикл, эта инструкция - два цикла, это один цикл ...», подсчет возможен в более простых, медленных и старых процессорах. В некоторых случаях вы не столкнетесь с неясностями. Если вы столкнулись с неясностями, я предлагаю:
Эти требования, вероятно, дают ответ на ваш вопрос: «Нет, это не очень хорошая идея, если возникшие трудности не стоят затрат», - но вы уже это знали.
источник
Одним из способов обойти эту проблему является использование устройств с детерминированными или предсказуемыми временными интервалами, таких как чипы Parallax Propeller и XMOS:
http://www.parallaxsemiconductor.com/multicoreconcept
http://www.xmos.com/
Подсчет циклов очень хорошо работает с Propeller (необходимо использовать язык ассемблера), в то время как устройства XMOS имеют очень мощную программную утилиту, XMOS Timing Analyzer, которая работает с приложениями, написанными на языке программирования XC:
https://www.xmos.com/download/public/XMOS-Timing-Analyzer-Whitepaper%281%29.pdf
источник
Подсчет циклов становится более проблематичным, когда вы переходите от низкоуровневых микроконтроллеров к более универсальным вычислительным процессорам. Первые обычно имеют четко определенные сроки инструкций, отчасти по причинам, которые вы посещаете. Это также потому, что их архитектура довольно проста, поэтому время инструкций фиксировано и понятно.
Хорошим примером этого являются большинство микрочип PIC. Серии 10, 12, 16 и 18 имеют очень хорошо документированные и предсказуемые сроки выполнения команд. Это может быть полезной функцией для небольших приложений управления, для которых предназначены эти чипы.
Поскольку вы избавляетесь от сверхнизких затрат, и поэтому дизайнер может потратить немного больше места на чипах, чтобы получить более высокую скорость от более экзотической архитектуры, вы также избавитесь от предсказуемости. Взгляните на современные варианты x86 как крайние примеры этого. Существует несколько уровней кэшей, витализация памяти, выборочная проверка, конвейерная обработка и многое другое, что делает подсчет циклов команд практически невозможным. В этом приложении это не имеет значения, так как клиент заинтересован в высокой скорости, а не в предсказуемости синхронизации команд.
Вы даже можете увидеть этот эффект на более высоких моделях микрочипов. 24-битное ядро (серии 24, 30 и 33) имеет в значительной степени предсказуемую синхронизацию команд, за исключением нескольких исключений, когда существуют конфликты шины регистра. Например, в некоторых случаях машина вставляет остановку, когда следующая инструкция использует регистр с некоторыми режимами косвенной адресации, значение которого было изменено в предыдущей инструкции. Этот тип сбоев необычен для dsPIC, и большую часть времени вы можете его игнорировать, но он показывает, как эти вещи закрадываются из-за дизайнеров, пытающихся предоставить вам более быстрый и более мощный процессор.
Таким образом, основной ответ - это часть компромисса, когда вы выбрали процессор. Для небольших приложений управления вы можете выбрать что-то маленькое, дешевое, с низким энергопотреблением и с предсказуемым временем выполнения команды. По мере того, как вам требуется больше вычислительной мощности, архитектура меняется, так что вам приходится отказываться от предсказуемой синхронизации команд. К счастью, это не проблема, так как вы переходите к приложениям, требующим больших вычислительных ресурсов и общего назначения, поэтому я думаю, что компромиссы работают достаточно хорошо.
источник
Да, вы все еще можете сделать это, даже на ARM. Самая большая проблема с этим в ARM состоит в том, что ARM продает ядра, а не чипы, и тактирование ядра известно, но то, что оборачивает поставщик чипов, варьируется от поставщика к поставщику, а иногда от семейства чипов к другому в пределах поставщика. Таким образом, конкретный чип от конкретного поставщика может быть весьма детерминированным (например, если вы не используете кэши), но портировать его становится сложнее. При работе с 5 часами здесь и 11 часами там использование таймеров является проблематичным, так как количество инструкций, необходимых для выборки таймера и определения, истекло ли время ожидания. Судя по звукам вашего прошлого опыта программирования, я готов поспорить, что вы, вероятно, отлаживаете осциллограф так же, как и я, поэтому вы можете попробовать плотную петлю на чипе с тактовой частотой, посмотреть на spi или i2c или любую форму сигнала, добавить или удалить nops, изменить количество раз через цикл и в основном настроить. Как и с любой платформой, отсутствие использования прерываний значительно помогает детерминированной природе выполнения команд.
Нет, это не так просто, как PIC, но все же вполне выполнимо, особенно если задержка / время приближаются к тактовой частоте процессора. Ряд поставщиков на основе ARM позволяют вам умножить тактовую частоту и получить, скажем, 60 МГц от эталона 8 МГц, поэтому, если вам нужен интерфейс с частотой 2 МГц вместо выполнения каких-либо действий через каждые 4 инструкции, вы можете повысить тактовую частоту (если у вас есть энергопотребление), а затем используйте таймер и дайте себе много часов, чтобы заниматься другими делами.
источник