реклама на сайте
подробности

 
 
> gcc для AVR, слишком большой код
609
сообщение Oct 5 2010, 06:41
Сообщение #1





Группа: Новичок
Сообщений: 7
Регистрация: 10-08-10
Пользователь №: 58 849



Здравствуйте. Я программирую на языке C для микроконтроллеров AVR при помощи компилятора gcc. Нашел такую интересную особенность. В приведенном ниже коде программа занимает место порядка 200 байт. Если раскомментировать закомментированную строку с объявлением функции delay_ms, программа резко полнеет до 350 байт. Никак не могу разобраться, почему. Не могли бы вы мне помочь. Упорное чтение Кернигана и Ричи не помогает. Куда гуглить просто не знаю. Заранее спасибо за ответ.

Код
#define WDR        asm("wdr")
//void delay_ms(int time);

void main(void)
{
    delay_ms(1);
    delay_ms(1);
}


void delay_ms(int time)
{
    volatile int Timer, Timer1;

    for (Timer=0; Timer<time; Timer++)
        for (Timer1=0; Timer1<51; Timer1++)
            WDR;
}



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

Код
-Wall
-gdwarf-2
-Os
-std=gnu99
-funsigned-char
-funsigned-bitfields
-fpack-struct
-fshort-enums
Go to the top of the page
 
+Quote Post
2 страниц V   1 2 >  
Start new topic
Ответов (1 - 14)
777777
сообщение Oct 5 2010, 06:56
Сообщение #2


Профессионал
*****

Группа: Участник
Сообщений: 1 091
Регистрация: 25-07-07
Из: Саратов
Пользователь №: 29 357



Цитата(609 @ Oct 5 2010, 10:41) *
Здравствуйте. Я программирую на языке C для микроконтроллеров AVR при помощи компилятора gcc. Нашел такую интересную особенность. В приведенном ниже коде программа занимает место порядка 200 байт. Если раскомментировать закомментированную строку с объявлением функции delay_ms, программа резко полнеет до 350 байт. Никак не могу разобраться, почему. Не могли бы вы мне помочь. Упорное чтение Кернигана и Ричи не помогает. Куда гуглить просто не знаю.

А какой варнинг он выдает когда строка закомментирована?
Go to the top of the page
 
+Quote Post
609
сообщение Oct 5 2010, 06:59
Сообщение #3





Группа: Новичок
Сообщений: 7
Регистрация: 10-08-10
Пользователь №: 58 849



Цитата(777777 @ Oct 5 2010, 10:56) *
А какой варнинг он выдает когда строка закомментирована?

Build succeeded with 0 Warnings...
Go to the top of the page
 
+Quote Post
777777
сообщение Oct 5 2010, 07:08
Сообщение #4


Профессионал
*****

Группа: Участник
Сообщений: 1 091
Регистрация: 25-07-07
Из: Саратов
Пользователь №: 29 357



Цитата(609 @ Oct 5 2010, 10:59) *
Build succeeded with 0 Warnings...

Стало жутко интересно. Сделал проект и получил 230 байт в обоих случаях, только при закомментированном прототипе выдаются варнинги:

implicit declaration of function 'delay_ms'
conflicting types of function 'delay_ms'

С этим, надеюсь, понятно? При неявном использовании функции они считается возвращающей int, а когда компилятор дошел до ее определения, она оказалась void
Go to the top of the page
 
+Quote Post
609
сообщение Oct 5 2010, 07:24
Сообщение #5





Группа: Новичок
Сообщений: 7
Регистрация: 10-08-10
Пользователь №: 58 849



Компилирую при помощи WinAVR-20081205, прикрученном к AVR Studio 4.16.

Цитата
При неявном использовании функции они считается возвращающей int, а когда компилятор дошел до ее определения, она оказалась void


Про это я читал. Пробовал вместо void ставить int, но ситуация не меняется.

Если точно, то с закомментированной строчкой получается 220 байт, а если я ее раскомментирую, то 364. Не могли бы Вы сказать, какой конкретно версией gcc пользуетесь.
Go to the top of the page
 
+Quote Post
777777
сообщение Oct 5 2010, 07:30
Сообщение #6


Профессионал
*****

