Ассемблер (ASM) для AVR в вопросах и ответах

Обсуждаем контроллеры компании Atmel.
Ответить
Вымогатель припоя
Сообщения: 680
Зарегистрирован: Ср фев 24, 2010 19:16:07

Сообщение ВитГо »

pyzhman писал(а):Пишем диплом? "Отверженных"? "Войну и мир"? Не думаю. А стало быть даем краткие и понятные имена. В том числе константам.
НЕ СМЕШНО, имена констант взял с головы чтобы вам головы не убивать

но если желаете то пожалуйста, вот не из головы

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

				# конфигурируем пины порта С
					MOV32	R0	, GPIOC+GPIO_CRH
					MOV		R1	, (GPIO_CRH_MODE8 + GPIO_CRH_CNF8_0 + GPIO_CRH_MODE9 + GPIO_CRH_CNF9_1 + GPIO_CRH_MODE10 + GPIO_CRH_CNF10_0 + GPIO_CRH_MODE11 + GPIO_CRH_CNF11_0 + GPIO_CRH_MODE12 + GPIO_CRH_CNF12_0 )

					STR		R1	, [R0]

p.s. есть кто нить кто писал на gnu gcc на ассемблере или знает как в нем можно переносить параметры команды на следующую строку ?

еще раз повторюсь, хотелось бы получить примерно следующее:

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

		MOV		R1	, (GPIO_CRH_MODE8 + GPIO_CRH_CNF8_0 +
                                          GPIO_CRH_MODE9 + GPIO_CRH_CNF9_1 + 
                                          GPIO_CRH_MODE10 + GPIO_CRH_CNF10_0 + 
                                          GPIO_CRH_MODE11 + GPIO_CRH_CNF11_0 +
                                          GPIO_CRH_MODE12 + GPIO_CRH_CNF12_0 )
Реклама
Поставщик валерьянки для Кота
Аватара пользователя
Сообщения: 1900
Зарегистрирован: Сб фев 21, 2009 13:11:40
Откуда: Москва

Сообщение ibiza11 »

насколько я понял у вас идет настройка портов ввода/вывода. так сделайте одну конфигурацию через ".equ" в начале файла, назовите ее коротким именем, а потом уже используйте ее для загрузки в регистр. например

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

.equ P_8 (GPIO_CRH_MODE8 | GPIO_CRH_CNF8_0)
.equ P_9 (GPIO_CRH_MODE9 | GPIO_CRH_CNF9_1)
.equ P_10 (GPIO_CRH_MODE10 | GPIO_CRH_CNF10_0)
.equ P_11 (GPIO_CRH_MODE11 | GPIO_CRH_CNF11_0)
.equ P_12 (GPIO_CRH_MODE12 | GPIO_CRH_CNF12_0)
.equ P_ALL (P_8 | P_9 | P_10 | P_11 | P_12)
....
MOV R0, P_ALL
Ставим плюсы: )
Реклама
Друг Кота
Аватара пользователя
Сообщения: 7016
Зарегистрирован: Вс июл 12, 2009 19:15:29
Откуда: Ижевск

Сообщение pyzhman »

2ibiza11: товарища интересует
как в нем можно переносить параметры команды на следующую строку ?
:)
Docendo discimus
Контактная информация:
Поставщик валерьянки для Кота
Аватара пользователя
Сообщения: 1900
Зарегистрирован: Сб фев 21, 2009 13:11:40
Откуда: Москва

Сообщение ibiza11 »

Если вопрос принципиальный, то я не знаю ответ. А если вопрос был вызван необходимостью избавить исходник от нечитабельных фрагментов, то, пожалуй, мой пост может помочь топикстартеру.
Ставим плюсы: )
Реклама
Эиком - электронные компоненты и радиодетали
Вымогатель припоя
Сообщения: 680
Зарегистрирован: Ср фев 24, 2010 19:16:07

Сообщение ВитГо »

ibiza11 писал(а):насколько я понял у вас идет настройка портов ввода/вывода. так сделайте одну конфигурацию через ".equ" в начале файла, назовите ее коротким именем, а потом уже используйте ее для загрузки в регистр.
о! хороший выход, по крайней мере простой и читаемость исходника сохранит! спасибо!
Реклама
Друг Кота
Сообщения: 4550
Зарегистрирован: Чт май 05, 2011 21:26:34
Откуда: Украина, Славутич

Сообщение Alexeyslav »

И еще вынести его в отдельный инклуд... константы эти все.
Контактная информация:
Реклама
Вымогатель припоя
Сообщения: 680
Зарегистрирован: Ср фев 24, 2010 19:16:07

Сообщение ВитГо »

Alexeyslav писал(а):И еще вынести его в отдельный инклуд... константы эти все.
да, так и сделал, получился замечательный конфигуратор периферии

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

