Страница 1 из 1
Ассемблерная вставка Avr Studio 5 GCC
Добавлено: Вт фев 06, 2018 17:45:03
vovik15
Здравствуйте! целую неделю воевал с адресуемой светодиодой лентой WS2812. Код написанный на си выполнялся некорректно, было решено написать функцию критичную по времени на ассемблере. В итоге родился вот такой код
Код: Выделить всё
WsOut: //вывод данных
push DataReg; копируем в стек DataReg
ldi Counter,8;устанвливаем счетчик в8
m1:
lsl DataReg; << старший бит выдвигается в С регистра SREG
brcs C_1 ; проверяем флаг С , если 1 то переходим на C_1
brcc C_0 ; проверяем флаг С , если 0 то переходим на C_0
m2: ; сюда вернемся после обработки подпрограммы
dec Counter ; C--
cpi Counter,0; сравниваем значение счетчика с нулем
brne m1;переходим на m1 если не нулевой результат
pop DataReg; извлекаем из стека DataReg
ret; конец подпрограммы
C_0: //если флаг С в регистре SREG равен0
sbi PORTB,0 //установить в 1 бит 0 порта B
nop nop nop; держим 0,333 мкс
cbi PORTB,0 //установить в 0 бит 0 порта В
nop nop nop ;держим 0,9167 мкс
nop nop nop
rjmp m2; возвращаемся в подпрограмму вывода данных
C_1: //если флаг С в регистре SREG равен1
sbi PORTB,0 //установить в 1 бит 0 порта B
nop nop nop ; держим 0,8333 мкс
nop nop nop
nop nop nop
cbi PORTB,0 //установить в 0 бит 0 порта В
//держим 0,4167 мкс
rjmp m2; возвращаемся в подпрограмму вывода данных
Реализацию самих световых эффектов хочу сделать на си, так как это проще и лучше. Вопрос в следующем, как этот кусок кода оформить в виде сишной функции, и скормить компилятору? Поиск в гугле явных ответов не дал,вопросов стало только еще больше. Огромное спасибо за понимание
Re: Ассемблерная вставка Avr Studio 5 GCC
Добавлено: Вт фев 06, 2018 18:26:03
ARV
Сделайте, как я - задействуйте аппаратный SPI, и не мучайтесь с ассемблером! При 16 МГц тактовой работает отлично!
Добавлено after 51 second:
Кстати, со дня на день опубликуется моя статья (на Паяльнике) - там и исходники на Си прилагаются, и кое-какие эффекты...
Re: Ассемблерная вставка Avr Studio 5 GCC
Добавлено: Вт фев 06, 2018 19:39:22
vovik15
Несколько лет назад вы мне микросхемы посылкой в Тамбов выслали