Группа: Участник
Сообщений: 1 091
Регистрация: 25-07-07
Из: Саратов
Пользователь №: 29 357



Цитата(609 @ Oct 5 2010, 11:24) *
Компилирую при помощи WinAVR-20081205, прикрученном к AVR Studio 4.16.

Про это я читал. Пробовал вместо void ставить int, но ситуация не меняется.

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


4.18 b700 WinAVR 20100110
Еще имеет значение чип, я выбрал ATmega168
Go to the top of the page
 
+Quote Post
dimka76
сообщение Oct 5 2010, 07:53
Сообщение #7


developer
****

Группа: Свой
Сообщений: 902
Регистрация: 12-04-06
Из: Казань
Пользователь №: 16 032



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

Вот еще один путь снижения объема кода

Код
void delay_ms(int time)
{
    int Timer1 = 51;

    while(time--)
       while(Timer1--)
           WDR;
}


Здесь переменная Timer вообще не нужна.
Операция сравнения с нулем выполняется быстрее, чем с каким-либо другим числом.


--------------------
Все может быть и быть все может, и лишь того не может быть-чего уж точно быть не может, хотя..и это может быть.
Go to the top of the page
 
+Quote Post
MrYuran
сообщение Oct 5 2010, 08:14
Сообщение #8


Беспросветный оптимист
******

Группа: Свой
Сообщений: 4 640
Регистрация: 26-12-07
Из: Н.Новгород
Пользователь №: 33 646



Цитата(dimka76 @ Oct 5 2010, 11:53) *
Код
void delay_ms(int time)
{
    int Timer1 = 51;

    while(time--)
       while(Timer1--)
           WDR;
}

Не знаю как себя поведёт avr-gcc, но в аннотации к mspgcc про такую конструкцию написано, что при удачном стечении обстоятельств ждать будем вечно...


--------------------
Программирование делится на системное и бессистемное. ©Моё :)
— а для кого-то БГ — это Bill Gilbert =)
Go to the top of the page
 
+Quote Post
609
сообщение Oct 5 2010, 08:26
Сообщение #9





Группа: Новичок
Сообщений: 7
Регистрация: 10-08-10
Пользователь №: 58 849



Цитата(777777 @ Oct 5 2010, 11:30) *
4.18 b700 WinAVR 20100110
Еще имеет значение чип, я выбрал ATmega168

Спасибо! Завтра попробую скачать эту версию, посмотрю что получится.




Цитата(dimka76 @ Oct 5 2010, 11:53) *
Не понятно для чего вы используете volatile для локальной переменной. Если без volatile, то тогда компилятор скорее всего разместит ее в регистре.


Если не использовать volatile, то компилятор может оптимизировать задержку, т.е. просто выполнить конечный результат функции.

Цитата(dimka76 @ Oct 5 2010, 11:53) *
Вот еще один путь снижения объема кода


Вопрос не в том как сделать код задержки меньше, а почему при объявлении функции код увеличивается?
Go to the top of the page
 
+Quote Post
MrYuran
сообщение Oct 5 2010, 08:35
Сообщение #10


Беспросветный оптимист
******

Группа: Свой
Сообщений: 4 640
Регистрация: 26-12-07
Из: Н.Новгород
Пользователь №: 33 646



Цитата(609 @ Oct 5 2010, 12:26) *
Вопрос не в том как сделать код задержки меньше, а почему при объявлении функции код увеличивается?

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


--------------------
Программирование делится на системное и бессистемное. ©Моё :)
— а для кого-то БГ — это Bill Gilbert =)
Go to the top of the page
 
+Quote Post
Сергей Борщ
сообщение Oct 5 2010, 10:23
Сообщение #11


Гуру
******

Группа: Модераторы
Сообщений: 8 455
Регистрация: 15-05-06
Из: Рига, Латвия
Пользователь №: 17 095



Цитата(609 @ Oct 5 2010, 11:26) *
Если не использовать volatile, то компилятор может оптимизировать задержку, т.е. просто выполнить конечный результат функции.
А если напишете #define WDR asm volatile ("wdr"), то не сможет.


--------------------
На любой вопрос даю любой ответ
"Write code that is guaranteed to work, not code that doesn’t seem to break" (C++ FAQ)
Go to the top of the page
 