@ правильный способ выбора сумма из двух параметров: режим + частота
@
@ на выходе получаем два параметра PORTx_CRH, PORTx_CRL - для конфигурации порта x
@
@ +- пин на выход ----------------------------------------------------------+
@ |       																	|
@ | режим:      															|
@ |	GPIO_MODE_OUT_PP	= Вывод порта push-pull								|
@ |	GPIO_MODE_OUT_OD	= Вывод порта OD									|
@ | GPIO_MODE_AF_PP		= Альтернативная функция порта, режим push-pull		|
@ |	GPIO_MODE_AF_OD		= Альтернативная функция порта, режим OD			|
@ |																			|
@ |	доступные частоты тактирования при работе порта на выход:				|
@ |	GPIO_CRx_MODE_50M = 50MHz												|
@ |	GPIO_CRx_MODE_10M = 10MHz												|
@ |	GPIO_CRx_MODE_2M  = 2MHz												|
@ +-------------------------------------------------------------------------+
@
@ +- пин на вход -----------------------------------------------------------+
@ |       																	|
@ | режим:      															|
@ |	GPIO_MODE_AIN 	      =  АЦП											|
@ |	GPIO_MODE_IN_FLOATING = Hi-Z											|
@ |	GPIO_MODE_IPDU		  = Подтяжка вниз/задать одновременно бит порта =0	|
@ |																			|
@ |	в режиме входа задать в качестве частоты тактирования:					|
@ |	GPIO_CRx_MODE_IN  = режим "Вход"										|
@ +-------------------------------------------------------------------------+
@
.include "st32f100rbt6b.s"	@ файл описания для микроконтроллера
@
@ +--------------------+
@ |       ПОРТ А       |
@ +--------------------+
@
 .equ	PORTA_P0	, (GPIO_CRx_MODE_IN + GPIO_MODE_IPDU)<<GPIO_PORTx_BIT0
 .equ	PORTA_P1	, (GPIO_CRx_MODE_IN + GPIO_MODE_IPDU)<<GPIO_PORTx_BIT1
 .equ	PORTA_P2	, (GPIO_CRx_MODE_IN + GPIO_MODE_IPDU)<<GPIO_PORTx_BIT2
 .equ	PORTA_P3	, (GPIO_CRx_MODE_IN + GPIO_MODE_IPDU)<<GPIO_PORTx_BIT3
 .equ	PORTA_P4	, (GPIO_CRx_MODE_IN + GPIO_MODE_IPDU)<<GPIO_PORTx_BIT4
 .equ	PORTA_P5	, (GPIO_CRx_MODE_IN + GPIO_MODE_IPDU)<<GPIO_PORTx_BIT5
 .equ	PORTA_P6	, (GPIO_CRx_MODE_IN + GPIO_MODE_IPDU)<<GPIO_PORTx_BIT6
 .equ	PORTA_P7	, (GPIO_CRx_MODE_IN + GPIO_MODE_IPDU)<<GPIO_PORTx_BIT7

 .equ	PORTA_P8	, (GPIO_CRx_MODE_50M + GPIO_MODE_OUT_OD)<<GPIO_PORTx_BIT8
 .equ	PORTA_P9	, (GPIO_CRx_MODE_50M + GPIO_MODE_OUT_OD)<<GPIO_PORTx_BIT9
 .equ	PORTA_P10	, (GPIO_CRx_MODE_50M + GPIO_MODE_OUT_OD)<<GPIO_PORTx_BIT10
 .equ	PORTA_P11	, (GPIO_CRx_MODE_50M + GPIO_MODE_OUT_OD)<<GPIO_PORTx_BIT11
 .equ	PORTA_P12	, (GPIO_CRx_MODE_50M + GPIO_MODE_OUT_OD)<<GPIO_PORTx_BIT12
 .equ	PORTA_P13	, (GPIO_CRx_MODE_50M + GPIO_MODE_OUT_OD)<<GPIO_PORTx_BIT13
 .equ	PORTA_P14	, (GPIO_CRx_MODE_50M + GPIO_MODE_OUT_OD)<<GPIO_PORTx_BIT14
 .equ	PORTA_P15	, (GPIO_CRx_MODE_50M + GPIO_MODE_OUT_OD)<<GPIO_PORTx_BIT15

@ значение для регистра GPIOA_CRL
 .equ	PORTA_CRL   , PORTA_P0+PORTA_P1+PORTA_P2+PORTA_P3+PORTA_P4+PORTA_P5+PORTA_P6+PORTA_P7

@ значение для регистра GPIOA_CRH
 .equ	PORTA_CRH   , PORTA_P8+PORTA_P9+PORTA_P10+PORTA_P11+PORTA_P12+PORTA_P13+PORTA_P14+PORTA_P15
