[an error occurred while processing this directive]
трудности с компилятором WINAVR
(«Телесистемы»: Конференция «Микроконтроллеры и их применение»)

миниатюрный аудио-видеорекордер mAVR

Отправлено goracio888 14 ноября 2006 г. 00:11

Шесть лет пишу ассемблере для AVR. Решил перейти на С, надеясь ускорить процесс написания, отладки и сопровождения. Купил книгу "Программирование на языке С для AVR и PIC микроконтроллеров". К ней прилагался диск с инсталлятором WINAVR. Поскольку версия программы 2004 года, то поддержки tiny2313 там не было. Качнул WINAVR 2006 года. Первое что сделал переписал на С таймер, ваял две недели - иначе не научишся. Поскольку ассемблер примерно знаю, есть возможность анализировать то что строит компилятор. Наткнулся на одну непонятную заморочку. Сразу хочу сказать, что компилятор не виню, вероятно чего-то не знаю. В общем схема такова. В функции анализа состояния клавиатуры в цикле while реализовано ожидание отжатия клавиш. Т.е. анализируется переменные shift_plus,r_key и shift_minus, которые меняют свои значение в обработчике прерывания таймера Т0.

void parser_md(void)
{
while (!(((r_key & 0x01) == 0x01)||(shift_minus == 0)||(shift_plus == 0))) {}
}

Пока не выполнится это условие, цикл будет крутится. Но процессор зависает в этом цикле. Анализ ассемблерного кода показывает, что в цикле анализируется не переменная, а ее копия один раз считанная из ОЗУ.

188: 90 91 6a 00 lds r25, 0x006A
18c: 80 91 6b 00 lds r24, 0x006B
190: 98 23 and r25, r24
192: 80 91 7f 00 lds r24, 0x007F
196: 98 23 and r25, r24
198: 9f 3f cpi r25, 0xFF ; 255
19a: f1 f7 brne .-4 ; 0x198

cpi сравнивает r25 с 0xff .

А выход таков. Если в теле цикла обратится к функции, которая модифицирует глобальные переменные (а может и локальные), тогда компилятор cменяет гнев на милость (тупость на интеллект) и в цикле уже используется чтение переменной из ОЗУ.

Добавим функцию tupak, предварительно объявив переменную tup

void tupak(void)
{
tup++;
tup--;
}

И вставим ее в выше рассмотренный цикл

void parser_md(void)
{
while (!(((r_key & 0x01) == 0x01)||(shift_minus == 0)||(shift_plus == 0)))
tupak;
}

Компилятор сгенерировал следующий код

188: 80 91 6a 00 lds r24, 0x006A
18c: 90 91 6b 00 lds r25, 0x006B
190: 89 23 and r24, r25
192: 90 91 7f 00 lds r25, 0x007F
196: 89 23 and r24, r25
198: 8f 3f cpi r24, 0xFF ; 255
19a: 11 f0 breq .+4 ; 0x1a0
19c: d7 df rcall .-82 ; 0x14c
19e: f4 cf rjmp .-24 ; 0x188

Вместо банального чтения из регистров присутствует обращение к ячейкам ОЗУ, так сказать к первоисточникам. Я не думаю, что степень оптимизации компиллера позволяет ему генерировать кривой код. Добавление volatile к описанию переменных не помагает. Попытка размещения переменной в регистре в этой версии кажется упразднено. Наверное надо возвращаться на *.asm.

В институте семь раз читал книгу по Фортрану под редакцией Ющенко (не автор, а ... президент), а здесь пялюсь в англоязычные тексты как избиратель в телевизор. Хоть бы кто кратенько перевел на русский язык, я бы о нем стихи написал на весь Советский Союз.
С уважением Игорь Пешляев gora888@rambler.ru

Составить ответ  |||  Конференция  |||  Архив

Ответы


Отправка ответа
Имя (обязательно): 
Пароль: 
E-mail: 

Тема (обязательно):
Сообщение:

Ссылка на URL: 
URL изображения: 


Rambler's Top100 Рейтинг@Mail.ru
Перейти к списку ответов  |||  Конференция  |||  Архив  |||  Главная страница  |||  Содержание