Обсуждаем контроллеры компании Atmel.
Ответить

Re: Ассемблер (ASM) для AVR в вопросах и ответах

Пн мар 09, 2020 08:12:10

А через push/pop?
...
Это просто как предположение достаточно редкоиспользуемого варианта решения.
:roll:

Спасибо. Идею понял. Подумаю.

PS Немного математики. Что бы просто залить дисплей 240х320 фоном, нужно отправить 76800 16-битных пакетов данных. Это в восьмибитных будет 153600. И если добавить сюда ещё и переходы на подпрограмму SPI_WAIT, то дисплей будет заливаться медленно и печально. Так что приходится жертвовать памятью во ради скорости. Для того и "SPI_WAIT" и оформил макросом, для наглядности и сокращения кода.

Re: Ассемблер (ASM) для AVR в вопросах и ответах

Пн мар 09, 2020 08:59:01

Вовсе не обязательно. Никто не заставляет дожидаться передачи каждого байта по SPI wait-ом. Пока он передаётся (16 тактов CPU, как минимум), вполне можно успеть подготовить следующий.

У меня в проекте велокомпьютера на C я практически максимальные 6.5 FPS выжал на 16MHz тактовой.

Основная суть трюка - ожидать готовности не после того, как байт положен в регистр SPI, а перед этим.

Re: Ассемблер (ASM) для AVR в вопросах и ответах

Пн мар 09, 2020 09:23:32

Основная суть трюка - ожидать готовности не после того, как байт положен в регистр SPI, а перед этим.

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

PS
Например при выводе текста, цвет переднего плана заранее помещён в регистры R12, R13.
Код:
      out SPDR,color_front_H
      SPI_WAIT
      out SPDR,color_front_L
      SPI_WAIT

Там и ждать то больше негде, кроме как на spiwait-е
Последний раз редактировалось shonty Пн мар 09, 2020 09:46:51, всего редактировалось 2 раз(а).

Re: Ассемблер (ASM) для AVR в вопросах и ответах

Пн мар 09, 2020 09:23:59

Я имею в виду конструкцию, вроде (0<<CS02 | 1<<CS01 | 1<<CS00)

Да ну. Неужели не схавает конструкцию вида (6<<CS00)?

Re: Ассемблер (ASM) для AVR в вопросах и ответах

Пн мар 09, 2020 10:41:06

shonty писал(а):Не понял разницы, ждать до или после
Разница существенная.

Если ждать после - то фактически всё то время, пока SPI аппаратно что-то передаёт, основной цикл программы тупо висит в ожидании. И только потом начинает готовить (доставать из массива или ещё что-то) следующий байт для отправки.

Гораздо более правильно положить байт в регистр SPI и сразу же перейти к подготовке (доставанию из массива) следующего байта. И только когда он извлечён и готов к отправки - только тогда повисеть в ожидании, отправился ли предыдущий байт. И как только отвисло - тут же положить готовые данные.

Во втором случае ожидание будет гораздо меньше (если будет вообще).

P.S. Да, когда вся передача закончена и нужно дёрнуть CS или D/C, нужно в самом конце тоже ещё подождать один раз, чтобы передача до конца завершилась.

Re: Ассемблер (ASM) для AVR в вопросах и ответах

Пн мар 09, 2020 11:18:27

Если ждать после - то фактически всё то время, пока SPI аппаратно что-то передаёт, основной цикл программы тупо висит в ожидании. И только потом начинает готовить (доставать из массива или ещё что-то) следующий байт для отправки.

Да, возможно при многоцветовом выводе так будет рациональнее.
Подумаю...
У меня текст переменной ширины символов, И поиск параметров символа идёт через таблицу индекса.
И если однотонная заливка просто бешеная, то при выводе текста (переписать одну строку не ощутимо, а вот когда весь экран переписать текстом...) вывод притормаживает немного.
Подумаю как можно использовать этот метод.

Re: Ассемблер (ASM) для AVR в вопросах и ответах

Пн мар 09, 2020 11:31:46

Я не знаю, как у Вас вывод шрифтов сделан, но у меня подход такой:

Шрифт, по сути - картинка некоторого размера W*H. ILI9341 (да и все подобные) поддерживает вывод в режиме окна. То есть, задаются координаты (x, y, w, h) этого окна, а дальше можно посылать байты сплошным потоком. В зависимости от настроек, это окно будет заполняться в определённом порядке. У меня выбран такой: сверху вниз первый столбец, затем переход к столбцу правее, и так далее.

То есть, если заранее подготовить шрифт в подходящем формате, то отрисовка становится очень быстрой. Накладные расходы - это по сути только установка окна и установка указателей на нужную "картинку". Дальше - сплошной поток данных, без пауз (из-за wait в нужном месте).

