Ассемблерная вставка Avr Studio 5 GCC

Обсуждаем контроллеры компании Atmel.
Ответить
Опытный кот
Сообщения: 768
Зарегистрирован: Сб ноя 08, 2008 18:32:36

Сообщение 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; возвращаемся в подпрограмму вывода данных



Реализацию самих световых эффектов хочу сделать на си, так как это проще и лучше. Вопрос в следующем, как этот кусок кода оформить в виде сишной функции, и скормить компилятору? Поиск в гугле явных ответов не дал,вопросов стало только еще больше. Огромное спасибо за понимание
Контактная информация:
Реклама
ARV
Ум, честь и совесть. И скромность.
Аватара пользователя
Сообщения: 18678
Зарегистрирован: Чт дек 28, 2006 08:19:56
Откуда: Новочеркасск

Сообщение ARV »

Сделайте, как я - задействуйте аппаратный SPI, и не мучайтесь с ассемблером! При 16 МГц тактовой работает отлично!

Добавлено after 51 second:
Кстати, со дня на день опубликуется моя статья (на Паяльнике) - там и исходники на Си прилагаются, и кое-какие эффекты...
если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...

Мой уютный бложик... заходите!
Контактная информация:
Реклама
Опытный кот
Сообщения: 768
Зарегистрирован: Сб ноя 08, 2008 18:32:36

Сообщение vovik15 »

Несколько лет назад вы мне микросхемы посылкой в Тамбов выслали :) ещё раз вам за это спасибо!

Добавлено after 55 minutes 44 seconds:
Все дело в том,что эта лента будет использоваться в сложном проекте,и аппаратный spi уже занят
Контактная информация:
ARV
Ум, честь и совесть. И скромность.
Аватара пользователя
Сообщения: 18678
Зарегистрирован: Чт дек 28, 2006 08:19:56
Откуда: Новочеркасск

Сообщение ARV »

vovik15 писал(а):Все дело в том,что эта лента будет использоваться в сложном проекте,и аппаратный spi уже занят
если проект на самом деле сложный, то разумнее будет для иных целей сделать программный SPI, а аппаратный под WS-ки выделить, иначе это будет геморрой, а не проект.

кстати, чем занят SPI? в моём проекте, который сейчас на модерации на Паяльнике, аппаратный SPI использован и под WS2812 и для работы с SD-картой.
если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...

Мой уютный бложик... заходите!
Контактная информация:
Реклама
Эиком - электронные компоненты и радиодетали
Опытный кот
Сообщения: 768
Зарегистрирован: Сб ноя 08, 2008 18:32:36

Сообщение vovik15 »

Он занят передачей данных на драйвер мах7221. Ну впринципе его можно и программно обрабатывать без проблем. А как досрочно посмотреть вашу статью?

Добавлено after 1 minute 32 seconds:
Я если честно не совсем понимаю как вам удалось реализовать строгие тайминги на аппаратном spi

Добавлено after 38 minutes 10 seconds:
Почитал,принцип понятен,главное правильно биты на линию выставлять,жаль что я не подумал об этом раньше
Контактная информация:
Реклама
ARV
Ум, честь и совесть. И скромность.
Аватара пользователя
Сообщения: 18678
Зарегистрирован: Чт дек 28, 2006 08:19:56
Откуда: Новочеркасск

Сообщение ARV »

если хотите ассемблерную вставку, то найдите и скачайте "библиотеку" neopixel (кажется так называется) для ардуино. во всяком случае любой проект с WS-ками на ардуино применяет эту библиотеку - там исходник на GCC, и вывод как раз на ассемблере с жесткой привязкой NOP-ами к тактам... можно и посмотреть, как оформлено, да и слизнуть код можно.

или наберитесь терпения и дождитесь публикации моего проекта - там полные исходники всего, включая работу с WS2812b через аппаратный SPI. по условиям публикации на Паяльнике я досрочно ничего не могу показывать...
если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...

Мой уютный бложик... заходите!
Контактная информация:
Реклама
Грызет канифоль
Сообщения: 289
Зарегистрирован: Чт ноя 06, 2014 13:09:06

Сообщение 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;
}
Опытный кот
Сообщения: 768
Зарегистрирован: Сб ноя 08, 2008 18:32:36

Сообщение vovik15 »

Спасибо,интересный вариант,я обязательно попробую так сделать. Подскажите,если я всталю свой ассемблерных код во внешний файл,как можно будет передавать в него параметры?
Контактная информация:
Грызет канифоль
Сообщения: 289
Зарегистрирован: Чт ноя 06, 2014 13:09:06

Сообщение 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)

Код: Выделить всё

avr-gcc -mmcu=atmega16 -Os -S my-asm.c
Получаем ассемблерный файл

Код: Выделить всё

        .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);
...
}
Мудрый кот
Сообщения: 1849
Зарегистрирован: Вс дек 25, 2016 08:34:54

Сообщение 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"
  );
}
Грызет канифоль
Сообщения: 289
Зарегистрирован: Чт ноя 06, 2014 13:09:06

Сообщение 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"
на мой взгляд, интуитивно не совсем понятен (скорее, совсем не понятен) :-)
Мудрый кот
Сообщения: 1849
Зарегистрирован: Вс дек 25, 2016 08:34: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

Я сам этот "птичий язык" не знаю.
Грызет канифоль
Сообщения: 289
Зарегистрирован: Чт ноя 06, 2014 13:09:06

Сообщение viiv »

[uquote="Dimon456",url="/forum/viewtopic.php?p=3304981#p3304981"]Я сам этот "птичий язык" не знаю.[/uquote]
Так я же и советую почитать. Если бы почитали, то узнали бы, что, например, компилятору неплохо бы сообщить, что Ваш asm volatile код портит R25. Без этого возможны интересные "танцы с бубном" во время отладки.
Мудрый кот
Сообщения: 1849
Зарегистрирован: Вс дек 25, 2016 08:34:54

Сообщение 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))
 );  
     	
}
Ответить

Вернуться в «AVR»