Перейти к содержанию
    

Как переписать для IAR

static inline void ws2812_send_single_byte(uint8_t byte)
{
	for(uint8_t mask = 0x80; mask != 0; mask >>= 1) {
		if(byte & mask) {
			__asm__ __volatile__("sbi %0, %1 \n\t"
					     "nop \n\t"
					     "nop \n\t"
					     "nop \n\t"
					     "nop \n\t"
					     "nop \n\t"
					     "cbi %0, %1 \n\t"
					     :
					     : "i" (PORT_LED), "i" (PIN_LED)
					     :
					);
		} else {
			__asm__ __volatile__("sbi %0, %1 \n\t"
					     "nop \n\t"
					     "cbi %0, %1 \n\t"
					     "nop \n\t"
					     "nop \n\t"
					     :
					     : "i" (PORT_LED), "i" (PIN_LED)
					     :
					);
		}
	}
}

попробовал  так:

asm("sbi PORT_LED,PIN_LED"); 
			asm("nop");
			asm("cbi PORT_LED,PIN_LED");		     
			asm("nop");		     
			asm("nop");

ругается:

Цитата

 Unknown symbol in inline assembly: "PORT_LED"  
 

Я пытался объяснить:

#define PIN_LED PB0
#define PORT_LED PORTB

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

3 minutes ago, muravei said:

Я пытался объяснить:

OFF: Вопрос: зачем для современного компилятора писать на ассемблере без крайней на то необходимости? У IAR очень хороший оптимизатор для ARM. Возможно, что то же самое и для AVR.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

5 минут назад, haker_fox сказал:

без крайней на то необходимости?

Так как раз тот случай.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

19 минут назад, muravei сказал:
__asm__ __volatile__("sbi %0, %1 \n\t"
					     "nop \n\t"
					     "nop \n\t"
					     "nop \n\t"
					     "nop \n\t"
					     "nop \n\t"
					     "cbi %0, %1 \n\t"
					     :
					     : "i" (PORT_LED), "i" (PIN_LED)
					     :
					);

Этот вариант не компилируется для AVR? Вроде бы у них для ARMовского компилятора такой синтаксис документирован и должен работать.

PS: Попытки засунуть дефайны из C в инлайн-ассемблер могут сработать только с помощью конкатенации строк и макроса типа STRINGIFY, чтобы при передачи в транслятор ассемблера уже были подставлены макросы портов и т.п. элементов ассемблерного кода.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

14 минут назад, makc сказал:
__asm__ __volatile__

Если заменить на "asm", то не нравится :

 

15 минут назад, makc сказал:
 :
					     : "i" (PORT_LED), "i" (PIN_LED)
					     :

Если прямо вписать адрес и бит , то мой вариант проходит.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

7 часов назад, makc сказал:

Вроде бы у них для ARMовского компилятора такой синтаксис документирован и должен работать.

Для IAR ARM всё ок:

#define PORT_LED 29
void ws2812_send_single_byte(uint byte)
{
  asm("MOVS R0, %0\n" : : "i"(PORT_LED) : "cc");
}

Нормально компилится даже старым IAR_v7.80.4

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

7 часов назад, muravei сказал:

Если заменить на "asm", то не нравится :

Откройте документацию на компилятор. Да-да, на компилятор ИАР. Там про встроенный ассемблер буквально пара страниц и в конце резюме - не используйте встраиваемый ассемблер ни для чего сложнее NOP или разрешения/запрета прерываний. То есть ответ на заголовок темы: никак это невозможно переписать на встроенный ассемблер ИАРа для AVR. Для ИАРа надо всю функцию писать на настоящем ассемблере.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

1 час назад, muravei сказал:

Ну низя, так низя.

Дело не в "нельзя". Никто за вас разбираться, что у вас там глючит не будет. И телепатов тут нет, которые угадают - что скрывается за вашими PB0 и PORTB:

В 09.02.2023 в 14:27, muravei сказал:

Я пытался объяснить:

#define PIN_LED PB0
#define PORT_LED PORTB

И во что они разворачиваются.

Я выше приводил работоспособный пример. В котором макрос PORT_LED нормально разворачивается в литеральную константу. Которая далее нормально компилится. И в вашем компиляторе должен также разворачиваться. Так как препроцессор есть в любом си-компиляторе и работает по общим правилам. Но похоже вы его даже не попробовали.  :unknw:

Кроме того, IAR for ARM например в свойствах проекта имеет опцию "Preprocessor output to file". При её включении можно посмотреть - что получилось на выходе препроцессора, перед собственно компиляцией файла. Увидеть результаты макроподстановки. Вполне возможно IAR for AVR тоже имеет аналогичный ключ.

Компилим мой пример с включённым ключом "Preprocessor output to file". И в соответствующем .i-файле видим:

void ws2812_send_single_byte(uint byte)
{
  asm("MOVS R0, %0\n" : : "i"(29) : "cc");
}

Макроподстановка выполнена успешно. Далее asm() будет обработан компилятором.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

3 часа назад, jcxz сказал:

И в вашем компиляторе должен также разворачиваться.

Не должен. Не умеет IAR для AVR передавать во встроенный ассемблер параметры. Вот это вот все он не умеет:

3 часа назад, jcxz сказал:
 : : "i"(29) : "cc"

И поэтому не может ни передать byte внутрь асма ни отследить, какие регистры были испорчены. Соответственно весь дальнейший код может работать как угодно.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

2 часа назад, Сергей Борщ сказал:

Не умеет IAR для AVR передавать во встроенный ассемблер параметры

Как это "не умеет"? А тут:

В 09.02.2023 в 14:07, muravei сказал:
В 09.02.2023 в 13:49, makc сказал:
 :
					     : "i" (PORT_LED), "i" (PIN_LED)
					     :

Если прямо вписать адрес и бит , то мой вариант проходит

ТС вроде как пишет, что можно вписать адрес и бит явно. Я понял - литеральными константами вместо PORT_LED и PIN_LED. И будет компилироваться.

Или о чём он тут?... написано невразумительно...

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

6 часов назад, jcxz сказал:

Как это "не умеет"?

Вот так. Не умеет согласно документации:

image.thumb.png.6ca7dd35acb986399e1056b9752a32d2.png

6 часов назад, jcxz сказал:

Или о чём он тут?.

Это код, который надо было перенести с gcc на IAR.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

А почему нельзя так (примерно)

byte |= mask
nop()
....
byte &= ~mask

Компилятор должен сам догадаться.

При передаче в функцию адреса регистра ввода-вывода могут быть особенности из-за различных адресных пространств. В документации GCC-AVR об этом написано, в IAR думаю тоже должно быть, вроде были модификаторы типов под адреса-порты, с которыми работают битовые инструкции.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.

Гость
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...