Наигравшись с PIC'ами, решил поковырять ARM в редакции STM. Столкнулся с непонятным моментом. Для работы с периферией контроллера необходимо то и дело снимать/ставить разные биты в ячейках памяти. В ассемблере PIC'ов есть замечательные команды BSFaddr, bit / BCFaddr, bit. Они берут бит bit по адресу addr и, соответственно, ставят его или снимают. Разумеется, с некоторыми оговорками, но сейчас это не важно. Смысл в том, что у ПИКов для этого - отдельная команда, одна, которая выполняется за один такт. У АВРов - по-другому, и я в нескольких местах (например, здесь) видел упоминание, что аналогичная операция требует не менее трёх инструкций и, соответственно, трёх тактов: прочитать слово из памяти в регистр, изменить его (поставить/снять бит логической операцией), записать обратно. Пример на сях:
Код:
*(unsigned long*)(0x40023830) |= 0x8;
Я решил глянуть, а как это будет на ассемблере? GCC выдал мне следующий результат обработки приведённой строчки:
Код:
ldr r2, .L3 /*.L3 - это адрес 32-разрядного слова в памяти*/ ldr r3, .L3 /*зачем это здесь - непонятно... адрес больше нигде в программе не используется.*/ ldr r3, [r3] /*загружаю слово из памяти в регистр*/ orr r3, r3, #8 /*меняю нужный бит*/ str r3, [r2] /*сохраняю в память*/
Тут целых пять строчек, и пять тактов! Порывшись по учебникам, я прикинул, как бы я написал такой код - и получил не менее ЧЕТЫРЁХ строк:
Код:
ldr r1, addr_of_work /*загружаю адресв регистр*/ ldr r2, [r1] /*загружаю слово из памяти в регистр*/ orr r2, r2, #8 /*меняю нужный бит*/ str r2, [r1] /*сохраняю в память*/
Я не знаю, как сделать этот код ещё меньше. Правильно ли я понимаю, что он будет выполняться 4 такта? А про три такта имеется в виду случай, когда адрес нужной ячейки уже в регистре? Или я чего-то не знаю?
Правильно ли я понимаю, что он будет выполняться 4 такта? А про три такта имеется в виду случай, когда адрес нужной ячейки уже в регистре? Или я чего-то не знаю?
В общем случае -- да. Здесь сразу две причины:
1) ARM умеет обрабатывать данные только и исключительно в регистрах процессора; соответственно, необходимо сначала загрузить означенные данные, потом выполнить операцию и в конце записать результат обратно, что даёт нам три команды.
2) ARM для обращения к памяти всегда использует адреса в регистрах, а соответственно, эти адреса надо предварительно загрузить -- вот и лишняя команда.
Если необходимо выполнить несколько обращений подряд к регистрам одного и того же устройства, базовый адрес можно загрузить только один раз, в самом начале:
Код:
LDR R3, =базовый адрес
LDR R0, [R3, #смещение регистра] LDR R1, [R3, #смещение другого регистра] и так далее
Z_h_e писал(а):
Почитайте про bit banding
Этот механизм не является универсальным и может отсутствовать в том или ином МК, так что полагаться на него нельзя -- но, если переносимость кода не требуется и он имеется, то, естественно, можно им воспользоваться.
Z_h_e писал(а):
Для портов ввода/вывода есть еще специальный регистр BSRR.
Я с STM32 практически не сталкивался, но про этот регистр помню. Но это опять-таки специфический случай -- хорош для ногодрыга, но и только. Если, например, необходимо сбрасывать-устанавливать отдельные разряды регистров USARTа или её какой периферии, там, надо полагать, придётся-таки считывать их в регистр проца, выполнять операцию и записывать на место.
В некоторых реализациях ARM, например в семействе Kinetis, имеется BME (Bit Manipulation Engine) модуль. Он позволяет производить 2-цикловые атомарные 8/16/32-битные операции непосредственно с регистрами периферии. В число операций входит AND, OR, XOR, и вставка битов. Для этого к адресу регистра следует добавить определённую константу в зависимости от операции. Например, для операции OR значения data с регистром по адресу addr код будет таким (здесь бит 27 отвечает за операцию OR):
Для оперативной работы с GPIO в этом семействе для каждого порта имеются специальные регистры для установки/сброса битов (как BSRR/BRR в STM32), а также для их инвертирования (toggle).
Обязательным условием долгой и стабильной работы Li-FePO4-аккумуляторов, в том числе и производства EVE Energy, является применение специализированных BMS-микросхем. Литий-железофосфатные АКБ отличаются такими характеристиками, как высокая многократность циклов заряда-разряда, безопасность, возможность быстрой зарядки, устойчивость к буферному режиму работы и приемлемая стоимость. Но для этих АКБ очень важен контроль процесса заряда и разряда для избегания воздействия внешнего зарядного напряжения после достижения 100% заряда. Инженеры КОМПЭЛ подготовили список таких решений от разных производителей.
Заголовок сообщения: Re: Как установить бит в памяти на ARM?
Добавлено: Ср авг 31, 2016 18:02:41
Собутыльник Кота
Карма: 29
Рейтинг сообщений: 645
Зарегистрирован: Сб май 14, 2011 21:16:04 Сообщений: 2694 Откуда: г. Чайковский
Рейтинг сообщения:0 Медали: 1
Кстати о bit banding. Это аппаратный |=, выяснилось при записи в регистр с битами типа togle. Наверняка это указано в каком-то документе, но я не видел.
_________________ Добро всегда побеждает зло. Поэтому кто победил - тот и добрый.
Компания EVE выпустила новый аккумулятор серии PLM, сочетающий в себе высокую безопасность, длительный срок службы, широкий температурный диапазон и высокую токоотдачу даже при отрицательной температуре.
Эти аккумуляторы поддерживают заряд при температуре от -40/-20°С (сниженным значением тока), безопасны (не воспламеняются и не взрываются) при механическом повреждении (протыкание и сдавливание), устойчивы к вибрации. Они могут применяться как для автотранспорта (трекеры, маячки, сигнализация), так и для промышленных устройств мониторинга, IoT-устройств.
Правильно ли я понимаю, что он будет выполняться 4 такта?
Нет, ldr/str в общем случае выполняется два такта. Иногда N последовательных ldr/str могут быть выполнены за N+1 такт. Кроме того, первый ldr может загружать адрес из константы во flash памяти, это может добавить еще несколько тактов так как flash медленная. Правда, он может быть заменен на mov32, который всегда выполняется ровно два такта. Ну и напоследок надо добавить, что при исполнении данного кода из flash, количество тактов еще увеличится (как я уже говорил - flash медленная).
Заголовок сообщения: Re: Как установить бит в памяти на ARM?
Добавлено: Чт сен 01, 2016 05:54:18
Собутыльник Кота
Карма: 29
Рейтинг сообщений: 645
Зарегистрирован: Сб май 14, 2011 21:16:04 Сообщений: 2694 Откуда: г. Чайковский
Рейтинг сообщения:0 Медали: 1
menzoda писал(а):
что при исполнении данного кода из flash, количество тактов еще увеличится (как я уже говорил - flash медленная)
Наоборот, код расположенный в ОЗУ выполняется медленнее. Если Ваш код расположен во флеш, то выборка инструкций из флеш будет производится через шину ICODE, а данных через DCODE. Если код разместить в RAM, то все ляжет на шину DCODE.
Лучше конечно проверить это, записав некий тестовый код и туда и туда, затем сравнить.
_________________ Добро всегда побеждает зло. Поэтому кто победил - тот и добрый.
Я открыл даташит на первый попавшийся STM32f407, так вот там ICode имеет доступ и к SRAM.
Цитата:
I-bus This bus connects the Instruction bus of the Cortex®-M4 with FPU core to the BusMatrix. This bus is used by the core to fetch instructions. The target of this bus is a memory containing code (internal Flash memory/SRAM or external memories through the FSMC/FMC).
Не знаю какой МК у топикстартера, но думаю что у всех STM32 на Cortex-M3 и Cortex-M4 именно такое устройство. Вот с Cortex-M0 уже может быть отличие, там же все обрезано. Но это все не важно, так как в любом случае медленность flash все перебьет. Ну пускай добавит эта коллизия шин по одному-два такта к некоторым инструкциям при исполнении из SRAM, зато исполнение из flash добавит к каждой инструкции от 3 тактов (типичное значение, на высокой частоте может быть и больше)! Акселераторы flash есть не у всех, а быстрая flash вообще у единиц.
Заголовок сообщения: Re: Как установить бит в памяти на ARM?
Добавлено: Чт сен 01, 2016 12:47:27
Собутыльник Кота
Карма: 29
Рейтинг сообщений: 645
Зарегистрирован: Сб май 14, 2011 21:16:04 Сообщений: 2694 Откуда: г. Чайковский
Рейтинг сообщения:0 Медали: 1
Смотрим RM008. Это на STM32F10x. Ядро Cortex-M3. Спойлер Читаем оттуда же.
Цитата:
ICode bus This bus connects the Instruction bus of the Cortex®-M3 core to the Flash memory instruction interface. Prefetching is performed on this bus.
Т.е. у таких МК шина Icode не имеет доступ к SRAM. Обращаем внимание, что чтение флеша происходит через буфер FLITF, который читает сразу 2х64 бит, т.е. четыре 32 битных слова. Это должно ускорять процесс чтения.
Цитата из книги Trevor Martin_The Insiders Guide to the STM32 ARM Based Microcontroller
Цитата:
Несмотря на то, что программный код может загружаться и исполняться изSRAM, команды в таком случае будут извлекаться с использованием системной шины, что приводит к дополнительным задержкам. И вероятнее всего код будет исполняться медленнее изSRAM, чем из встроеннойFlash памяти, расположенной в области для программного кода.
Это он про Cortex-M3.
Кроме того, мне где-то еще попадалась информация, что код из ОЗУ выполняется медленнее. Не помню где блин.
----------
Вы привели в пример STM32f407. Я с ним не работал. Это уже Cortex-M4. Гляжу RM009. Цитату Вашу дублировать не буду. Смотрим сразу картинку. Спойлер Действительно получается I-bus тут "достает" до ОЗУ. НО!!! Шина ICode и Dcode подключены ко флеш через некий акселератор. Если ничего не напутал, то вот цитата про него
Цитата:
To release the processor full performance, the accelerator implements an instruction prefetch queue and branch cache which increases program execution speed from the 128-bit Flash memory. Based on CoreMark benchmark, the performance achieved thanks to the ART accelerator is equivalent to 0 wait state program execution from Flash memory at a CPU frequency up to 180 MHz.
Т.е. ноль времени простоя при чтении флеша. Куда еще быстрее?
---------- На данный момент моих знаний, делаю вывод. Выполнение кода в ОЗУ не будет быстрее, но может быть медленее. Конечно это нельзя говорить за все контроллеры. ----------
Сегодня может попробую сделать тестовый код и поробовать его на STM32F103 (другого у меня нет). Если сделаю, то результат выложу само собой.
Если есть желание, то можете и Вы попробовать на своем МК.
_________________ Добро всегда побеждает зло. Поэтому кто победил - тот и добрый.
Так я и не против, что в частных случаях из flash может быть даже быстрее. Я говорю про большинство случаев, а в большинстве случаев, как я уже говорил, в МК нет акселератора. Например, у ST он есть только в некоторых продвинутых линейках. А без акселератора, как я тоже уже говорил, flash настолько медленная, что сведет на нет всю ту небольшую выгоду, полученную от использования раздельных шин. Это я уже гарантирую, потому что не так давно специально искал ARM МК с быстрой flash или акселератором. Так вот, их можно сосчитать по пальцам одной руки! Это несколько STM32 (есть акселератор) и вроде что-то было у Infineon (быстрая flash). У остальных, на номинальной частоте, по 3-5 циклов ожидания, Карл!
Кстати пресловутый акселератор тоже не панацея, он как и любой кэш может ошибаться. Если код выполняет частое ветвление, то этот акселератор быстренько сдуется. А вот SRAM гарантированно будет обеспечивать 0 циклов ожидания в любом случае. Пусть даже при этом LDR и STR будут немного медленнее, зато весь остальной код будет гораздо быстрее.
Конечно лучше провести тест, чтобы убедиться. Можно попробовать следующие тесты: 1. линейный код из flash с выключенным акселератором 2. линейный код из flash с включенным акселератором 3. код с частым ветвлением (дальше чем 4 слова) из флеш с включенным акселератором (чтобы убедиться, что он сдуется) 4. линейный код из SRAM 5. код с частым ветвлением из SRAM.
Частота значительно ниже. При том, что положительный импульс где-то похож по длительности на предыдущий тест, а вот отрицательный чуть не в два раза длиннее. Я думаю это легко объяснить работой буфера FLITF. Когда код линеен он успевает кэшировать данные. А вот предсказать ветвления он не может совсем, даже безусловные.
Ну вот, как то вот так.
---------- Если бы кто сделал что-то подобное для контроллера с акселератором и выложил, думаю была бы полезная инфа.
---------- З.Ы. Есть у меня STM8. Еще не разу не игрался с ним и почти ничего не читал. Но русской статейке видел, что если там выполнять код из ОЗУ, то точно будет медленнее ибо шина значительно уже по разрядности для ОЗУ. Если руки дойдут до изучения этого МК, постараюсь сделать и для него аналогичный тест.
_________________ Добро всегда побеждает зло. Поэтому кто победил - тот и добрый.
Заголовок сообщения: Re: Как установить бит в памяти на ARM?
Добавлено: Пт сен 02, 2016 18:22:40
Собутыльник Кота
Карма: 29
Рейтинг сообщений: 645
Зарегистрирован: Сб май 14, 2011 21:16:04 Сообщений: 2694 Откуда: г. Чайковский
Рейтинг сообщения:0 Медали: 1
Сегодня провел еще один тест. На выполнение одного и того же кода во Флеш и в ОЗУ. Была мысль создать отдельную тему, так как данные тесты по сути офтоп.
Из предыдущего теста, можно было предположить, что линейный код выполняется практически с одинаковой скоростью и во флеш и в ОЗУ. Тормозит все у данного МК переходы.
int main(void) { RCC->APB2ENR |= RCC_APB2ENR_IOPAEN; GPIOA->CRL=GPIO_CRL_MODE0|GPIO_CRL_MODE1;
while(1) { Mac4; GPIOA->ODR^=1;//Инвертируем выход A0 } }
Такой исходник компильнулся почти в 14КБ кода и практически весь линейный.
Скрины не буду прикладывать. Частота при выполнении кода из ОЗУ - 4,655 кГц. Частота при выполнении кода из Флеш - 3,394 кГц. Так что буфер FLITF на 128 бит и тут не помогает для данного МК.
----------
Думаю, если продолжать подобные тесты, для разных МК, нужно создать отдельный топик со ссылкой на этот. Наверное данный МК тестировать уже нет необходимости, вроде все понятно.
_________________ Добро всегда побеждает зло. Поэтому кто победил - тот и добрый.
С другими еще хуже будет. Не у всех есть этот буфер, который может хоть как-то помогает. Могу сказать, что на TMS320F2810 (это не ARM) на номинальной частоте 150 МГц код из SRAM выполняется примерно в два-три раза быстрее чем из flash.
Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 31
Вы не можете начинать темы Вы не можете отвечать на сообщения Вы не можете редактировать свои сообщения Вы не можете удалять свои сообщения Вы не можете добавлять вложения