Запись области ОЗУ одной командой
- Войдите на сайт для отправки комментариев
Ср, 17/05/2017 - 01:35
С ассемблером Atmel не знаком, но где-то читал что можно одной стандартной командой 8-разрядного контроллера копировать область данных из ОЗУ в ОЗУ в несколько десятков байт. Как это можно сделать ?
Массивы большие и цель уменьшение времени исполнения программы.
Только побайтно
Где бы посмотреть результат компиляции С++ в ассемблер для этой программы, неужели компилятор будет побайтно копировать из области ff в область ee и не знает способа лучше ?
Да. Аналога цепочечных команд Intel-a у AVR нет. Единственное упрощение для программиста, есть команда пересылки с отоматическим инкрементом(декрементом) адреса. И сё.
за то все команды за один такт?
неть, каждая пересылка - такт.
P.S. Ошибся, 2 такта.
Нет. Каждое чтение/запись SRAM занимают ДВА такта, если SRAM внутренняя и НЕ МЕНЕЕ 3-х тактов, если внешнее расширение SRAM (можно настроить до 5-6 уж не помню). Команда чтения/записи с автоинкрементом/декрементом кажется тоже требует 1 доп. такт на операцию инкремента/декремента, но это уже надо уточнять в мануале, лень лазить сейчас.
Так что, операция: считать байт по одному указателю--/++ , записать байт по другому--/++ занимает как миниум 4 такта. Плюсом проверка на длину блока и переход цикла .. итого "от 6 тактов" на каждый байт пачки. Другое дело, что наибольший объем памяти у дунек это .. 8 КИЛО байт "на все про все" .. какие там "большие объемы"?!?
Normas
Это дизассемблирование, но последние пару версий ide собирает elf с символами, так что в некотором роде будут.
где last_measure_time была определена, как UL, что мы и видим - результат millis [r22:r25] запихивается в 4 байта UL.
Ключей у avr-tools много, мне просто лень искать нужный вам режим, может он и существует, но это уж сами.
Получил нелинейную зависимость времени копирования от размера массива. Причина не понятна, ничем кроме работы сторонних прерываний объяснить это не могу :-(((
размер=32 байт, t=16 мкС
размер=64 байт, t=28 мкС
размер=128 байт, t=60 мкС
размер=256 байт, t=144 мкС
размер=512 байт, t=280 мкС
Где бы посмотреть результат компиляции С++ в ассемблер для этой программы
Я уже задавался этим вопросом, здесь подробно всё описано - Настройка компиляции в Arduino IDE
Ну собственно об чем вам и написал: ld,st испльзуют по 2 такта, в т.ч. и с ++/--, декремент = 1 такт и переход = 2 такта. Итого имеем 7 тактов на каждый байт пересылки. Остальная неравномерность - обработка прерываний от таймера: millis(), micros() и т.д. Чуть около или больше 2 мегабайт в секунду .. где это "много времени" для 8килов в наибольшем варианте?
Люди, читайте класику, все ж изложено в первоисточнике предельно просто. Клоки крайние справа.
И при желании экспериментально проверяется. Только правильно надо мерить, с учетом времени потраченого на измерение времени ;) Де там наша тема про время выполнения операций на разных контролерах завалялась?
Контроллер должен выполнять еще и текущие операции и все вместе занимает "много" по времени.
Кстати, сколько команд занимает вход-выход в функцию (пролог и эпилог), если не передавать параметры в стеке то есть void Myfunction(void) ?
Буду пытаться экономить время при помощи inline http://arduino.ru/forum/programmirovanie/inline-eto-prinuditelnyi-modifi...
5 тактов - вызов, 5 тактов возврат из функции. На каждый байт параметра надо добавить по 3 команды: считать параметр в регистр (2 такта), положить параметр на стек (2 такта), и внутри достать параметр со стека (2 такта). Это после первых 2-4 параметров, в зависимости от их разрядности. Смотрите описание соглашения о регистрах для avr-gcc, там все детально прописано. Соответственно, long параметр, передаваемый через стек это 4х6 = 24 такта "плюсом". Подпрограммы с 1-3 параметрами как правило хорошо оптимизируются и там происходит передача в регистрах.
Если подпрограмма имеет локальные переменные (особенно long, float), то там тоже сильно зависит от оптимизации, но можно легко словить локалы на стеке и избыточное сохранение регистров там же "до" и "после" работы подпрограммы даже для байтовых переменных. Как правило, относительно хорошо компилируются только простые подпрограммы с 0-6 байтами в локалах, независимо от размерности переменных.
Тут ЕвгенийП с год назад исследовал поверхностно этот вопрос .. вызовы простых подпрограмм снижают ногодрыг с 5Мгц примерно до 1, помнится..
Сказки про "однотактовые Risc" .. на практике всего лишь сказки.. увы.
Ну и ещё: вместо копирования массивов "туда-сюда-обратно", попробуйте освоить указательную арифметику. Не гарантирую, но возможно это то, что требуется.