Речь о том, что ЛЮБАЯ вставка на ассемблере в Си подчиняется правилам проекта в целом
еще раз вставки НЕТ - есть файлы (можно только ассемблерные), а сборка всего проекта проводится по предельно простым правилам:
Код:
1)# Assemble: create object files from assembler source files. 2)# Compile: create object files from C source files. 3)# Link: create ELF output file from object files.
гуглеперевод:
Код:
1) # Assemble: создание объектных файлов из исходных файлов на ассемблере. 2) # Компиляция: создание объектных файлов из исходных файлов Си. 3) # Link: создать выходной файл ELF из объектных файлов.
Запускаем полный комплект ассемблер - линкер - библиотекарь, да еще относительно компилятора СИ? Он же будет планировку для Си делать. Да и указанное в приведенном Вами выше файле не выходит за рамки типичной подпрограммы, которую можно разместить в рамках проекта ЛЮБОГО компилятора (хоть ассемблер хоть Си).
полный комплект состоит всего из одного файлика avr-gcc.exe - он компилирует и си и асм файлы и линкует вдобавок
ой ли? по-моему, он всего лишь вызывает соответствующие модули из папки bin тулчейна, передавая между ними параметры... или нет?
Добавлено after 7 minutes 58 seconds: сам себе отвечаю: не прав был... действительно, один файл все делать может... во всяком случае для однофайлового проекта, на котором протестировал.
_________________ если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе при взгляде на многих сверху ничего не меняется...
GCC также известен как программа-драйвер, поскольку он знает о ней и легко управляет другими программами для создания конечного результата. Ассемблер и компоновщик являются частью другого проекта с открытым исходным кодом, называемого GNU Binutils. GCC знает, как заставить GNU-ассемблер (газ) собирать выходные данные компилятора. GCC знает, как управлять компоновщиком GNU (ld), чтобы связать все объектные модули в конечный исполняемый файл.
но вопрос странноватый был;
Цитата:
Запускаем полный комплект ассемблер - линкер - библиотекарь, да еще относительно компилятора СИ?
ответ (тоже странный) - запускаем один файлик. з.ы. BOB51 бы ручками позапускал бы компилятор в командной строке и много вопросов отпало бы и ардуино оказалось не нужным бы
Да запускал и запускаю. Только ассемблер относительно 51-й и из батника. Можно было бы попробовать Ваш вариант подключения с готовой АВРкиной прожкой, но она у меня несколько на слэнге сделана - под "чистокровный ассемблер" придется перелопатить...
Это всего-то тест светиков. Попробуйте его вставкой в Сишный проект сделать. Допустим ... как исполнительный драйвер индикации для проекта какого-либо прикладного назначения (индикация при сработке будильника к примеру). Вернее даже не всю прожку, а только обработчик вывода - trd2812_m.txt.... С учетом его особенностей...
.section .bss .global bufout ; xfunc_out must be initialized before using this module. bufout: .ds.w 5 .section .text
.global bob51_func .func bob51_func bob51_func: rjmp mass_trm slot0: ; 6/14 (6-4=2 посему роль остатка выполняет CBI) cbi port_out, out_line ; 2 цикла nop nop nop nop nop nop nop nop nop ret ; 4 цикла slot1: nop ; 13/7 (13-4=9) nop nop nop nop nop nop cbi port_out,out_line ; 2 цикла nop nop ret ; 4 цикла xslot0: ; 6/14 (6-5=1 посему роль остатка выполняет CBI с избытком в 1 nop) cbi port_out,out_line ; 2 цикла cbr zl,(1<<6) ; модификация указателя 1 цикл nop nop nop nop nop nop ; -2 цикла на ld R16,x+ dec R17 ; 1 цикл brbs SREG_Z,ends_trd ; 1 цикл при неисполнении (в цикле) rjmp trasstt ; 2 цикла xslot1: nop ; 13/7 (13-5=8) cbr zl,(1<<6) ; модификация указателя 1 цикл nop nop nop nop nop cbi port_out,out_line ; 2 цикла ; -2 цикла на ld R16,x+ dec R17 ; 1 цикл brbs SREG_Z,ends_trd ; 1 цикл при неисполнении (в цикле) rjmp trasstt ; 2 цикла ; ends_trd: pop R16 pop R17 pop xl pop xh pop zl pop zh ; восстановить рабочую область из стека ret ;---------- ; ; предварительно: ; линия out_line настроена на вывод ; исходный уровень out_line =0 ; указатель стека усатновлен на RAMEND ; массив данных (bufout:bufout_size) предварительно загружен ; флаг готовности массива данных установлен ; mass_trm: push zh push zl push xh push xl push R17 push R16 ; храним рабочую область в стеке res_line: ldi R16, 4 ser R17 cbi port_out,out_line res_time: dec R17 brne res_time dec R16 brne res_time ; =>50uS time out ldi XH,hi8(bufout) ldi XL,lo8(bufout) ; загрузка начального адреса массива ; в указатель ldi R17, 5 ;bufout_size ldi ZL, lo8(slot0) ; адрес начала таблицы в указателе ldi ZH, hi8(slot0) ;---------- trasstt: ld R16,x+ ; 2 цикла slot_0: sbi port_out,out_line ; 2 цикла реально до установки 3 цикла bst R16,7 ; 1 цикл bld zl,4 ; 1 цикл icall ; 3 цикла = 4 цикла от out_line=1 ;---------- slot_1: sbi port_out,out_line bst R16,6 ; 1 цикл bld zl,4 ; 1 цикл icall ; 3 цикла ;---------- slot_2: sbi port_out,out_line bst R16,5 ; 1 цикл bld zl,4 ; 1 цикл icall ; 3 цикла ;---------- slot_3: sbi port_out,out_line bst R16,4 ; 1 цикл bld zl,4 ; 1 цикл icall ; 3 цикла ;---------- slot_4: sbi port_out,out_line bst R16,3 ; 1 цикл bld zl,4 ; 1 цикл icall ; 3 цикла ;---------- slot_5: sbi port_out,out_line bst R16,2 ; 1 цикл bld zl,4 ; 1 цикл icall ; 3 цикла ;---------- slot_6: sbi port_out,out_line bst R16,1 ; 1 цикл bld zl,4 ; 1 цикл icall ; 3 цикла ;---------- slot_7: sbi port_out,out_line sbr zl,(1<<6) ; модификация указателя под завершающий фрагмент ; 1 цикл bst R16,0 ; 1 цикл bld zl,4 ; 1 цикл ijmp ; 3 цикла ;---------- .endfunc
Makefile Спойлер
Код:
### Project name (also used for output file name) PROJECT = BOB51_test
ЖУТЬ... И для простенького фрагмента выписывать тот Makefile?... Легче уж под чистым ассемблером несколько файликов настрочить. Надеюсь обратили внимание, что там точки входа с жестко заданными адресами (или с определенным пропуском) даже если использовать вариант перемещаемого кода slot1=slot0+16 А не линейное продолжение как в Вашем примере. на всякий случай оригинал, чтоб понятнее было в чем ловушка: Спойлер
Код:
; ; ; trd2812_m.txt ; ; файл обработчика передачи массива ; из буфера вывода в линейку на основе WS2812B ; базовый МК из линейки АТМЕЛ при тактовой частоте ; от 16 Мегагерц ( 0,000000062 S) ; ; требуемые интервалы по даташиту WS2812B ; ;Data transfer time( TH+TL=1.25µs±600ns) ; T0H 0 code ,high voltage time 0.4us ±150ns ; T1H 1 code ,high voltage time 0.8us ±150ns ; T0L 0 code ,low voltage time 0.85us ±150ns ; T1L 1 code ,low voltage time 0.45us ±150ns ; RES low voltage time Above 50µs ; исходный уровень линии связи = 0 ; данные передаются пакетами из трех байт на точку ; старшими битами вперед в последовательности ; соответствующей G - R - B цветам точки ; количество блоков должно соответствовать ; количеству точек в ленте ; ; реальные данные согласно тест - отладки дебаггером (версия1!) ; авр-студио 4.19 ; ; Data transfer time( TH+TL=1.38µs -10ns) ; T0H 0 code ,high voltage time 0.44us ±10ns ; T1H 1 code ,high voltage time 0.88us ±10ns ; T0L 0 code ,low voltage time 0.94us ±10ns ; T1L 1 code ,low voltage time 0.50us ±10ns ; RES low voltage time 192,88uS (Above 50µs) ; ; длина прерывания с пакетом загрузки (x60*3) = 2175uS (0.002175) ; интервал между прерываниями (irq t/c0) = 0.004S (4000uS) ; ; define datas ; .equ port_out = PORTB ; порт вывода (по усмотрению) ; .equ out_line = 0 ; линия вывода данных ; .equ bufout = SRAM_START ; начальный адрес буфера вывода ; .equ pixel = 60 ; количество точек в линейке/ленте ; .equ bufout_size = (pixel * 3) ; не может быть более объема ОЗУ - стек!!!
.cseg .org 0x0020 ; старовая позиция 0х0020 !!! slot0: ; 6/14 (6-4=2 посему роль остатка выполняет CBI) cbi port_out,out_line ; 2 цикла nop nop nop nop nop nop nop nop nop ret ; 4 цикла .org (slot0+16) slot1: nop ; 13/7 (13-4=9) nop nop nop nop nop nop cbi port_out,out_line ; 2 цикла nop nop ret ; 4 цикла .org 0x0060 xslot0: ; 6/14 (6-5=1 посему роль остатка выполняет CBI с избытком в 1 nop) cbi port_out,out_line ; 2 цикла cbr zl,(1<<6) ; модификация указателя 1 цикл nop nop nop nop nop nop ; -2 цикла на ld tmp0,x+ dec tmp1 ; 1 цикл brbs SREG_Z,ends_trd ; 1 цикл при неисполнении (в цикле) rjmp trasstt ; 2 цикла .org (xslot0+16) xslot1: nop ; 13/7 (13-5=8) cbr zl,(1<<6) ; модификация указателя 1 цикл nop nop nop nop nop cbi port_out,out_line ; 2 цикла ; -2 цикла на ld tmp0,x+ dec tmp1 ; 1 цикл brbs SREG_Z,ends_trd ; 1 цикл при неисполнении (в цикле) rjmp trasstt ; 2 цикла ; ends_trd: pop tmp0 pop tmp1 pop xl pop xh pop zl pop zh ; восстановить рабочую область из стека ret ;---------- ; ; предварительно: ; линия out_line настроена на вывод ; исходный уровень out_line =0 ; указатель стека усатновлен на RAMEND ; массив данных (bufout:bufout_size) предварительно загружен ; флаг готовности массива данных установлен ; mass_trm: push zh push zl push xh push xl push tmp1 push tmp0 ; храним рабочую область в стеке res_line: ldi tmp0,4 ser tmp1 cbi port_out,out_line res_time: dec tmp1 brne res_time dec tmp0 brne res_time ; =>50uS time out ldi xh,high (bufout) ldi xl,low (bufout) ; загрузка начального адреса массива ; в указатель ldi tmp1,bufout_size ldiw z,slot0 ; адрес начала таблицы в указателе ;---------- trasstt: ld tmp0,x+ ; 2 цикла slot_0: sbi port_out,out_line ; 2 цикла реально до установки 3 цикла bst tmp0,7 ; 1 цикл bld zl,4 ; 1 цикл icall ; 3 цикла = 4 цикла от out_line=1 ;---------- slot_1: sbi port_out,out_line bst tmp0,6 ; 1 цикл bld zl,4 ; 1 цикл icall ; 3 цикла ;---------- slot_2: sbi port_out,out_line bst tmp0,5 ; 1 цикл bld zl,4 ; 1 цикл icall ; 3 цикла ;---------- slot_3: sbi port_out,out_line bst tmp0,4 ; 1 цикл bld zl,4 ; 1 цикл icall ; 3 цикла ;---------- slot_4: sbi port_out,out_line bst tmp0,3 ; 1 цикл bld zl,4 ; 1 цикл icall ; 3 цикла ;---------- slot_5: sbi port_out,out_line bst tmp0,2 ; 1 цикл bld zl,4 ; 1 цикл icall ; 3 цикла ;---------- slot_6: sbi port_out,out_line bst tmp0,1 ; 1 цикл bld zl,4 ; 1 цикл icall ; 3 цикла ;---------- slot_7: sbi port_out,out_line sbr zl,(1<<6) ; модификация указателя под завершающий фрагмент ; 1 цикл bst tmp0,0 ; 1 цикл bld zl,4 ; 1 цикл ijmp ; 3 цикла ;----------
механизм обработки тайм-слотов основан на фиксированных адресах начала блоков формирования тайм-слотов. slot0 = 0x0020 slot1 = slot0+16 xslot0 = 0x0060 xslot1 = xslot0+16 Можно конечно то и препроцессору поручить - но тогда переписываем определенные участки обработчика trasstt. Иначе хоть и соберется - но работать не будет.
makefile скопирован из проекта Чена, легким движением настраивается - тип микроконтроллера и перечень исходников. Теперь он НАВСЕГДА - легко идет в другие проекты и даже под армы подправить можно. Насчет жестких адресов (никогда не приходилось) - легко решаемо другими способами (имхо), даже любимыми вставками обходятся https://github.com/lpodkalicki/blog/blo ... t_ws2812.c
на всякий случай оригинал, чтоб понятнее было в чем ловушка
я бегло посмотрел... и понял, в чем ловушка... или догадался. ваш код абсолютно непортируемый. вот это большое количество NOP-ов - это же задержки? чуть поменялась тактовая частота, и надо пересчитывать неизвестно как новое их количество... жестко привязанные точки входа - это не достоинство, а недостаток: чуть изменился тип МК (например, взяли МК с более чем 64К памяти, чтобы Jmp/call стал четырехбайтным - все, сливай воду... и так далее.
ваш пример как раз хорош в качестве "страшилки" для начинающих программистов: будете дети вот так писать - никто вас на работу не возьмет, так и будете всю жизнь вручную pop-push по 30 раз писать...
_________________ если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе при взгляде на многих сверху ничего не меняется...
Ну так.. на то и ассемблер, чтоб подобные вопросы решать. Насчет четырехбайтового вызова - то только при вызове самой программы - в теле используется косвенная адресация (IJMP)- а она НЕИЗМЕННА по времени. Использование высчитываемых вручную задержек в принципе вполне обосновано в данном случае (фазовая манипуляция с помощью ногодрыга под протокол WS2812 при обеспечении долговременной стабильности комплектов слотов). Вопрос же был в том - все ли варианты приемов "чистого ассемблера" легко переносятся в Си. Кроме прочего - алгоритм не только для АВРок... Мне надо иметь возможность однотипные приемы на разных семействах отрабатывать. Посему и предпочитаю правило - не мешать чистый ассемблер с ЯВУ в варианте разнообразных ассемблерных вставок. Другое дело приемы работы и алгоритмические решения, если таковое возможно (и за шо меня периодически поцарапывают).
Последний раз редактировалось BOB51 Пт мар 20, 2020 21:13:20, всего редактировалось 1 раз.
все ли варианты приемов "чистого ассемблера" легко переносятся в Си
ну знаете... вопрос из разряда "где взять упряжь для кошки?" - зачем ВСЕ ВАРИАНТЫ переносить? в Си следует переносить лишь то, без чего принципиально невозможно решить задачу!
_________________ если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе при взгляде на многих сверху ничего не меняется...
Ну так.. на то и ассемблер, чтоб подобные вопросы решать
Подобные вопросы в современном мире теперь принято аппаратно решать - см. AN1606: Using the Configurable Logic Cell (CLC) to Interface a PIC16F1509 and WS2811 LED Driver
ARV Вот и я про то же - не следует пихать в ЯВУ примитивы. Для того соответствующие средства имеются. В адуринке следует следовать концепту применения референса, а не пытаться "гибриды" лепить (по крайней мере на уровне "продвинутого пользователя"). А мне рекомендуют скрещивать адуринку с ассемблерными файлами. Говорю же уже какой раз - в рамках IDE руководствуемся возможностями, предлагаемыми референсом. А ежли хотим повыделываться - берем нашу DIP микросборку (ту же нанку) и программируем в рамках соответствующего компилятора (хоть Си, хоть ассемблер) - но то уже не ардуино, а конструкция на базе соответствующего МК.
Насчет аппаратных... Там где много аппаратных модулей понатыкано есть побочный эфект - надо детально изучать начинку на предмет начального состояния МК. Дабы изолировать неиспользуемые узлы. А это ужшшш... Весьма муторное занятие (да и накладно). Обычно ограничиваемся определенным набором проработанных кристаллов в каждом семействе.
Снова мимо! А я то думал, найдется таки умная усато-полосатая сущность и покажет решение средствами препроцессора. Я - то ведь всего лишь "продвинутый пользователь-любитель". В прожке позиционно-программный селектор (аналогия табличного дешифратора для скоростного двоично-десятичного преобразования в диапазоне 0-99 - классического приема при работе под ассемблером). Это касательно АВРок более актуально - анализ и выдача значения с одинаковым интервалом (оптимизация по скорости и равным интервалам для определения как 0 так и 1). Для получения ограниченно перемещаемого кода там всего-то надо жестко обусловить начальный адрес подпрограммы. У стартового адреса допустимы любые из нижеприведенных значений: 0хnn00 0xnn20 0xnn40 0xnn60
лично я экспериментировать не буду - ибо писал эта и подобные задачи легко решаются другим путем или програмным или аппаратным. Нет такой задачи, где понадобились бы фиксированые адреса (имхо) - а если есть просьба, описать словами такую задачу с обоснованием необходимости. По исходнику трудно понять что требовалось - если зажигать светодиоды, то была ссылка как это делать без фиксированых адресов.
А при помощи препроцессора компилятора ассемблера никак? Печалька однако... Ибо писать скрипты линкера под каждый файл, коих в многофайловом проекте может быть энное количество, весьма муторно... А в варианте моего "слэнга" практически от такой заморочки я избавлен. Касательно "других решений" - естественно оные имеются, однако вопрос о некорректности применения "чисто ассемблерных файлов", не учитывающих специфику работы компилятора Си, в проектах заточенных под Си похоже закрыт. Пример, который я привёл выше - всего лишь одна из разновидностей классического решения при работе под " чистым ассемблером". И таких приёмов, некорректных по отношению к "чистому Си" достаточно много встречается. Просто не стоит "впадать в крайности" - у каждого из компиляторов свои особенности, которые надо учитывать при работе.
Да любых авторов - зависит от самого проекта и рациональности применения. Просто Вы, почуствовав сложности работы с "чистым ассемблером", пораньше на Си соскочили. Писанина скриптов и маке-файлов должна быть осознанно - самостоятельной. А коль такового уровня нету - стараемся в дебри не лазить без особой необходимости. Существует достаточно много методов, позволяющих обойти подобные осложнения.
Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 5
Вы не можете начинать темы Вы не можете отвечать на сообщения Вы не можете редактировать свои сообщения Вы не можете удалять свои сообщения Вы не можете добавлять вложения