@
ну и в принципе так же для других портов

спасибо всем участвовавшим, особенно ibiza11, сам я до этого чтото не додумался

если кто "попадет" в stm32 на асме - обращайтесь, с удовольствием поделюсь тем что наработал (по асму инфы в инете и на форумах очень мало к сожалению), да и доки после AVR не такими уж и прозрачными кажутся
Поставщик валерьянки для Кота
Аватара пользователя
Сообщения: 1900
Зарегистрирован: Сб фев 21, 2009 13:11:40
Откуда: Москва

Сообщение ibiza11 »

Всегда пожалуйста) обращайтесь)))
Ставим плюсы: )
Опытный кот
Аватара пользователя
Сообщения: 785
Зарегистрирован: Сб фев 27, 2010 21:45:37
Откуда: Ростов-на-Дону

Сообщение Coolish »

Здравствуйте.

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

ISR(TIMER0_OVF_vect)
{

push r1
push r0
in r0, 0x3f ; 63
push r0
eor r1, r1
PORTA |= 0x02;
sbi 0x1b, 1 ; 27
state = 0;
sts 0x055C, r1
}
pop r0
out 0x3f, r0 ; 63
pop r0
pop r1
reti


и второй:


ISR(TIMER0_COMP_vect)
{

push r1
push r0
in r0, 0x3f ; 63
push r0
eor r1, r1
PORTA &= ~0x02;
cbi 0x1b, 1 ; 27
}
pop r0
out 0x3f, r0 ; 63
pop r0
pop r1
reti


Это листинг кода, который скомпилировал avr-gcc. Жирным выделен исходный сишный код.

Да, обработчики должны работать именно так, аппаратный вывод таймера использовать невозможно.

Можно ли не сохранять в стеке SREG (т.е. меняется ли он при этих операциях?), и надо ли сохранять и очищать r1, который, насколько я знаю, всегда в AVR-GCC равен нулю?

Во втором случае, вообще не вижу причины, зачем компилятор стал работать с r1.
Сделать хотел грозу, а получил КоЗу
Контактная информация:
Модератор
Аватара пользователя
Сообщения: 13490
Зарегистрирован: Ср ноя 26, 2008 16:34:25
Откуда: Тамбовская обл.

Сообщение ploop »

Можно ли не сохранять в стеке SREG (т.е. меняется ли он при этих операциях?)
Сохранять обязательно. Меняется тут при всех операциях, кроме push/pop, in/out
и надо ли сохранять и очищать r1, который, насколько я знаю, всегда в AVR-GCC равен нулю?
Не может быть он всегда равен нулю, т.к. используется, например, в операциях аппаратного умножения (MULxx)
Во втором случае, вообще не вижу причины, зачем компилятор стал работать с r1.
Да, в принципе он там не нужен. А больше оптимизировать нечего. Вручную на ассемблере код получится такой-же.
Опытный кот
Аватара пользователя
Сообщения: 785
Зарегистрирован: Сб фев 27, 2010 21:45:37
Откуда: Ростов-на-Дону

Сообщение Coolish »

ploop, спасибо. Я читал, что r1 всегда держится в нуле, а после операций с ним компилятор его опять обнуляет. Но это обработчик прерывания, и надеяться на обнуление нельзя.

Правильно ли будет вот так, например?

ISR(TIMER0_OVF_vect)
{

push r1
push r0
in r0, 0x3f ; SREG
push r0
eor r1, r1
PORTA |= 0x02;
sbi 0x1b, 1 ; PORTA
state = 0;
sts 0x055C, r1
}
pop r0
out 0x3f, r0 ; SREG
pop r0
pop r1
reti


ISR(TIMER0_COMP_vect)
{

push r1
push r0
in r0, 0x3f ; SREG
push r0
eor r1, r1
PORTA &= ~0x02;
cbi 0x1b, 1 ; PORTA
}
pop r0
out 0x3f, r0 ; SREG
pop r0
pop r1
reti

Или можно ещё проще?
Сделать хотел грозу, а получил КоЗу
Контактная информация:
Модератор
Аватара пользователя
Сообщения: 13490
Зарегистрирован: Ср ноя 26, 2008 16:34:25
Откуда: Тамбовская обл.

Сообщение ploop »

А, вы же там один бит устанавливаете, тогда например так:

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

TIMER0_OVF_vect:
push r0
in r0,SREG
push r0

cbi PORTA,1
clr r0 <<< только эта зараза меняет SREG. Иначе было бы на 6 команд меньше
sts 0x055C, r0