ещё раз вам за это спасибо!
Добавлено after 55 minutes 44 seconds:
Все дело в том,что эта лента будет использоваться в сложном проекте,и аппаратный spi уже занят
Re: Ассемблерная вставка Avr Studio 5 GCC
Добавлено: Вт фев 06, 2018 19:52:43
ARV
vovik15 писал(а):Все дело в том,что эта лента будет использоваться в сложном проекте,и аппаратный spi уже занят
если проект на самом деле сложный, то разумнее будет для иных целей сделать программный SPI, а аппаратный под WS-ки выделить, иначе это будет геморрой, а не проект.
кстати, чем занят SPI? в моём проекте, который сейчас на модерации на Паяльнике, аппаратный SPI использован и под WS2812 и для работы с SD-картой.
Re: Ассемблерная вставка Avr Studio 5 GCC
Добавлено: Вт фев 06, 2018 21:54:33
vovik15
Он занят передачей данных на драйвер мах7221. Ну впринципе его можно и программно обрабатывать без проблем. А как досрочно посмотреть вашу статью?
Добавлено after 1 minute 32 seconds:
Я если честно не совсем понимаю как вам удалось реализовать строгие тайминги на аппаратном spi
Добавлено after 38 minutes 10 seconds:
Почитал,принцип понятен,главное правильно биты на линию выставлять,жаль что я не подумал об этом раньше
Re: Ассемблерная вставка Avr Studio 5 GCC
Добавлено: Ср фев 07, 2018 07:05:36
ARV
если хотите ассемблерную вставку, то найдите и скачайте "библиотеку" neopixel (кажется так называется) для ардуино. во всяком случае любой проект с WS-ками на ардуино применяет эту библиотеку - там исходник на GCC, и вывод как раз на ассемблере с жесткой привязкой NOP-ами к тактам... можно и посмотреть, как оформлено, да и слизнуть код можно.
или наберитесь терпения и дождитесь публикации моего проекта - там полные исходники всего, включая работу с WS2812b через аппаратный SPI. по условиям публикации на Паяльнике я досрочно ничего не могу показывать...
Re: Ассемблерная вставка Avr Studio 5 GCC
Добавлено: Чт фев 08, 2018 11:47:00
viiv
[uquote="vovik15",url="/forum/viewtopic.php?p=3302525#p3302525"]Вопрос в следующем, как этот кусок кода оформить в виде сишной функции, и скормить компилятору?[/uquote]
Если все-таки надо, то:
A) Ассемблерные вставки в с-файлы (гуглить по ключевым словам "avr gcc inline assembler")
Б) Вставить Ваш ассемблерный код в проект (отдкльным файлом). И вызывать как обычно. Чем не устраивает?
Код: Выделить всё
.text
.global WsOut
.type WsOut, @function
WsOut:
.....
ret
Код: Выделить всё
extern void WsOut (void);
int f (void)
{
...
WsOut ();
...
return 0;
}
Re: Ассемблерная вставка Avr Studio 5 GCC
Добавлено: Пт фев 09, 2018 00:50:26
vovik15
Спасибо,интересный вариант,я обязательно попробую так сделать. Подскажите,если я всталю свой ассемблерных код во внешний файл,как можно будет передавать в него параметры?
Re: Ассемблерная вставка Avr Studio 5 GCC
Добавлено: Пт фев 09, 2018 08:36:41
viiv
[uquote="vovik15",url="/forum/viewtopic.php?p=3304489#p3304489"]Подскажите,если я всталю свой ассемблерных код во внешний файл,как можно будет передавать в него параметры?[/uquote]
Гуглить по словам "
AVR GCC calling conventions" (соглашения о передачe параметров).
Второй метод (не отменяет ознакомления с соглашениями о передачe параметров)
Код: Выделить всё
#include <avr/io.h>
void my_asm (unsigned char var)
{
DDRA=var;
}
Пример, естественно, "синтетический", главное чтобы был понятен принцип. Компилируем в ассемблер (с ключиком -S)
Получаем ассемблерный файл
Код: Выделить всё
.text
.global my_asm
.type my_asm, @function
my_asm:
out 0x1a,r24
ret
1) Видим, что параметр передается в R24.
2) Можно поправить ассемблерный файл как необходимо и вставить его в проект. Объявть my_asm как внешнюю и вызывать еe:
Код: Выделить всё
extern void my_asm (unsigned char val);
void do_something (...)
{
...
my_asm (0x35);
...
}
Re: Ассемблерная вставка Avr Studio 5 GCC
Добавлено: Пт фев 09, 2018 11:09:53
Dimon456
viiv писал(а):1) Видим, что параметр передается в R24.
2) Можно поправить ассемблерный файл как необходимо и вставить его в проект. Объявть my_asm как внешнюю и вызывать еe:
Зачем что то править, пусть рабочий пример берет и в путь, к примеру не плохой примерчик
Спойлер
Код: Выделить всё
void putch(char ch) {
__asm__ __volatile__ (
" com %[ch]\n" // ones complement, carry set
" sec\n"
"1: brcc 2f\n"
" cbi %[uartPort],%[uartBit]\n"
" rjmp 3f\n"
"2: sbi %[uartPort],%[uartBit]\n"
" nop\n"
"3: rcall uartDelay\n"
" rcall uartDelay\n"
" lsr %[ch]\n"
" dec %[bitcnt]\n"
" brne 1b\n"
:
:
[bitcnt] "d" (10),
[ch] "r" (ch),
[uartPort] "I" (_SFR_IO_ADDR(UART_PORT)),
[uartBit] "I" (UART_TX_BIT)
:
"r25"
);
}
Re: Ассемблерная вставка Avr Studio 5 GCC
Добавлено: Пт фев 09, 2018 12:33:07
viiv
[uquote="Dimon456",url="/forum/viewtopic.php?p=3304693#p3304693"]Зачем что то править, пусть рабочий пример берет и в путь, к примеру не плохой примерчик[/uquote]
Зачем что то, править, если можно править что-то другое?
В этом посте разговор был не про inline assembler, а про "обычный". В своем первом ответе я описал что есть два подхода (обычный vs inline). Для каждого случая надо решать, что лучше. Более того, иногда полезно их использовать вместе, например, inline assembler используется в качестве "обертки" при вызове чисто ассемблерных подпрограмм.
В качестве "отправной" точки для asm-исходника иногда бывает полезно получить этот asm-файл из си-файла, а затем, например, nop-ами добится нужного результата.
ЗЫ
Чтбы править Ваш пример, надо хотя бы "по диагонали"прочитать
avr gcc inline assembler - "птичий язык"
Код: Выделить всё
[bitcnt] "d" (10),
[ch] "r" (ch),
[uartPort] "I" (_SFR_IO_ADDR(UART_PORT)),
[uartBit] "I" (UART_TX_BIT)
:
"r25"
на мой взгляд, интуитивно не совсем понятен (скорее, совсем не понятен)