Текст/картинка, получается, рисуется практически с той же скоростью, что и просто заливка экрана.

Re: Ассемблер (ASM) для AVR в вопросах и ответах

Пн мар 09, 2020 11:50:18

WiseLord писал(а):Я не знаю, как у Вас вывод шрифтов сделан, но у меня подход такой:

Шрифт, по сути - картинка некоторого размера W*H. ILI9341 (да и все подобные) поддерживает вывод в режиме окна. То есть, задаются координаты (x, y, w, h) этого окна, а дальше можно посылать байты сплошным потоком. В зависимости от настроек, это окно будет заполняться в определённом порядке. У меня выбран такой: сверху вниз первый столбец, затем переход к столбцу правее, и так далее.

Да и у меня так же. Один в один.

Но первая заливка фоном (возможно) немного отличается. Фон (черный) 0000h. Это 2x 00h.
По этому просто заливку поля можно реализовать проливая один байт 00h в цикле, но в 2 раза больше.

И RGB565 вообще можно сделать однобайтовым. Например 4E4Eh, 0202h, и т.д. По таблице нужно подбирать. И лить по 2 раза.
Цветов конечно поубавится, но судя по тому как эти дисплеи воспроизводят цвета, то не существенно.

PS Эксперименты по удалению и перемещению SPI_wait-ов дали очень интересные и неожиданные результаты, но не положительные. Всё таки возможно есть разница программ на C или Asm. Возможно C вставляет лишние циклы, может ещё что...

PS2 Что бы не голословить, видео вывода. Шрифт 24х40. Вторую сторку специально через паузу сделал.

Re: Ассемблер (ASM) для AVR в вопросах и ответах

Пн мар 09, 2020 18:19:17

По порядку....
Сначала покажите мне в ассемблере такую сущность как переменная. ИХ ТАМ НЕТ. То что мы называем переменными - это абстракция более высокого уровня чем ассемблер. Ассемблер и процессор не работает с переменными - он работает с РЕГИСТРАМИ и такой большой абстракцией как память. ДА! то что вы называете памятью это не обязательно ячейки с долговременным хранением данных, просто чаще всего память используется для хранения данных, но вот сюрприз - это не всегда так. И это становится большой неожиданностью для некоторых программистов, особенно в таких специфических штуках как микроконтроллеры и встраиваемые системы. Поэтому для процессора память не более чем устройство с которого можно читать и записывать данные адресно. Таким же образом ассемблер не может в принципе дать вам то что не может процессор, но перед ассемблером есть ещё надстройки всевозможные, которые реализуют тот или иной "человеческий" функционал и некоторое подобие так называемых переменных. Но тут возникает диллема. С одной стороны для человека "переменная" звучит однозначно и понятно, но для процессора.... начинается АД. Ведь процессор может адресовать совершенно различные виды памяти - РЕГИСТРЫ, ВНУТРЕННЕЕ адресное пространство, ВНЕШНЕЕ адресное пространство, всевозможные параллельные и последовательные чипы памяти как с программным доступом так и аппаратным - I2C, SPI, параллельный доступ... Вы хотите чтобы ассемблер прозрачно поддерживал всё это разнообразие прямо из коробки? Так этого не будет. Такая поддержка потянет за собой накладные расходы. И получим в итоге... язык С. Вот что значит изобретать велосипед.

Основной смысл – не изобретать велосипед, а использовать готовую функцию.
Думаю, встроенную функцию вызвать проще, соответственно, удобней.

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

Это какую такую траву надо курить, чтобы придумать метод набора двоичного числа в группу смежных бит одного регистра путем сдвигов нулей или единиц на обозначенное символически число бит? Я имею в виду конструкцию, вроде 0<<CS02 | 1<<CS01 | 1<<CS00 для прескалера таймера 0 вместо простого и понятного (допустим) T0prs64, которое в подключаемом по .Include файле было бы определено, как 0x03.

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

В СИ приходится делать вставки из ассемблера - это вроде как костыли. А костыли свидетельствуют об инвалидности программы, здоровому костыли не нужны.

Это не костыли а необходимость. Причем, обратите внимание сколько при этом нужно предоставить сведений о вашей вставке компилятору чтобы он не поломал ваш код. И сколько требований предъявляется к вставке чтобы она не поломала СИ-шный код. Всё это плата за высокоуровневость.
Но в принципе, хорошо зная язык можно строить такие конструкции на ЯВУ которые разворачиваются компилятором и оптимизатором в быстрый код. Но да, при этом надо много знать особенностей и всяких заморочек.