pop r0
out SREG,r0
pop r0
reti
Друг Кота
Аватара пользователя
Сообщения: 3872
Зарегистрирован: Пт янв 29, 2010 10:27:40
Откуда: Москва

Сообщение Engineer_Keen »

Во второй подпрограмме можно вообще оставить только

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

cbi 0x1b, 1 ; PORTA
cbi/sbi SREG не меняют
Модератор
Аватара пользователя
Сообщения: 13490
Зарегистрирован: Ср ноя 26, 2008 16:34:25
Откуда: Тамбовская обл.

Сообщение ploop »

Да, во втором векторе можно оставить одну команду - CBI. Она не изменяет флагов.

И еще фишка - при написании на ассемблере её можно вообще в таблицу векторов засунуть, вместо условного перехода на вектор, сэкономится 4 или 6 тактов

---
Опередили..
Поставщик валерьянки для Кота
Сообщения: 1995
Зарегистрирован: Ср май 11, 2011 21:37:45
Откуда: Цветочный город

Сообщение Мастер Ломастер »

Coolish писал(а):Помогите, пожалуйста, оптимизировать эти обработчики прерывания по максимуму.
по-максимуму - это ассемблерная вставка:

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

ISR(TIMER0_OVF_vect, ISR_NACKED){
   volatile asm(
      "push r0"        "\n"
      "clr  r0"        "\n"
      "sbi  0x1b, 1"   "\n"
      "sts  0x55, r0"  "\n"
      "pop  r0"        "\n"
      "reti"
   );
}
сохранять SREG не обязательно: вы не меняете своими операциями флаги состояния
битва с дураками проиграна, победители торжествуют. слава победителям!
Контактная информация:
Модератор
Аватара пользователя
Сообщения: 13490
Зарегистрирован: Ср ноя 26, 2008 16:34:25
Откуда: Тамбовская обл.

Сообщение ploop »

CLR меняет. Смотрите мой пост (код) на той странице.
Опытный кот
Аватара пользователя
Сообщения: 785
Зарегистрирован: Сб фев 27, 2010 21:45:37
Откуда: Ростов-на-Дону

Сообщение Coolish »

ploop, Engineer_Keen, спасибо!

Компилирую на avr-gcc. Ассемблерный вопрос возник только на этих двух обработчиках.
насчёт вектора не совсем понял. Имеется в виду, что во втором обработчике, который короткий, вместо jmp туда можно разместить команды cbi и reti ?
Сделать хотел грозу, а получил КоЗу
Контактная информация:
Поставщик валерьянки для Кота
Сообщения: 1995
Зарегистрирован: Ср май 11, 2011 21:37:45
Откуда: Цветочный город

Сообщение Мастер Ломастер »

ploop писал(а):CLR меняет. Смотрите мой пост (код) на той странице.
да, пардон, поспешил, можно так:

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

ISR(TIMER0_OVF_vect, ISR_NACKED){   
   volatile asm(
      "push r20"       "\n"
      "ldi  r20, 0"    "\n"
      "sbi  0x1b, 1"   "\n"
      "sts  0x55, r20" "\n"
      "pop  r20"       "\n"
      "reti"   
   );
}
битва с дураками проиграна, победители торжествуют. слава победителям!
Контактная информация:
Друг Кота
Аватара пользователя
Сообщения: 3872
Зарегистрирован: Пт янв 29, 2010 10:27:40
Откуда: Москва

Сообщение Engineer_Keen »

Coolish писал(а):насчёт вектора не совсем понял. Имеется в виду, что во втором обработчике, который короткий, вместо jmp туда можно разместить команды cbi и reti ?
Если вместо JMP, то можно, если векторы "однословные" (флеш <=8К, переходы по RJMP), то только если следующий вектор не используется.

Мастер Ломастер Опередил, как раз хотел вариант с LDI выложить :)))
Модератор
Аватара пользователя
Сообщения: 13490
Зарегистрирован: Ср ноя 26, 2008 16:34:25
Откуда: Тамбовская обл.

Сообщение ploop »

насчёт вектора не совсем понял. Имеется в виду, что во втором обработчике, который короткий, вместо jmp туда можно разместить команды cbi и reti ?
Вы на Си пишите, там таблица векторов прерываний автоматом формируется. На ассемблере она делается вручную, напротив каждого вектора ставится команда условного перехода (если надо), или просто nop (или reti) если вектора нет.
Так вот, переход - такая же команда, и вместо него можно засунуть ваше CBI. Правда в следующем векторе должен быть RETI.
Короче не парьтесь, к вопросу это не относится.

А второй обработчик вам надо сделать так:

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

ISR(TIMER0_OVF_vect, ISR_NACKED){  
Ivolatile asm(
      "sbi  что_там_у_вас, 1"   "\n"
      "reti"
   );
} 
Ответить

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