Мне кажется, у начинающих есть такое недопонимание : вот на асме для данной задачки - целая страница, а на С - пару строчек, и все работает, значит, оно проще. И невдомек, что "проще" это только экономия усилий пальцами по клаве, а в результирующем коде, как правило, МК-ру приходится во втором случае трудиться в несколько раз больше. Это отнюдь не означает, что я антиСишник, и если бы мне пришлось на заказ клепать массу дивайсов так, что пот утереть некогда, то кончно, использовал бы его. А как для души - так на асме
Это только для молодой души. Со старостью приходит лень - какой там может быть ассемблер!
Что касается загрузки проца, так в большинстве проектов его вычислительная мощность используется только на несколько процентов. Ну будет он пустой Main Loop крутить не за 100 мкс, а за 500, ну и что? Пользователь даже не заметит. Есть, конечно, редкие случаи, где процессор загружен под завязку. Из своей практики могу привести один пример - генератор синуса. Такой проект пишется только на ассемблере. Раньше я так и делал. Но из-за лени в новой версии генератора я поставил 2 процессора, один запрограммирован на asm, но там только ядро DDS, а другой запрограммирован на Си, там все менюшки и прочее, связанное с интерфейсом пользователя.
Это только для молодой души. Со старостью приходит лень - какой там может быть ассемблер!
Пусть будет «лень» («мне лень за такое-то время писать один проект на асме, лучше я за это время два на С напишу… Или один на С и на даче вишни обрежу…»).
Леонид Иванович писал(а):
Есть, конечно, редкие случаи, где процессор загружен под завязку.
Исключения всегда есть. Кто со времён RU.EMBEDDED помнит флеймы am vs. C, тот помнит, что я всегда за С агитировал (время от времени демонстрируя, что на асме я тоже могу ). Позже, правда (ещё там, в RU.EMBEDDED), Журов за С++ начал и я уже в сторонке был Но сейчас я один небольшой проект для меги48 «макетирую» на С, но потом перепишу на асме. Чтобы с 1 мегагерца тактовую скинуть на 500 кГц и выиграть по потреблению. Там прерываний много и в прерываниях со многими переменными работа. На С прологи/эпилоги много жрут. А на асме внимательно разместив ключевые переменные (где-то так 20-24 из 32, на С -ffixed-reg/asm("Ri") столько не позволят разместить) навсегда в регистрах я выиграю достаточно для того, чтобы на 500 кГц всё успевать. Вот только далеко не всегда такое нужно.
_________________ Лень в виде мании величия: «ты гений, зачем стараться?». В виде комплекса: «всё равно не выйдет, зачем упираться?». Как логика: «если достаточно, зачем знать и уметь больше?». Цель одна: остановить. Не любит тепло работающих мышц и шум работающего мозга.
Качественное и безопасное устройство, работающее от аккумулятора, должно учитывать его физические и химические свойства, профили заряда и разряда, их изменение во времени и под влиянием различных условий, таких как температура и ток нагрузки. Мы расскажем о литий-ионных аккумуляторных батареях EVE и нескольких решениях от различных китайских компаний, рекомендуемых для разработок приложений с использованием этих АКБ. Представленные в статье китайские аналоги помогут заменить продукцию западных брендов с оптимизацией цены без потери качества.
Это только для молодой души. Со старостью приходит лень - какой там может быть ассемблер!
Спасибо, земляк, за бодрые слова об молодой душе, когда уже 7-й десяток закрываю
Цитата:
Что касается загрузки проца, так в большинстве проектов его вычислительная мощность используется только на несколько процентов.
Мне не повезло с синекурой - работал на частную фирму, где каждый цент на учете, и "давайте возьмем проц пошустрее" вызвало бы у шефа несколько слов, которых нет в словаре Ожегова И когда делаешь реалтайм по 4 каналам 50-Гц сигнала да еще с кучей float вычислений по оцифрованным массивам - тут уж даже на асме МК-ру, фигурально говоря, высморкаться некогда было
Компания EVE выпустила новый аккумулятор серии PLM, сочетающий в себе высокую безопасность, длительный срок службы, широкий температурный диапазон и высокую токоотдачу даже при отрицательной температуре.
Эти аккумуляторы поддерживают заряд при температуре от -40/-20°С (сниженным значением тока), безопасны (не воспламеняются и не взрываются) при механическом повреждении (протыкание и сдавливание), устойчивы к вибрации. Они могут применяться как для автотранспорта (трекеры, маячки, сигнализация), так и для промышленных устройств мониторинга, IoT-устройств.
Вариантов - море. Все зависит от схемы и вашего алгоритма. Одно из возможных:
Код:
LSL data ;ваши данные SBI data_port, n ;устанавливаем "1" на входе 595 BRCS met ;если перенос есть, то обходим CBI data_port, n ;устанавливаем "0" на входе 595 met: CBI shift_port,m ;импульс сдвига для 595. Данные записываются внутрь SBI shift_port,m
CBI latch_port,k ;импульс записи для 595 SBI latch_port,k
Сдвигать влево или вправо, записывать по одному биту или все махом, передавать на выход 595-ой - все в ваших руках.
Лучше сделать один проект хорошо, с пониманием чем два но лишь бы работало.
А ещё лучше два с пониманием. Или Вы о том, что за одно и то же время можно сделать один проект на асме с пониманием или два на С без понимания? Это не так. Причём чем сложнее проект, тем это более не так.
pyzhman писал(а):
Вариантов - море. Все зависит от схемы и вашего алгоритма.
Так в том-то и дело! Если кидаться кодить на асме «для эффективности» и просить примеров, но без понимания своей задачи, то и ответы не подойдут, и задача не решится. Асм как таковой не поможет, скорее наоборт — за деревьями леса не будет видно.
Если нужна предельная скорость, а объём кода не важен, то софт-spi можно и как-то так сделать: http://www.forum.radiokot.ru/forum/view ... 77#p514577 (только там и ввод, и вывод, в случае только вывода две последних команды в блоке rept нужно убрать) (вообще в этой теме soft-spi обсуждался, кажется, далеко не один раз)
Если кристалл позволяет инверсию выхода выводом в PIN (а сейчас таких большинство), то можно в каком-то регистре хранить маску с единичкой в месте тактового сигнала для сдвигового регистра и строб выдавать способом
Код:
ldi r16, 1 << m ... ... out shift_PIN, r16 ; два раза подряд инвертируем выход out shift_PIN, r16 ... ...
Это можно и в цикле делать, размер кода растёт на один ldi в начале плюс, при необходимости, на один sbi либо cbi на установку нужного состояние выхода клока, а время выполнения уменьшается на два такта для одного бита, на 16 тактов на байт.
_________________ Лень в виде мании величия: «ты гений, зачем стараться?». В виде комплекса: «всё равно не выйдет, зачем упираться?». Как логика: «если достаточно, зачем знать и уметь больше?». Цель одна: остановить. Не любит тепло работающих мышц и шум работающего мозга.
Что касается загрузки проца, так в большинстве проектов его вычислительная мощность используется только на несколько процентов. Ну будет он пустой Main Loop крутить не за 100 мкс, а за 500, ну и что? Пользователь даже не заметит. Есть, конечно, редкие случаи, где процессор загружен под завязку. Из своей практики могу привести один пример - генератор синуса. Такой проект пишется только на ассемблере. Раньше я так и делал. Но из-за лени в новой версии генератора я поставил 2 процессора, один запрограммирован на asm, но там только ядро DDS, а другой запрограммирован на Си, там все менюшки и прочее, связанное с интерфейсом пользователя.
Вот у меня дилемма сейчас. Пишу пока все на АСМЕ, в т.ч. и менюшки. Конечно хотелось бы освоить С чтобы не мелочится с интерфейсом. Но есть проблема - я использую активно прерывания по таймеру и большинство задач решаю в прерывании. Причем мой любимый метод настроить одно прерывание например 10кгц (обрабатываются скоростные процедуры, как например 1wire, обработка радиообмена, и т.д.), внутри этого же прерывания организован счетчик который делит частоту прохода до 100-400 гц (динамическая индикация, опрос кнопок, часы, переменные, и т.д.) причем в низкоскоростной части прерывания разрешены чтобы не нарушать высокоскоростную часть. Если я все это зделаю на С, то скоростная часть безнадежно не впишется, так как там я вылизываю процедуры до байтов. Посоветуйте, как можно решить эту дилемму, основную прогу писать на С, а в прерываниях сохранить компактность ассемблера.....
Причем мой любимый метод настроить одно прерывание например 10кгц (обрабатываются скоростные процедуры, как например 1wire, обработка радиообмена, и т.д.)
Ну так я делал на старых классических 51-ых, где катастрофически не хватало таймеров. Одна оставшаяся свободной половинка давала прерывание раз в 256 циклов процессора и от него всё плясало. Кстати, одна из программ дожила до где-то семи тысяч строк на С плюс около трёх на асме. Это было последнее, что я на 51-ых делал. Все прерывания были на асме для скорости. Часть обработки на асме для компактности не сильно в ущерб скорости (там практически прямой шитый код был). Если бы не то, что поначалу был зажат 16-килобайтным ПЗУ, то этого и не делал бы. Но потом все равно не влезло, в итоге в 32 килобайтах было занято 25. Не думаю, что на чистом асме назад в 16 К влез бы, там одних знакогенератора и текстовых строк было килобайт 8, а 17 килобайт из-под С в 8 килобайт на асме всё равно не влезли бы.
В таких случаях программа на С общается с прерываниями через буфера и флаги запуска действия и готовности выполнения. Не забывать такие флаги на С квалифицировать как volatile, иногда и буфера желательно. Но сейчас вроде ж с таймерами полегче, нет нужды вешать всё на один (точнее, на одно прерывание от него). Ну например, у нас есть кварц 7.3728 и 8-битный таймер с каналами сравнения. Ставим таймеру прескалер 64. Переполнение таймера получаем 7372800/64/256 = 450 герц, для той же динамической индикации. Ну и там уже не жалко времени на доделиватели для 10 мс и 1 сек программных таймеров для «просто службы времени».
Теперь один из каналов сравнения настраиваем на прерывание по сравнению и в прерывании передвигаем точку сравнения в будущее, причём как опора не текущее состояние таймера, а предыдущее значение регистра сравнения, тогда сетка будет равномернее, ошибка не будет накапливаться.
Код:
... ; // OCR0A += 12; in r16, OCR0A subi r16, -12 out OCR0A, r16
Получим прерывание 7372800/64/12 = 9600 Гц, это программный UART, передача. Приём аналогично, только по прерыванию по спаду стартового бита в OCR0B заносим значение TCNT0 с отступом вперёд на пол или полтора бита (в зависимости от того, будем ли ловить ошибку старт-бита) и некоторой коррекцией на задержку обработки этого прерывания от спада.
Если прерывание от спада далать по input capture, то тогда легче, просто OCR1B = ICR1 + (в зависимости от длины бита и задачи).
Таким образом для обслуживания soft-UART занято аж три прерывания, два из которых работают с одним автоматом (машиной состояний) на приём. Но зато они возникают только тогда, когда они нужны. По завершению передачи прерывание TX OCR0A просто запрещается (в конце отработки стопового бита — если в буфере передачи нет других байтов). Пока не приёл стартовый бит на приём, OCR0B тоже запрещено. Если это вешать на один таймер, то надо было бы хотя бы на 28.8 килогерца проверять состояние входной линии RX, не пришёл ли стартовый бит. И прерывание лупило бы постоянно, даже когда никто ничего не присылает.
Конечно, можо и такую методику облегчения нагрузки и всё на асме писать, но если оно надо. А нагружать все в одно прерывание с тем, чтобы оно часть работы каждый раз делало впустую (а иначе нельзя, пропустит) — какой смысл?
После расталкивания по разным прерываниям уже можно решить, кто может подождать и в начале тех прерываний разрешать вложенные. Иногда это и не нужно, так как каждое прерывание получается довольно простое, С-компилятор не сохраняет/восстанавливает по полтора десятка регистров, чо благотворно сказывается на времени обработки. Иногда это невозможно -- в одной из небольших (около 8 килобайт вместе с printf, это С++ с шаблонами для размножения обработчиков прерываний из одного шаблона) программ на меге64 у меня все шесть OCR от 16-битных таймеров и еще 6 внешних прерываний задействованы. Плюс UART на компьютер, еще два прерывания, итого 14. Так и немного Это был 6-канальный приёмник чего-то LIN-подобного с настройкой частоты по первому байту пакета. Все 6 каналов равноправны, выделять какой-то один и в остальных разрешать вложенные прерывания просто нет смысла.
_________________ Лень в виде мании величия: «ты гений, зачем стараться?». В виде комплекса: «всё равно не выйдет, зачем упираться?». Как логика: «если достаточно, зачем знать и уметь больше?». Цель одна: остановить. Не любит тепло работающих мышц и шум работающего мозга.
Теперь один из каналов сравнения настраиваем на прерывание по сравнению и в прерывании передвигаем точку сравнения в будущее, причём как опора не текущее состояние таймера, а предыдущее значение регистра сравнения, тогда сетка будет равномернее, ошибка не будет накапливаться.
Так если прерывание по сравнению, то там ошибка и не накапливается, зачем передвигать точку сравнения?
avreal писал(а):
Таким образом для обслуживания soft-UART
Да вообщета для обмена по радиоканалу я не использую UART, использую свой обработчик на основе манчестера.
avreal писал(а):
После расталкивания по разным прерываниям уже можно решить, кто может подождать и в начале тех прерываний разрешать вложенные.
Да если надо будет то распихаю по разным, пока в этом проблемы нет. Вопрос, в том как в программе на С вставить ассемблерный блок, в частности обработчик прерываний.
avreal писал(а):
В таких случаях программа на С общается с прерываниями через буфера и флаги запуска действия и готовности выполнения.
Вот тут прозвучала интересная мысля..... Хотя основная программа так и общается с прерываниями, но и та и та у меня на асме. А можно на С рарезервировать некоторые регистры контроллера, чтобы С их не использовал, обозвать эти регистры именами, и использовать из С и из Асма эти регистры совместно? Тогда основная прога будет на С, а к ней просто прилепить файл обработки прерываний написанный на Асме.....
Заголовок сообщения: Re: Ассемблер (ASM) для AVR в вопросах и ответах
Добавлено: Вт июл 10, 2012 13:44:10
Держит паяльник хвостом
Карма: 15
Рейтинг сообщений: 70
Зарегистрирован: Ср мар 28, 2012 21:45:24 Сообщений: 904 Откуда: ВО
Рейтинг сообщения:0
Цитата:
Так если прерывание по сравнению, то там ошибка и не накапливается, зачем передвигать точку сравнения?
Это так называемый Free Timer. Он считает от 0 до 0xFF или 0xFFFF(16-бит) и так по кругу не останавливаясь.(Mode- NORMAL) Если нам нужно получить частоту 9600 , то каждые (Х+12) мы будем получать прерывание по сравнению . Где Х=0...FF или для 16-ти (FFFF)
И все таки: Возможно ли на С рарезервировать некоторые регистры контроллера, чтобы С их не использовал, обозвать эти регистры именами, и использовать (как переменные) из С и из Асма, совместно? (например основная прога будет на С, а файл обработки прерываний написанный на Асме.....)
Заголовок сообщения: Re: Ассемблер (ASM) для AVR в вопросах и ответах
Добавлено: Вт июл 10, 2012 15:29:42
Друг Кота
Карма: 67
Рейтинг сообщений: 1012
Зарегистрирован: Чт сен 18, 2008 12:27:21 Сообщений: 18798 Откуда: Столица Мира Санкт-Петербург
Рейтинг сообщения:0 Медали: 1
Ну, это уже лучше у СИшников спрашивать. Причём даже могут быть различия между компиляторами. В СИ для ядра 8051 вроде можно было объявить переменную со свойством register. Правда, сам не пробовал.
_________________ [ Всё дело не столько в вашей глупости, сколько в моей гениальности ] [ Правильно заданный вопрос содержит в себе половину ответа ] Измерить нннада?
Заголовок сообщения: Re: Ассемблер (ASM) для AVR в вопросах и ответах
Добавлено: Вт июл 10, 2012 23:00:16
Друг Кота
Карма: 67
Рейтинг сообщений: 1012
Зарегистрирован: Чт сен 18, 2008 12:27:21 Сообщений: 18798 Откуда: Столица Мира Санкт-Петербург
Рейтинг сообщения:0 Медали: 1
pyzhman писал(а):
asm vs C
Можно в МЯЯЯУ открыть. Такой срач начнётся...........
_________________ [ Всё дело не столько в вашей глупости, сколько в моей гениальности ] [ Правильно заданный вопрос содержит в себе половину ответа ] Измерить нннада?
Причем мой любимый метод... Если я все это зделаю на С, то скоростная часть безнадежно не впишется, так как там я вылизываю процедуры до байтов.
Советую плюнуть - и всё. Смириться, как получается в Си, так и пойдет. Неужели есть охота сильно напрягаться? Вообще, я делаю примерно всё то же самое, причем на Си, и всё работает. Для 1-Wire зачем прерывание 10 кГц? У меня этот интерфейс обслуживается в основной программе. Да, есть в нем микросекундные интервалы, кторые нужно точно выдержать, там в любом случае прерывания должны быть запрещены. Ничего длинного в обработчиках не делаю, всё по флагам делает основная программа. Прерывание таймера обычно тикает 1 или 2 кГц и только устанавливает флаг нового системного интервала, внутри обработчика ничего больше нет. По этому флагу все процессы декрементируют свои программные таймеры, которые формируют нужные интервалы (антидребезг, автоповтор клавиатуры, мигание дисплея и т.д.). Радиообмен не делал, но для него или использовал бы UART, или завел бы еще одно прерывание другого таймера. Понятно, что программируя на Си жесткого реалтайма не достичь, но в 99% случаев его хватает, а в остальных можно поставить аппаратные кодеки и т.д., это проще, чем ковыряться в ассемблере.
shads писал(а):
Возможно ли на С рарезервировать некоторые регистры
Можно, но с ограничениями. Вообще, на практике наибольший прирост эффективности программ получался при монопольном владении в прерывании не простым регистром, а, например, указателем (XH:XL, YH:YL или чаще ZH:ZL) и даже несколькими. Компилятор не отдаст свои любимые регистры. В результате таким шаманством, как часть программы на asm, а часть на Си, не занимался никогда. Почти всё ложится на Си, и всего лишь два сопроцессора с маленькой программой (ATmega88 и AT90PWM3B) запрограммировал на asm за последних 4 года.
Сейчас этот форум просматривают: Engineer_Keen и гости: 22
Вы не можете начинать темы Вы не можете отвечать на сообщения Вы не можете редактировать свои сообщения Вы не можете удалять свои сообщения Вы не можете добавлять вложения