Re: Ассемблер (ASM) для AVR в вопросах и ответах

Пн мар 09, 2020 18:44:55

По порядку....
Сначала покажите мне в ассемблере такую сущность как переменная. ИХ ТАМ НЕТ. То что мы называем переменными - это абстракция более высокого уровня чем ассемблер.

Вы, милостивый государь, путаете транслятор с железом.
Ассемблер, как и любой язык, имеет сущности сходные с языками более высокого уровня. В том числе и переменные. Причем, В ЗАВИСИМОСТИ ОТ АРХИТЕКТУРЫ контроллера, эти переменные могут размещаться не только в резидентном ОЗУ, но и во внешней памяти. Главное тут, чтобы было единое адресное пространство данных.
Приличный ассемблер всегда имеет контроль за размещением данных в памяти. Так, если для одной переменной выделено 2 байта, а для другой 4, то линкер не позволит одной наехать на другую, а при явном указании на адрес выдаст ошибку размещения.
Таким образом, если в начале кода я выделил для некоей целостной сущности кода некое пространство в памяти данных, а так же объявил символьное имя этой сущности, то эта сущность с точностью до неразличимости стала переменной. Эта переменная отображается в среде разработки именно как переменная заявленной разрядности, а при совместной компиляции АСМ кода (не вставки, а именно кода), имя объявленное в Си кочует без изменений формата в АСМ и наоборот.
Единственное отличие - отсутствие некоторых ограничений на использование этих переменных в АСМе, что может привести к ошибкам. Но если человек имеет опыт работы с ассемблером, эти ошибки крайне редки. Все зависит от МЕТОДОВ написания кода. Ошибки такого рода можно и в Си долго искать, если не владеешь им в дОлжной мере. Взять хотя бы приведение типов... :tea:

Re: Ассемблер (ASM) для AVR в вопросах и ответах

Пн мар 09, 2020 19:00:39

не соглашусь с вами, КРАМ. ассемблер все-таки оперирует "метками", сопоставляя им некие константы, а не переменными. и что именно эта константа будет обозначать, транслятору ассемблера неведомо: вы можете запросто обявить метку М1 в сегменте кода (для JMP), и использовать её в команде пересылки MOV A, #M1 (ну или как там по синтаксису), и ничего "не будет". или запузырить переход на метку M2, которая объявлена примерно так: [b]M2: db 6[b] - и снова ничего не будет. скорее всего, ничего хорошего :)))
и распределением памяти ассемблер никак не занимается - программист сам метки расставляет, и будут они обозначать пересекающиеся области памяти или нет - его личное дело. и вряд ли линкер на это среагирует.

еще в ассемблере есть "подстановки" (директива EQU), или алиасы - но это тоже не эквивалент переменных.

главное отличие переменной, как сущности, в её независимости от контекста. т.е. при пересылках , присваивании и т.п. переменная выступает как атомарная единица программы. естественно, ассемблер такой абстракции не поддерживает.

во всяком случае ассемблеры MCS51, AVR, TASM и MASM работают именно так, как я и описал - с другими не имел чести быть знакомым...

Re: Ассемблер (ASM) для AVR в вопросах и ответах

Пн мар 09, 2020 22:27:34

с другими не имел чести быть знакомым...