+Quote Post
dimka76
сообщение Oct 5 2010, 10:39
Сообщение #12


developer
****

Группа: Свой
Сообщений: 902
Регистрация: 12-04-06
Из: Казань
Пользователь №: 16 032



Цитата(MrYuran @ Oct 5 2010, 12:14) *
Не знаю как себя поведёт avr-gcc, но в аннотации к mspgcc про такую конструкцию написано, что при удачном стечении обстоятельств ждать будем вечно...


А там случайно эти обстоятельства не конкретизируются?


--------------------
Все может быть и быть все может, и лишь того не может быть-чего уж точно быть не может, хотя..и это может быть.
Go to the top of the page
 
+Quote Post
zhevak
сообщение Oct 5 2010, 10:50
Сообщение #13


Знающий
****

Группа: Свой
Сообщений: 723
Регистрация: 29-08-05
Из: Березовский
Пользователь №: 8 065



Цитата(609 @ Oct 5 2010, 14:26) *
Вопрос не в том как сделать код задержки меньше, а почему при объявлении функции код увеличивается?

Смею предположить, что оптимизирующий компилятор в одном случае может вставлять вызов функции, а в другом -- осуществлять in-line подстановку тела этой функции в месте ее вызова. Попробуйте отключить оптимизацию и, как абсолютно правильно сказал MrYuran, посмотрите листинги. Вы не только ответите на свой вопрос, но и существенно придвинетесь в сторону профи.


--------------------
Хочешь рассмешить Бога -- расскажи ему о своих планах!
Go to the top of the page
 
+Quote Post
MrYuran
сообщение Oct 5 2010, 11:10
Сообщение #14


Беспросветный оптимист
******

Группа: Свой
Сообщений: 4 640
Регистрация: 26-12-07
Из: Н.Новгород
Пользователь №: 33 646



Цитата(dimka76 @ Oct 5 2010, 14:39) *
А там случайно эти обстоятельства не конкретизируются?


Цитата
18. If you execute
while ((long) a & 0x80000l);
the program will hang, unless ’a’ is declared volatile. So, do it!


Цитата
19. Delay loops are very sophisticated routines. Normally, users do something like:
int i = 1234;
while (i--);
or
int i;
for (i = 0; i < 1234; i++);
NEITHER WILL WORK AS YOU EXPECT when optimisation is switched on!!! The optimizer will detect
dead code in both examples and will eliminate it. It might even eliminate the loop completely. Adding the
volatile attribute to the definition of ’i’ might help, but don’t count on it if ’i’ is a local variable. The
compiler can still detect the calculations are wasteful, and eliminate them.
Regardless of these optimisation issues, this type of delay loop is poor programming style - you have no
idea how long or short a delay it might produce (although there is an obvious minimum bound!). It would be
better, and more reliable to define something like:
static void __inline__ brief_pause(register unsigned int n)
{
__asm__ __volatile__ (
"1: \n"
" dec %[n] \n"
" jne 1b \n"
: [n] "+r"(n));
}
and call this routine where needed. This is simple, compact, and predictable.

Хотя, я пробовал - иногда прокатывало...
Но тут уж как повезёт.

Основной смысл последней цитаты - задержку лучше определить самому (с точностью до такта), чем отдавать на откуп компилятору


--------------------
Программирование делится на системное и бессистемное. ©Моё :)
— а для кого-то БГ — это Bill Gilbert =)
Go to the top of the page
 
+Quote Post
Dx!
сообщение Oct 5 2010, 20:58
Сообщение #15


Частый гость
**

Группа: Участник
Сообщений: 108
Регистрация: 6-02-09
Из: Новочеркасск
Пользователь №: 44 469



А чем макросы _delay_ms() и _delay_us() что идут с WinAVR плохи?
Go to the top of the page
 
+Quote Post

2 страниц V   1 2 >
Reply to this topicStart new topic
2 чел. читают эту тему (гостей: 2, скрытых пользователей: 0)
Пользователей: 0

 


RSS Текстовая версия Сейчас: 23rd July 2025 - 00:00
Рейтинг@Mail.ru


Страница сгенерированна за 0.01709 секунд с 7
ELECTRONIX ©2004-2016