Re: Ассемблерная вставка Avr Studio 5 GCC
Добавлено: Пт фев 09, 2018 16:45:54
Dimon456
viiv писал(а):на мой взгляд, интуитивно не совсем понятен (скорее, совсем не понятен)
Чего не понятно то?
Спойлер
Код: Выделить всё
#include <avr/io.h>
extern void WsOut(char ch)
{
__asm__ __volatile__ (
" ldi r25,0 \n"
"2: subi r25,255 \n"
" cpi r25,8 \n"
" breq 4f \n"
" sbrs %[ch],0 \n"
" rjmp 3f \n"
" sbi %[u_Port],0 \n"
" nop\n" "nop\n" "nop \n"
" cbi %[u_Port],0 \n"
" nop\n" "nop\n" "nop \n"
" nop\n" "nop\n" "nop \n"
" rjmp 1f \n"
"3: sbi %[u_Port],0 \n"
" nop\n" "nop\n" "nop \n"
" nop\n" "nop\n" "nop \n"
" nop\n" "nop\n" "nop \n"
" cbi %[u_Port],0 \n"
"1: lsr %[ch] \n"
" rjmp 2b \n"
"4: \n"
:
:
[ch] "r" (ch),
[u_Port]"I" (_SFR_IO_ADDR(PORTB))
);
}
int main (void)
{
DDRB=0xff;
PORTB = 0x00;
WsOut (0x64);
WsOut (0x55);
while (1)
{
}
}
192 бата занимает.Обратите внимание, после метки 4: нет команды ret, компилятор сам ее добавит.
Так как протокол WS2812 я не читал, не сложно доработать,
если не туда сдвигает биты то поменять
команду lsr на lsl и соответственно
sbrs %[ch],0 на sbrs %[ch],7
ну и там с nop-ами разобраться, я не вникал в протокол.
В команде sbi %[u_Port],0 0 - это 0 пин порта PORTB, и соответственно cbi %[u_Port],0
Я сам этот "птичий язык" не знаю.
Re: Ассемблерная вставка Avr Studio 5 GCC
Добавлено: Пт фев 09, 2018 17:03:14
viiv
[uquote="Dimon456",url="/forum/viewtopic.php?p=3304981#p3304981"]Я сам этот "птичий язык" не знаю.[/uquote]
Так я же и советую почитать. Если бы почитали, то узнали бы, что, например, компилятору неплохо бы сообщить, что Ваш asm volatile код портит R25. Без этого возможны интересные "танцы с бубном" во время отладки.
Re: Ассемблерная вставка Avr Studio 5 GCC
Добавлено: Пт фев 09, 2018 17:59:30
Dimon456
viiv писал(а):[uquote="Dimon456",url="/forum/viewtopic.php?p=3304981#p3304981"]Я сам этот "птичий язык" не знаю.[/uquote]
Так я же и советую почитать. Если бы почитали, то узнали бы, что, например, компилятору неплохо бы сообщить, что Ваш asm volatile код портит R25. Без этого возможны интересные "танцы с бубном" во время отладки.
Какой вы неугомонный.
А если так
Спойлер
Код: Выделить всё
extern void WsOut(char ch)
{
__asm__ __volatile__ (
" sec \n"
"1: brcc 2f \n"
" sbi %[u_Port],0 \n"
" nop\n" "nop\n" "nop \n"
" cbi %[u_Port],0 \n"
" nop\n" "nop\n" "nop \n"
" nop\n" "nop\n" "nop \n"
" rjmp 3f\n"
"2: sbi %[u_Port],0 \n"
" nop\n" "nop\n" "nop \n"
" nop\n" "nop\n" "nop \n"
" nop\n" "nop\n" "nop \n"
" cbi %[u_Port],0 \n"
"3: lsr %[ch] \n"
" dec %[bitcnt] \n"
" brne 1b \n"
:
:
[bitcnt] "d" (8),
[ch] "r" (ch),
[u_Port]"I" (_SFR_IO_ADDR(PORTB))
);
}