Это ключевая фраза в Вашем сообщении.
Не работал с Ассемблером АВР, но поскольку нынче АВР принадлежит Микрочипу, приведу пример из MPASM.
Проблема в том, что мало кто удосуживается прочитать мануал на Ассемблер.
Так подавляющее большинство АСМописателей работающих с 8-битными ПИКами тупо брали манеру написания кода из темплейтов прилагавшихся к самому MPASM-у Микрочипом, которые написал какой то туповатый индус на удаленке.
И поэтому с удивлением обнаруживали при переходе на MPLAB X, что куда то исчезла видимость объявленных "переменных", которые объявили как КОНСТАНТЫ директивами EQU или CBLOCK/ENDC.
А всего то нужно было объявить переменные как неинициализированные данные директивой udata/udata_shr/udata_ovr/udata_acs и "таинственным" образом символьное имя будет привязано именно к адресу ДАННЫХ, а совсем не будет меткой со всеми вытекающими при трансляции последствиями. Мало того, квалификатор при директиве после подчеркивания разместит данные не где нибудь, а во вполне определенном сегменте ОЗУ. И при попытке "прибить гвоздями" пересекающиеся адреса переменных при явном определении расположения данных, в дело тут же вступит линкер, обматерив страдальца...
Таки да, имя объявленное для переменной будет означать АДРЕС этой переменной и использовать его можно или как указатель, или как непосредственные данные, определится это СИНТАКСИСОМ ассемблера этой платформы. То есть ровно так же, как и в Си - varname/*varname/&varname, только немного иными методами - размещением внутри инструкций в соответствующей позиции.
Метки кода при попытке их размещения в инструкции, как правило, приведут к ошибке линкера.
Аналогичные примеры могу привести из ASM30/ASM16 того же Микрочипа.
Да, метка кода - это перемещаемый или абсолютный адрес флеша, а имя переменной - это тоже адрес, но в ОЗУ. Но что тут может быть противоестественного, если в фон-неймановской архитектуре и данные и код находятся в одном адресном пространстве и метка кода действительно может быть именем переменной....

при пересылках , присваивании и т.п. переменная выступает как атомарная единица программы.
Ну нащщет ее атомарности бабка надвое сказала... Ее атомарность сильно зависит от архитектуры МК (его разрядности). Сколько удивлений вызывает у начинающих нарушение целостности int при присвоении в 8-битном МК... А еще эту целостность можно развалить методами Си специально...

Re: Ассемблер (ASM) для AVR в вопросах и ответах

Вт мар 10, 2020 02:22:41

Это функционал IDE(или по крайней мере препроцессора) а не ассемблера, ага прикрутили проверку и связи меток с именами переменных сверху, над ассемблером чтобы удобней их визуализировать - как раз это и есть пример типичного костыля. Скажите, как именно сам ассемблер решит что метка с адресом 0x0023 является переменной? и какой у неё размер? Все эти проверки прикручены в виде костылей и выполняются до того как будет вообще запущен компилятор или на первом его проходе. На уровне линкера проверять пересечения диапазонов? Ну это в качестве бреда... линкер работает уже после компилятора... когда код почти готов и осталось собрать все куски кода воедино, вычислив все смещения, поздновато на этом этапе сообщать об ошибках.

Re: Ассемблер (ASM) для AVR в вопросах и ответах

Вт мар 10, 2020 04:35:19

Спорить о вкусе устриц нужно с теми, кто их ел... Этот афоризм Жванецкого относится не только ко вкусовым предпочтениям.
1. Размерность переменных не является предметом рассмотрения ассемблера по одной очень простой причине - она ему не нужна для трансляции. Для ЯВУ нужна, а для АСМа - нет. Вы пытаетесь приписать АСМу не свойственные ему функции и на том основании делаете выводы о сущностях самого АСМа.
Но даже на разных языках человеческого общения есть разные объемы описания одних и тех же сущностей. Но никто при этом не берется утверждать, что слова в языке нет лишь потому, что язык не определяет в его смысле часть свойств, которые присутствуют в другом языке.
2. Контроль за размерностью в АСМе определяет линкер, патамушта единственной проблемой размерности от уровня ассемблера и ниже является определение абсолютных адресов. И не функция это среды, ибо определяются размерности ДИРЕКТИВАМИ АССЕМБЛЕРА, а среда лишь имеет возможность отображать то, что ей позволил АСМ.
Еще раз. АСМ в общем случае, является этапом компиляции из Си в бинарный код. И не надо пытаться сопоставлять эти языки по их влиянию на абстракции. Абстракции существуют независимо от инструментов для работы с ними.

Re: Ассемблер (ASM) для AVR в вопросах и ответах

Вт мар 10, 2020 08:42:48

КРАМ писал(а):Ее атомарность сильно зависит от архитектуры МК
я имел ввиду атомарность на уровне синтаксиса языка. в том смысле, что это неделимая языковая конструкция. поскольку ассемблер оперирует только с регистрами, понятие переменная ему чуждо именно по причине неатомарности работы с нею (в общем случае).
КРАМ писал(а):И при попытке "прибить гвоздями" пересекающиеся адреса переменных при явном определении расположения данных, в дело тут же вступит линкер, обматерив страдальца...
мне показалось, что это не в число плюсов, а в число минусов следует дописать. как в Си указатели - попытки наделить Си строгой проверкой типов указателей привела к появлению С++, но никак не улучшила Си. так и основное достоинство ассемблера заключается именно в вольнице работы с доступными ячейками памяти (и регистрами), и если эту вольницу ограничить, получится уже зародыш ЯВУ... я не уверен, что это достоинство АССЕМБЛЕРА. хотя привыкнуть можно ко всему, как и решать задачи можно всем
КРАМ писал(а):Спорить о вкусе устриц нужно с теми, кто их ел...
я ел много ассемблеров, но вот до микрочиповских руки не дошли :)) сомневаюсь, что там что-то сверхоригинальное на вкус :) тем более что с возрастом чувствительность вкусовых рецепторов притупляется...

Re: Ассемблер (ASM) для AVR в вопросах и ответах

Вт мар 10, 2020 11:05:24

это неделимая языковая конструкция
Если только ее не развалят через union и struct. :)
Но я говорил совершенно о другом.
Переменная как сущность это ИМЕНОВАННАЯ область оперативной памяти. Точка. Все остальное - это специфика языка.
Ассемблер рассматривает переменную именно так.
Я не собираюсь обсуждать те или иные достоинства Си по сравнению с ассемблером. Мне они известны. Как и недостатки первого в части встраиваемых архитектур.

я ел много ассемблеров, но ...

Вы меня и тут не поняли. Дело не в том, что Вы их ели, а в том, НА КАКОМ УРОВНЕ Вы это делали. Я не зря привел историю с микрочиповским ассемблером. То, о чем я написал существует лет так 20, если не больше. Сильно подозреваю, что и другие ассемблеры запилили не хуже...

Re: Ассемблер (ASM) для AVR в вопросах и ответах

Вт мар 10, 2020 11:29:05

КРАМ писал(а):Переменная как сущность это ИМЕНОВАННАЯ область оперативной памяти.
не совсем так - это, скажем, "исконный" смысл переменной. но в современном программировании это уже абстракция куда более высокого уровня, единственный корректный смысл которой - хранение данных. большинство ЯВУ в той или иной мере приближается к этому уровню... но не ассемблер - тут, естественно, вы абсолютно правы: для ассемблера переменная - это область памяти. но при этом ассемблер не оперирует этими областями, как чем-то атомарным, т.е. целым, как это делают ЯВУ. о чем я и говорил.

переменная в ассемблере - всего лишь очередной алиас, псевдоним метки. и тот факт, что линкер может следить за ними, ничего в сущности не меняет.

КРАМ писал(а):что и другие ассемблеры запилили не хуже...
ну да, когда-то давно мне попадалась в руки книжка "ООП на ассемблере" - выкинул, почти не читая :))) наделение ассемблера всеми этими "высокоуровневыми" наворотами, имхо (подчеркиваю - это моё личное мнение), ничего хорошего не делает: уровень абстракции ассемблера все равно остается слишком низким, чтобы облегчать программирование так, как это делают ЯВУ, но при этом заметно усложняют синтаксис, делая его отнюдь не таким простым, как изначально предполагалось (мнемоническая замена бинарных опкодов).

имхо, Кесарю - кесарево.

Re: Ассемблер (ASM) для AVR в вопросах и ответах

Вт мар 10, 2020 11:32:16

Ассемблер у АВРок и ПИКовых таки "немного отличается".
Основной разницей идут директивы распределения областей ОЗУ.
Второй пункт разницы - Регистр-аккумуляторы, с возможностью отображения на ОЗУ (аналогия только у ПИК24 вроде появляется).
Третий - линейная область ОЗУ без "дополнительных особенностей" (за пределами РСФ).
Атмел (до поглощения микрощипом) ближе к кейловскому стилю ассемблер подгонял.
По крайней мере "именованной областью оперативной памяти" может являться любой из регистров R0-R31...(они же и аккумуляторы)...
А также и любой из РСФ (но тут и у ПИКов аналогично сделано).
8)
Кстати...
Главное отличие ПИКового ассемблера - без дополнительного скрипта линкера для каждого конкретного кристалла он работать не будет (как и без линкера как компонента компилятора).
Такова уж особенность - по крайней мере у "среднемладшей".
Атмел вообще ушел от линкера (как для АВР, так и для mcs51)...
Что лучше/что хуже - в принципе и с тем и с другим работать вполне комфортно, разве что конспект для быстрой "перепрыжки" держать под руками надо (с "заметками о ....").
:beer:
Последний раз редактировалось BOB51 Вт мар 10, 2020 11:39:29, всего редактировалось 1 раз.

Re: Ассемблер (ASM) для AVR в вопросах и ответах

Вт мар 10, 2020 11:39:00

это, скажем, "исконный" смысл переменной. но в современном программировании это уже абстракция куда более высокого уровня

Коллега Алексей не обсуждал отклонения от "исконного смысла" в ЯВУ. Речь шла лишь о том, что в АСМе ЕСТЬ ПЕРЕМЕННЫЕ. И более ничего.

Re: Ассемблер (ASM) для AVR в вопросах и ответах

Вт мар 10, 2020 11:42:37

Если "переменная" как "ячейка с данными, кои могут изменяться в процессе исполнения программы"
то тогда еще можно принять.
:roll:
Ответить