Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: avr-gcc и IAR
Форум разработчиков электроники ELECTRONIX.ru > Микроконтроллеры (MCs) > Cредства разработки для МК > GNU/OpenSource средства разработки
Страницы: 1, 2
zhevak
(Предыстория. Можно пропустить.)
Я чуть боле двух лет как перебрался на Линукс. Оставил в покое Венду и Вендовые компиляторы. Все хорошо, полет более чем нормальный. Не сочтите за рекламу! Сижу в Ubuntu (и Debian). Просто после Венды мне показалось, что Ubuntu легче освоить, чем другие Линуксы типа Gentoo и Slackware. Тем более столько народа в ней сидит. И тем более, что средства для разработки программ для AVR уже лежат готовые в репозиториях. В общем, живу и в ус не дую.

Но меня давно подмывало произвести ревизию бинарного кода, который компилится avr-gcc, и сравнить его с IAR-овским кодом. Но все как-то не получалось сделать. То проект был не большой (типа "хелловорлд" в исполнении светодиодов), и поэтому полноценного сравнения не могло получиться. То проект наоборот был большой, и не хватало времени на его портацию в другую среду. А то проект коммерческий -- типа нельзя публиковать. В общем, все как-то не стыковалось с моими чаяниями.

И вот, внезапно выпало счастье заняться небольшим "не засекреченным" проектом. Я его начинал создавать на Mega48. Но в какой-то момент, по мере его роста не хватило флеши, пришлось перебираться на Mega8. Бывает. Не проблема! Переписал. Все легко поднялось и заработало. И на второе счастье у меня оказались свободными выходные (уже прошедшие). Чем я и воспользовался.

Откопал старый винт с установленной Вендой и IAR-ом, подцепил к компу.. и на до же! Оказывается я все еще помню, как в Венде тыкать мышкой! Короче, перенес проект под IAR, скомпилировал и поразился.


(А вот теперь по делу.)
Понятно, что поскольку компиляторы разные, они и должны создавать разный по объему код. Если размер кода (бинарник) чуть-чуть превышает 4КБ, то, как вы думаете, какая разница будет в объеме сгенерированных компиляторами кодов?

Я ожидал получить разницу в размере кода ну 100, ну 200 байт. А получил аж 1200 байт. Солидный кусок! Так сильно gcc меня еще не опускал. Обидно, да-а?

Конечно, на мое впечатление еще оказал воздействие тот факт, что если бы я изначально писал под IAR-ом, то мне бы не пришлось по ходу менять проц. Но ведь сам выбрал Линух и gcc!

Но это все эмоции. Мне же интересно было разобраться с состоянием дел вообще. Сначала я засел за оптимизацию. Начал перебирать различные комбинации ключей в надежде как можно более сильно сократить код и под gcc, и под IAR-ом. Да. Мне это удалось сделать. Код немного ужался и там, и там, но все равно разница в килобайт с хвостиком сохранилась: один компайлер генерит код размером в 2596 байт, другой -- 3772 байта. Я оцениваю размер кода по hex-файлу, который непосредственно заливается во флешь. Т.е. здесь вообще без дураков, которых можно обмануть не посчитав, допустим, размер таблицы векторов. Или опустив размер вспомогательных (ну или как их правильно-то назвать?) функций, который компилятор сам может создавать, увидев повторяющиеся участки кода.


(Вопрос.)
Коллеги, не впадая в безумие священных войн, вы можете помочь установить истину в работе компиляторов -- почему они дают такой существенно разный результат? Возможно что-то я не правильно делаю. (А это обязательно так!) Но мне, да и многим из вас, хотелось бы знать -- в каком отношении по объему друг к другу эти компиляторы "готовят" код.

Полный код проекта я могу предоставить. Единственная просьба -- по возможно соблюдать одинаковость исходных кодов в обоих версиях (для gcc и для IAR).

Ну, например, в gcc я есть команда для запрета прерываний cli(), и в IAR-е она тоже есть -- __disable_inerrupt(). Это все легко соблюсти. Сложнее соблюсти, допустим, программные задержки. В библиотеке gcc есть функции _delay_us() и _delay_ms(), а в IAR-е таковых нет. Но по жизни очень часто бывает так, что эти в программе без задержек никак. Поэтому я допускаю, что в исходниках для IAR-а, будут использованы приемы типа
Код
#define FCLK (11059200)
#define delay_ms(n)  __delay_cycles((FCLK / 1000) * (n));
#define delay_us(n)  __delay_cycles((FCLK / 1000000) * (n));


Есть еще одно замечание. Исходный текст написан не очень правильно с точки зрения профи. Пока его улучшать не надо! Я поясню. Дело в том, что этот проект не коммерческий, и этот девайс не предполагается кому-то продавать. Кроме того, передо мной стаояла задача: достаточно тупо слепить устройство и установить его в работу, не доводя его до витринного блеска. Поэтому, например, вместо того, чтобы работать с функциями строк из флеша (avr/pgmspace.h), я их тупо прописываю в printf() и не парюсь, что при этом в Оперативе создается их копия. Просто пока не до этого!

В общем, давайте _пока_ не будем трогать исходники. Ибо я хочу посмотреть на возможности компиляторов для среднестатистического быдлокодера, который пишет проги вот на таком вот уровне. А когда мы совместными усилиями получим какие-то цифры, для сравнения компиляторов, вот тогда уже можно будет отрываться и пытаться уникальными для конкретного компилятора приемами уменьшить объем кода.

Не думайте, что я пытаюсь вашими руками написать свой проект! Проект уже работает и приносит определенную пользу. Дальнейшее улучшение проекта пойдет не по направлению уменьшения кода или вылизыванию в нем ошибок, а по направлению увеличения функциональности (насыщенности). Но даже и это пока не нужно. У меня другая задача -- разобраться с компиляторами.


Надеюсь, вы понимаете меня, и топик не съедет в бессмысленный срач.

Пожалуйста, задавайте ваши вопросы.
_Pasha
Может быть, может быть...
Код выложите-то?
dimka76
Для корректного сравнения компиляторов не надо пользоваться библиотечными функциями, а у вас есть printf и из-за него сравнение будет не корректным, т.к. будет зависить от степени корявости этих библиотек, а не от особенности компилятора.
MrYuran
Цитата
Понятно, что поскольку компиляторы разные, они и должны создавать разный по объему код. Если размер кода (бинарник) чуть-чуть превышает 4КБ, то, как вы думете, какая разница в объеме сгенерированных компиляторами кодов может оказаться?

За AVR не скажу, но в MSPGCC получал при оптимизации -Os разницу примерно 16к->19к, 25к->29к ну или около этого, в пользу IAR.
Специально ничего не оптимизировал, поскольку потолок флеша 60к пока достаточно высоко...
zhevak
Цитата(_Pasha @ Feb 21 2011, 16:32) *
Может быть, может быть...
Код выложите-то?

Да, конечно и с удовольсивием!
Если я приаттачу к своим постам заархивированные (.tar.bz2) файлы -- это нормально будет? Вендузятники смогут разарзивировать?
neiver
IAR и GCC оба хорошие компиляторы, у каждого свои сильные и слабые стороны. ИМХО примерно так:
Сильные стороны IAR:
- устранение общих подвыражений;
- тщательная заточка под целевую архитектуру:
- - оптимальное использование режимов адресации,
- - максимально полное использование набора комманд процессора.

Сильные стороны GCC (по сравнению с IAR):
- продуманное встраивание функций;
- оптимизация циклов;
- оптимизация обращений к памяти;
- часто обходится меньшим числом регистров.

Вобщем, по-разноу, для одного исходника IAR генерирует более компактный код, для другого GCC.
zhevak
Исходники проектов выложил. Движок форума файлы .tar.bz2 не принял. Пришлось zip-овать.

Цитата(dimka76 @ Feb 21 2011, 16:44) *
Для корректного сравнения компиляторов не надо пользоваться библиотечными функциями, а у вас есть printf и из-за него сравнение будет не корректным, т.к. будет зависить от степени корявости этих библиотек, а не от особенности компилятора.

Ночью уж попробовал. Для простоты, не взирая на то, что проект станет нерабочим, закомментировал все printf-ы (они только в файле app.c ). Объем кода уменьшился, но колоссальная разница осталась. sad.gif Понятно, что printf() много съедает, и дешевле обойтись itoa() и строковыми функциями.

Цитата(neiver)
Вобщем, по-разноу, для одного исходника IAR генерирует более компактный код, для другого GCC.

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

Версии компиляторов:
[console]
alex@zhevak:~$ avr-gcc --version
avr-gcc (GCC) 4.3.5
[/console]

IAR v.5.11B
MrYuran
Цитата(zhevak @ Feb 21 2011, 14:46) *
Вендузятники смогут разарзивировать?

Смогут, 7zip в помощь!
demiurg_spb
Глянул Ваш Makefile - там можно сказать для хорошей оптимизации по объёму сделано далеко не всё.
Сейчас нет времени, но вечерком может попробую ваши исходники сбилдить по моим рецептам:-)
О результатах отпишусь.
zhevak
В проекте имеется файл hal.c (абстрагирование от аппаратного уровня), в котором определены функции обработчики двух прерываний -- от таймера и от UART-а.

CODE
// Прерываение случается каждую миллисекунду
ISR (USART_RXC_vect)
{
uint8_t data;
uint8_t status;

status = UCSRA;
data = UDR;
if ((status & (_BV(FE) | _BV(DOR) | _BV(PE))) == 0) // (FRAMING_ERROR | PARITY_ERROR | DATA_OVERRUN)) == 0)
{
// Байт принят без апаратных ошибок
_pack = data;
postmessage((msg_t) MSG_PACK); // Тоби пакет!
}
else
postmessage((msg_t) MSG_BADPACK); // Пакет принят с ошибкой
}


// Прерываение случается каждые 10 миллисекунд
ISR (TIMER2_COMP_vect)
{
static uint8_t _timer_200ms;
static uint8_t _key_prevstate;

uint8_t key_currstate;

// Таймер 200 мс
if (++_timer_200ms >= 20)
{
_timer_200ms = 0;
postmessage(MSG_TIMER200MS);
}

// Отработка таймеров
if (_timer_buzzer != 0)
if (--_timer_buzzer == 0)
BUZZER_OFF;

if (_timer_led0 != 0)
if (--_timer_led0 == 0)
LED0_OFF;

if (_timer_led1 != 0)
if (--_timer_led1 == 0)
LED1_OFF;

if (_timer_led2 != 0)
if (--_timer_led2 == 0)
LED2_OFF;

if (_timer_led3 != 0)
if (--_timer_led3 == 0)
LED3_OFF;

// проверка нажатия кнопки

if ((PINC & _BV(KEY)) == 0)
key_currstate = 1; // Кнопка нажата
else
key_currstate = 0; // Кнопка отпущена

if ((key_currstate == 1) && (_key_prevstate == 0))
postmessage(MSG_KEY);
_key_prevstate = key_currstate;
}



Вот как это сделал gcc:
CODE
00000130 <__vector_3>:
130: 1f 92 push r1
132: 0f 92 push r0
134: 0f b6 in r0, 0x3f; 63
136: 0f 92 push r0
138: 11 24 eor r1, r1
13a: 2f 93 push r18
13c: 3f 93 push r19
13e: 4f 93 push r20
140: 5f 93 push r21
142: 6f 93 push r22
144: 7f 93 push r23
146: 8f 93 push r24
148: 9f 93 push r25
14a: af 93 push r26
14c: bf 93 push r27
14e: ef 93 push r30
150: ff 93 push r31
152: 80 91 d3 00 lds r24, 0x00D3
156: 8f 5f subi r24, 0xFF; 255
158: 80 93 d3 00 sts 0x00D3, r24
15c: 84 31 cpi r24, 0x14; 20
15e: 20 f0 brcs .+8 ; 0x168 <__vector_3+0x38>
160: 10 92 d3 00 sts 0x00D3, r1
164: 84 e0 ldi r24, 0x04; 4
166: c8 df rcall .-112; 0xf8 <postmessage>
168: 80 91 e0 00 lds r24, 0x00E0
16c: 88 23 and r24, r24
16e: 51 f0 breq .+20 ; 0x184 <__vector_3+0x54>
170: 80 91 e0 00 lds r24, 0x00E0
174: 81 50 subi r24, 0x01; 1
176: 80 93 e0 00 sts 0x00E0, r24
17a: 80 91 e0 00 lds r24, 0x00E0
17e: 88 23 and r24, r24
180: 09 f4 brne .+2 ; 0x184 <__vector_3+0x54>
182: ad 98 cbi 0x15, 5; 21
184: 80 91 de 00 lds r24, 0x00DE
188: 88 23 and r24, r24
18a: 51 f0 breq .+20 ; 0x1a0 <__vector_3+0x70>
18c: 80 91 de 00 lds r24, 0x00DE
190: 81 50 subi r24, 0x01; 1
192: 80 93 de 00 sts 0x00DE, r24
196: 80 91 de 00 lds r24, 0x00DE
19a: 88 23 and r24, r24
19c: 09 f4 brne .+2 ; 0x1a0 <__vector_3+0x70>
19e: a8 98 cbi 0x15, 0; 21
1a0: 80 91 df 00 lds r24, 0x00DF
1a4: 88 23 and r24, r24
1a6: 51 f0 breq .+20 ; 0x1bc <__vector_3+0x8c>
1a8: 80 91 df 00 lds r24, 0x00DF
1ac: 81 50 subi r24, 0x01; 1
1ae: 80 93 df 00 sts 0x00DF, r24
1b2: 80 91 df 00 lds r24, 0x00DF
1b6: 88 23 and r24, r24
1b8: 09 f4 brne .+2 ; 0x1bc <__vector_3+0x8c>
1ba: a9 98 cbi 0x15, 1; 21
1bc: 80 91 e3 00 lds r24, 0x00E3
1c0: 88 23 and r24, r24
1c2: 51 f0 breq .+20 ; 0x1d8 <__vector_3+0xa8>
1c4: 80 91 e3 00 lds r24, 0x00E3
1c8: 81 50 subi r24, 0x01; 1
1ca: 80 93 e3 00 sts 0x00E3, r24
1ce: 80 91 e3 00 lds r24, 0x00E3
1d2: 88 23 and r24, r24
1d4: 09 f4 brne .+2 ; 0x1d8 <__vector_3+0xa8>
1d6: aa 98 cbi 0x15, 2; 21
1d8: 80 91 e1 00 lds r24, 0x00E1
1dc: 88 23 and r24, r24
1de: 51 f0 breq .+20 ; 0x1f4 <__vector_3+0xc4>
1e0: 80 91 e1 00 lds r24, 0x00E1
1e4: 81 50 subi r24, 0x01; 1
1e6: 80 93 e1 00 sts 0x00E1, r24
1ea: 80 91 e1 00 lds r24, 0x00E1
1ee: 88 23 and r24, r24
1f0: 09 f4 brne .+2 ; 0x1f4 <__vector_3+0xc4>
1f2: ab 98 cbi 0x15, 3; 21
1f4: 9c 9b sbis 0x13, 4; 19
1f6: 02 c0 rjmp .+4 ; 0x1fc <__vector_3+0xcc>
1f8: 80 e0 ldi r24, 0x00; 0
1fa: 07 c0 rjmp .+14 ; 0x20a <__vector_3+0xda>
1fc: 80 91 d2 00 lds r24, 0x00D2
200: 88 23 and r24, r24
202: 11 f4 brne .+4 ; 0x208 <__vector_3+0xd8>
204: 81 e0 ldi r24, 0x01; 1
206: 78 df rcall .-272; 0xf8 <postmessage>
208: 81 e0 ldi r24, 0x01; 1
20a: 80 93 d2 00 sts 0x00D2, r24
20e: ff 91 pop r31
210: ef 91 pop r30
212: bf 91 pop r27
214: af 91 pop r26
216: 9f 91 pop r25
218: 8f 91 pop r24
21a: 7f 91 pop r23
21c: 6f 91 pop r22
21e: 5f 91 pop r21
220: 4f 91 pop r20
222: 3f 91 pop r19
224: 2f 91 pop r18
226: 0f 90 pop r0
228: 0f be out 0x3f, r0; 63
22a: 0f 90 pop r0
22c: 1f 90 pop r1
22e: 18 95 reti

00000230 <__vector_11>:
230: 1f 92 push r1
232: 0f 92 push r0
234: 0f b6 in r0, 0x3f; 63
236: 0f 92 push r0
238: 11 24 eor r1, r1
23a: 2f 93 push r18
23c: 3f 93 push r19
23e: 4f 93 push r20
240: 5f 93 push r21
242: 6f 93 push r22
244: 7f 93 push r23
246: 8f 93 push r24
248: 9f 93 push r25
24a: af 93 push r26
24c: bf 93 push r27
24e: ef 93 push r30
250: ff 93 push r31
252: 8b b1 in r24, 0x0b; 11
254: 9c b1 in r25, 0x0c; 12
256: 8c 71 andi r24, 0x1C; 28
258: 21 f4 brne .+8 ; 0x262 <__vector_11+0x32>
25a: 90 93 e2 00 sts 0x00E2, r25
25e: 82 e0 ldi r24, 0x02; 2
260: 01 c0 rjmp .+2 ; 0x264 <__vector_11+0x34>
262: 83 e0 ldi r24, 0x03; 3
264: 49 df rcall .-366; 0xf8 <postmessage>
266: ff 91 pop r31
268: ef 91 pop r30
26a: bf 91 pop r27
26c: af 91 pop r26
26e: 9f 91 pop r25
270: 8f 91 pop r24
272: 7f 91 pop r23
274: 6f 91 pop r22
276: 5f 91 pop r21
278: 4f 91 pop r20
27a: 3f 91 pop r19
27c: 2f 91 pop r18
27e: 0f 90 pop r0
280: 0f be out 0x3f, r0; 63
282: 0f 90 pop r0
284: 1f 90 pop r1
286: 18 95 reti



А вот так отработал IAR:
CODE
26 __interrupt void _usart_rxc_isr(void)

\ _usart_rxc_isr:

27 {

\ 00000000 .... RCALL ?Subroutine0

\ ??CrossCallReturnLabel_0:

\ 00000002 B78F IN R24, 0x3F

28 uint8_t data;

29 uint8_t status;

30

31 status = UCSRA;

\ 00000004 B10B IN R16, 0x0B

32 data = UDR;

\ 00000006 B11C IN R17, 0x0C

33 if ((status & (_BV(FE) | _BV(DOR) | _BV(PE))) == 0) // (FRAMING_ERROR | PARITY_ERROR | DATA_OVERRUN)) == 0)

\ 00000008 710C ANDI R16, 0x1C

\ 0000000A F421 BRNE ??_usart_rxc_isr_0

34 {

35 // Байт принят без апаратных ошибок

36 _pack = data;

\ 0000000C 9310.... STS _pack, R17

37 postmessage((msg_t) MSG_PACK); // Тоби пакет!

\ 00000010 E002 LDI R16, 2

\ 00000012 C001 RJMP ??_usart_rxc_isr_1

38 }

39 else

40 postmessage((msg_t) MSG_BADPACK); // Пакет принят с ошибкой

\ ??_usart_rxc_isr_0:

\ 00000014 E003 LDI R16, 3

\ ??_usart_rxc_isr_1:

\ 00000016 .... RCALL postmessage

41 }

\ 00000018 BF8F OUT 0x3F, R24

\ 0000001A .... RCALL ?Subroutine1

\ ??CrossCallReturnLabel_2:

\ 0000001C 9518 RETI

\ 0000001E REQUIRE _A_UCSRA

\ 0000001E REQUIRE _A_UDR



\ In segment CODE, align 2, keep-with-next

\ ?Subroutine1:

\ 00000000 9109 LD R16, Y+

\ 00000002 9119 LD R17, Y+

\ 00000004 9129 LD R18, Y+

\ 00000006 9139 LD R19, Y+

\ 00000008 9149 LD R20, Y+

\ 0000000A 9159 LD R21, Y+

\ 0000000C 9169 LD R22, Y+

\ 0000000E 9179 LD R23, Y+

\ 00000010 9009 LD R0, Y+

\ 00000012 9019 LD R1, Y+

\ 00000014 9029 LD R2, Y+

\ 00000016 9039 LD R3, Y+

\ 00000018 91E9 LD R30, Y+

\ 0000001A 91F9 LD R31, Y+

\ 0000001C 9189 LD R24, Y+

\ 0000001E 9508 RET



\ In segment CODE, align 2, keep-with-next

\ ?Subroutine0:

\ 00000000 938A ST -Y, R24

\ 00000002 93FA ST -Y, R31

\ 00000004 93EA ST -Y, R30

\ 00000006 923A ST -Y, R3

\ 00000008 922A ST -Y, R2

\ 0000000A 921A ST -Y, R1

\ 0000000C 920A ST -Y, R0

\ 0000000E 937A ST -Y, R23

\ 00000010 936A ST -Y, R22

\ 00000012 935A ST -Y, R21

\ 00000014 934A ST -Y, R20

\ 00000016 933A ST -Y, R19

\ 00000018 932A ST -Y, R18

\ 0000001A 931A ST -Y, R17

\ 0000001C 930A ST -Y, R16

\ 0000001E 9508 RET

42

43

44 // Прерываение случается каждые 10 миллисекунд

45 // ISR (TIMER2_COMP_vect)

46 #pragma vector = TIMER2_COMP_vect



\ In segment CODE, align 2, keep-with-next

47 __interrupt void _timer2_comp_isr(void)

\ _timer2_comp_isr:

48 {

\ 00000000 939A ST -Y, R25

\ 00000002 .... RCALL ?Subroutine0

\ ??CrossCallReturnLabel_1:

\ 00000004 B79F IN R25, 0x3F

49 static uint8_t _timer_200ms;

50 static uint8_t _key_prevstate;

51

52 uint8_t key_currstate;

53

54 // Таймер 200 мс

55 if (++_timer_200ms >= 20)

\ 00000006 .... LDI R30, LOW(_timer_led0)

\ 00000008 .... LDI R31, (_timer_led0) >> 8

\ 0000000A 8105 LDD R16, Z+5

\ 0000000C 9503 INC R16

\ 0000000E 8305 STD Z+5, R16

\ 00000010 3104 CPI R16, 20

\ 00000012 F020 BRCS ??_timer2_comp_isr_0

56 {

57 _timer_200ms = 0;

\ 00000014 E000 LDI R16, 0

\ 00000016 8305 STD Z+5, R16

58 postmessage(MSG_TIMER200MS);

\ 00000018 E004 LDI R16, 4

\ 0000001A .... RCALL postmessage

59 }

60

61 // Отработка таймеров

62 if (_timer_buzzer != 0)

\ ??_timer2_comp_isr_0:

\ 0000001C 9100.... LDS R16, (_timer_led0 + 4)

\ 00000020 2300 TST R16

\ 00000022 F039 BREQ ??_timer2_comp_isr_1

63 if (--_timer_buzzer == 0)

\ 00000024 9100.... LDS R16, (_timer_led0 + 4)

\ 00000028 950A DEC R16

\ 0000002A 9300.... STS (_timer_led0 + 4), R16

\ 0000002E F409 BRNE ??_timer2_comp_isr_1

64 BUZZER_OFF;

\ 00000030 98AD CBI 0x15, 0x05

65

66 if (_timer_led0 != 0)

\ ??_timer2_comp_isr_1:

\ 00000032 9100.... LDS R16, _timer_led0

\ 00000036 2300 TST R16

\ 00000038 F039 BREQ ??_timer2_comp_isr_2

67 if (--_timer_led0 == 0)

\ 0000003A 9100.... LDS R16, _timer_led0

\ 0000003E 950A DEC R16

\ 00000040 9300.... STS _timer_led0, R16

\ 00000044 F409 BRNE ??_timer2_comp_isr_2

68 LED0_OFF;

\ 00000046 98A8 CBI 0x15, 0x00

69

70 if (_timer_led1 != 0)

\ ??_timer2_comp_isr_2:

\ 00000048 9100.... LDS R16, (_timer_led0 + 1)

\ 0000004C 2300 TST R16

\ 0000004E F039 BREQ ??_timer2_comp_isr_3

71 if (--_timer_led1 == 0)

\ 00000050 9100.... LDS R16, (_timer_led0 + 1)

\ 00000054 950A DEC R16

\ 00000056 9300.... STS (_timer_led0 + 1), R16

\ 0000005A F409 BRNE ??_timer2_comp_isr_3

72 LED1_OFF;

\ 0000005C 98A9 CBI 0x15, 0x01

73

74 if (_timer_led2 != 0)

\ ??_timer2_comp_isr_3:

\ 0000005E 9100.... LDS R16, (_timer_led0 + 2)

\ 00000062 2300 TST R16

\ 00000064 F039 BREQ ??_timer2_comp_isr_4

75 if (--_timer_led2 == 0)

\ 00000066 9100.... LDS R16, (_timer_led0 + 2)

\ 0000006A 950A DEC R16

\ 0000006C 9300.... STS (_timer_led0 + 2), R16

\ 00000070 F409 BRNE ??_timer2_comp_isr_4

76 LED2_OFF;

\ 00000072 98AA CBI 0x15, 0x02

77

78 if (_timer_led3 != 0)

\ ??_timer2_comp_isr_4:

\ 00000074 9100.... LDS R16, (_timer_led0 + 3)

\ 00000078 2300 TST R16

\ 0000007A F039 BREQ ??_timer2_comp_isr_5

79 if (--_timer_led3 == 0)

\ 0000007C 9100.... LDS R16, (_timer_led0 + 3)

\ 00000080 950A DEC R16

\ 00000082 9300.... STS (_timer_led0 + 3), R16

\ 00000086 F409 BRNE ??_timer2_comp_isr_5

80 LED3_OFF;

\ 00000088 98AB CBI 0x15, 0x03

81

82 // проверка нажатия кнопки

83

84 if ((PINC & _BV(KEY)) == 0)

85 key_currstate = 1; // Кнопка нажата

\ ??_timer2_comp_isr_5:

\ 0000008A 999C SBIC 0x13, 0x04

\ 0000008C C002 RJMP ??_timer2_comp_isr_6

\ 0000008E E001 LDI R16, 1

\ 00000090 C001 RJMP ??_timer2_comp_isr_7

\ ??_timer2_comp_isr_6:

\ 00000092 E000 LDI R16, 0

\ ??_timer2_comp_isr_7:

\ 00000094 2F80 MOV R24, R16

86 else

87 key_currstate = 0; // Кнопка отпущена

88

89 if ((key_currstate == 1) && (_key_prevstate == 0))

\ 00000096 3001 CPI R16, 1

\ 00000098 F431 BRNE ??_timer2_comp_isr_8

\ 0000009A 9100.... LDS R16, (_timer_led0 + 6)

\ 0000009E 2300 TST R16

\ 000000A0 F411 BRNE ??_timer2_comp_isr_8

90 postmessage(MSG_KEY);

\ 000000A2 E001 LDI R16, 1

\ 000000A4 .... RCALL postmessage

91 _key_prevstate = key_currstate;

\ ??_timer2_comp_isr_8:

\ 000000A6 9380.... STS (_timer_led0 + 6), R24

92 }

\ 000000AA BF9F OUT 0x3F, R25

\ 000000AC .... RCALL ?Subroutine1

\ ??CrossCallReturnLabel_3:

\ 000000AE 9199 LD R25, Y+

\ 000000B0 9518 RETI

\ 000000B2 REQUIRE _A_PINC

\ 000000B2 REQUIRE _A_PORTC

93



Фейерическое растранжиривание памяти компилятором gcc видите?
Что-нибудь можно предпринять на уровне компилятора или для gcc это фатально?
neiver
Да, да. Это феерическое растранжирование памяти в обработчиках прерываний является следствием того, что в этих обработчиках вызываются функции из другой единици трансляции. Компилятор не знает какие регистры использует вызываемая функция и сохраняет в стеке все call-saved регистры на всякий случай. А у IAR это как раз сильная сторона - устранение общих подвыражений. Он выносит эти сохранения/восстановления регистров в отдельные функции. Решение для avr-gcc - не вызывать из обработчиков прерываний функции из других единиц трансляции(для IAR, кстати тоже полезно будет) или использовать inline функции.


Второй пожиратель ресурсов это как уже все догадались функция sprintf. В IAR проекте у вас используется минимальная урезанная версия, в gcc - полная с поддержкой float и чтения параметров из памяти программ.
zhevak
Цитата(demiurg_spb @ Feb 21 2011, 17:56) *
Глянул Ваш Makefile - там можно сказать для хорошей оптимизации по объёму сделано далеко не всё.
Сейчас нет времени, но вечерком может попробую ваши исходники сбилдить по моим рецептам:-)
О результатах отпишусь.

Я не помню в каком состоянии оставил Makefile. Я уже отчаялся, добиться от gcc чего-либо значимого, и тупо, просто тупо, как китаес, перебирал варианты. Потом плюнул на все и пошел спать. А сегодня решил обратиться к помощи зала sm.gif Да, и это... Makefile это рабочая лошадка, т.е. он постоянно у меня в движении находится. Ну, т.е. это не готовый к употреблению файл. Исходнные тексты я более-иене причесал, а Makefile -- as is.

И тем не менее, спасибо за коллаборацию! Жду результатов.

Плюс-минус 10-20 байтов особой погоды не делают. Мне хотелось бы скинуть хотя бы 500 байт. Я уж не говорю о килобайте! Но обязательно, я еще раз подчеркиваю, -- сохранить этот быдлокод с его библиотечными вызовами монструозных функций типа printf. Мне хотелось бы в результате нашего совместного поиска выработать какие-то предложения (или правила), как надо и как не надо кодить в gcc. Что допустимо, а что не допустимо в нем по сравнению с IAR.
MrYuran
Цитата
20e: ff 91 pop r31
210: ef 91 pop r30
212: bf 91 pop r27
214: af 91 pop r26
216: 9f 91 pop r25
218: 8f 91 pop r24
21a: 7f 91 pop r23
21c: 6f 91 pop r22
21e: 5f 91 pop r21
220: 4f 91 pop r20
222: 3f 91 pop r19
224: 2f 91 pop r18
226: 0f 90 pop r0
228: 0f be out 0x3f, r0; 63
22a: 0f 90 pop r0
22c: 1f 90 pop r1
22e: 18 95 reti

Эта жесть!
Копайте в сторону инлайнов

Все ваши hal-функции должны быть static inline
(извините, ваши исходники не смотрел, меня за свои скоро расстреляют)

/Блин, а я-то 4-кратный push/pop в прерываниях считал диким оверхедом/

Цитата(zhevak @ Feb 21 2011, 16:13) *
Извините, не знаю как подвернуть эти листинги-простыни. Наверняка же можно как-то cut-нуть. Подскажите, плиз!

тег CODEBOX.
Поправьте вручную или слева вверху есть пулл-даун "Спец.элементы"
neiver
Параметры линкера:
-Wl,-u,vfprintf -lprintf_min
для avr-gcc сразу дают минус 372 байта.
_Pasha
По приведенным фрагментам.
push/pop ld/st - что в лоб, что по лбу. А вот при сравнении модификации таймеров - гцц использует интенсивно LDS/STS а IAR чаще LDD/STD или LD/ST. Имхо, секрет фокуса как раз в том, что размер инструкции LDS/STS 2 слова и разница в размере от этого. Можно проверить - сравнив кол-во LDS/STS в листинге. Зуб даю, у иара их меньше в разы.
По поводу стиля исходников ничего не скажу, но понял одно - у меня давно нет проблем впихнуть невпихуемое и тянуться к иару из-за того, что многие подобные таймерам вопросы решаются совсем по-другому.
zhevak
Цитата(neiver @ Feb 21 2011, 18:27) *
Решение для avr-gcc - не вызывать из обработчиков прерываний функции из других единиц трансляции или использовать inline функции.

да. Хороша мысль. Но не сейчас, а для второй фазы, когда нужно будет оптимизировать код и писать рекомендации для пользователей gcc.

Цитата
Второй пожиратель ресурсов это как уже все догадались функция sprintf. В IAR проекте у вас используется минимальная урезанная версия, в gcc - полная с поддержкой float и чтения параметров из памяти программ.

Точно! И об этом я тоже как-то не додумался, не дошел! В IAR-е тип функций printf (и scanf) задается в Опциях проекта (General Options / Library Options) из выпадающих списков, а вот в опций для gnu-линковщика я не удосужился поискать. Былпа такая светлая мысль, поискать, но утонула среди других вопросов.
(В IAR-e у меня стоял Printf Formatter = Small)

Сейчас попробую нащупать подобную опцию в avr-ld...
Отбой! Пока я писал этот пост, уже опередили http://electronix.ru/forum/index.php?showt...st&p=888593

Откомпилировал с
Да, действительно скидывает 372 байта. Объем кода по avr-size -- 3400 байт (text), в бинарнике под заливку во флешь 0x0DBA байт (= 3514).
У IAR-а бинарник под заливку -- 0x0A32 байт (= 2610)

Все еще много лишних байт (почти 900) надо чем-то объяснять blink.gif
neiver
При использовании близких по функциональности версий стандартной библиотеки "normal DLIB" в IAR и -lprintf_min в avr-gcc (обе без поддержки float и еще какой-то фигни) размер кода почти сравнялся: IAR - 3614, avr-gcc - 3708 байт. Изначально в проекте IAR-а использовалясь жутко урезанная "CLIB" версия рантайма. В avr-gcc настолько порезанной несоответствующей стандартам, но тем не менее компактной библиотеки нет.
Так вот. А если функции вызываемые из прерываний сделать встраиваемыми, то будет, видимо, паритет.
zhevak
в ответ на http://electronix.ru/forum/index.php?showt...st&p=888594
Ну вот, посчитал количество команд (считал через $ grep -iw sts *.lst | wc -l и ее модификации для других мнемоник)

Код
command   gcc   IAR
-------   ---   ----
LDS       87    23
STS       86    25
LD        16    24
ST        26    33

05.gif и?
_Pasha
Цитата(zhevak @ Feb 21 2011, 17:40) *
05.gif и?

На 250 байт разницу объяснили. wacko.gif Блин, я ожидал поболее.
zhevak
Как Вы считали? У меня другие цифры.

(87 + 86) * 4 + (16 + 26) * 2 = 776 байт
(23 + 25) * 4 + (24 + 33) * 2 = 306 байт

разница 470 байт.
neiver
Думаю, что не на 250 байт, поменьше. Не всегда Lds можно выгодно заменить на Ld/Ldd - адрес-то нужно предварительно загрузить в регистры.
Для 4-х и 2-х байтовых переменных и для структур выгоднее (только по размеру кода, но не по скорости) Ld/Ldd/St/Std использовать. Для однобайтовых - Lds/Sts.
А вообще, IAR более оптимально использует косвенную адресацию со смещением. AVR-GCC приходится явно намекать какую адресацию использовать, например работая с переменной через указатель.
_Pasha
Цитата(zhevak @ Feb 21 2011, 18:18) *
Как Вы считали?

(87-23)+(86-25)=125 слов, имея ввиду только разницу между нормальными командами и этой, придурошной sm.gif

Цитата(neiver @ Feb 21 2011, 18:30) *
Думаю, что не на 250 байт, поменьше.
А вообще, IAR более оптимально использует косвенную адресацию со смещением. AVR-GCC приходится явно намекать какую адресацию использовать, например работая с переменной через указатель.

Ну, поменьше, это ж на глазок было. Гцц как ни намекай, он иногда в такую бяку сваливается sad.gif, жаждешь от него этих "со смещением", а их все нету. Это РТЛ деревья, видать, по мозгам сильно проехались. Не умеет он по-настоящему юзать три указателя. Еще Гцц не любит действия со старшим битом. Еще... да нафиг! Зато "на переднем крае" всегда.
klen
после танцев с бубном получил следующие размеры

''чистая культура" без использования библиотечных аля printf
text data bss dec hex filename
2714 30 43 2787 ae3 monitor-gcc.elf

максимум что я выжал не выкидывая авторские вызовый sprintf
text data bss dec hex filename
3240 114 43 3397 d45 monitor-gcc.elf

gcc версия 4.6.0 20110127 (experimental) (Klen's GCC package (KGP) for AVR/elf platform)
zhevak
Ну вроде как стало соизмеримо (если не сказать сравнялось в ноль!):
gcc: 2787(text) + 30(data) = 2817 байт флеши.
IAR: 2596(text) + 221(data) = 2817 байт флеши

Но что значит "без использования"?
Цитата(klen @ Feb 22 2011, 14:08) *
''чистая культура" без использования библиотечных аля printf


Вы вызовы просто закомментировали или сохранили функциональность, заменив их на strcpy() и itoa()?
В исходниках для IAR-а вызовы printf() не удалены и не заменены. Т.е. как бы условия состязания нарушены.

Вчера ночью попробовал postmessage(), которую вызывают оба прерывания, сделать inline -- ни какой реакции sad.gif, как было, так и осталось.

А пока резюме такое (извините, оно получилось несколько персонифицированным конкретно ко мне)
1. Функции printf и их модификации в тулчейне для avr имеют большие размеры, чем в IAR. Поэтому, если стоит вопрос компактности кода, их использования следует избегать.
2. Не забывать, что функции printf имеют несколько реализаций, выбор которых через ключи линковщика -Wl, -u, ...


Ну что, если других предложений нет, тогда переходим к фазе оптимизации два -- оптимизация кода.
Тут я вижу сразу две точки приложения:
1. Заменить вызовы printf() на strcpy(), strcat() и itoa()
2. Сделать по уму, заменить функции работы с оперативой на функции работы с констатами во флеш, т.е. вместо strcat() использовать strcat_P() и т.д.

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

По крайней мере для себя я понял, почему в первом приближении на gcc не достигается компактность кода присущая IAR, и что следует делать, что бы хоть как-то уменьшить размер кода.


ГОСПОДА, СПАСИБО ЗА КОЛЛАБОРАЦИЮ!

Через какое-то время я сообщу, что у меня получилось после реализации фазы два.
klen
точно, чистая культура это вмесо printf заглушки. я это сделал чтоб посмотреть сколько собственного кода пллучится. второй вариант без нарушения функциональности
vitmeat
Попробуйте заменить стандартный gcc'ый printf на xprintf от elm-chan'a http://elm-chan.org/fsw/strf/xprintf.html
Эмм... В общем он теперь тоже сишный и большой, раньше был на асме и маленький, аж удивился rolleyes.gif . Но даже сейчас он меньше.
Заменил sprintf на xsprintf без потери функциональности

Из 4 тулчейнов: biggrin.gif

WinAVR -> ( тут еще включен -mint8 и --param inline-call-cost=0 )
Program: 3268 bytes (39.9% Full)
Data: 161 bytes (15.7% Full)

kgp_avr ->
Program: 3402 bytes (41.5% Full)
Data: 161 bytes (15.7% Full)

AVR_Toolchain -> ( тут еще включен -mint8 )
Program: 3366 bytes (41.1% Full)
Data: 161 bytes (15.7% Full)

mhvavrtools ->
Program: 3386 bytes (41.3% Full)
Data: 161 bytes (15.7% Full)

Для стандартной printf у меня получилось: biggrin.gif

WinAVR -> ( тут еще включен -mint8 и --param inline-call-cost=0 )
Program: 3514 bytes (42.9% Full)
Data: 157 bytes (15.3% Full)

kgp_avr ->
Program: 3578 bytes (43.7% Full)
Data: 157 bytes (15.3% Full)

AVR_Toolchain -> ( тут еще включен -mint8 )
Program: 3554 bytes (43.4% Full)
Data: 157 bytes (15.3% Full)

mhvavrtools ->
Program: 3566 bytes (43.5% Full)
Data: 157 bytes (15.3% Full)

WinAVR -> avr-gcc.exe (WinAVR 20100110) 4.3.3
kgp_avr -> avr-gcc.exe (Klen's GCC package (KGP) for AVR/elf platform) 4.6.0 20100725 (experimental)
AVR_Toolchain -> avr-gcc.exe (AVR_Toolchain_3.0_149) 4.4.3
mhvavrtools -> avr-gcc.exe (GCC) 4.5.1
wacko.gifcranky.gif
_Pasha
Наткнулся на интересную бяку. Для начала, убрал все "ньюансовые" флаги. Размер существенно не менялся. Компилер, тсз conventional 2010-0110 sm.gif
Придрался к стремно-длинным прологам/эпилогам в прерываниях. По опыту - это гавновопрос, сделал так (почти на автопилоте)
Код
static void postmessage_prim(msg_t msg);
void postmessage(msg_t msg)
{
postmessage_prim(msg);
}

Соответственно, в прерываниях, поменял вызовы на статик-примитив. Логика железная - статик как на ладони, шохошь то и делай.
Так он, собако, абсолютно это игнорирует и прологи те же. cranky.gif Вот жеж нанизм блин! И самое загадостное, что у мну это много раз так разруливалось. Он что, фамилию спрашиват?

UPD причину нашел, надо было указать __attribute__((pure))
С дефолтовым минимальным принтфом 3788 байт.
demiurg_spb
Цитата(_Pasha @ Feb 23 2011, 14:44) *
С дефолтовым минимальным принтфом 3788 байт.

аналогично, но у меня поменьше вышло 3424
вообще без правки исходников, лишь переписал Makefile.
CODE
avr-gcc (AVR_Toolchain_3.0_149) 4.4.3
Copyright © 2010 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

Building project: bin/monitor-gcctest/monitor-gcc.elf

avr-gcc -mmcu=atmega8 -MMD -MP -MF ./bin/monitor-gcctest/monitor-gcc.dep -gdwarf-2 -DF_CPU=4608000UL -Os -pedantic -funsigned-char
-funsigned-bitfields -fpack-struct -fshort-enums -Wall -Wstrict-prototypes -fno-split-wide-types --combine -fwhole-program -ffunction-sections
-fdata-sections -Wl,--relax -ftree-loop-ivcanon -mcall-prologues -fno-tree-scev-cprop -finline-small-functions -fearly-inlining
--param inline-call-cost=2 -finline-limit=65535 -mshort-calls -fno-unit-at-a-time -Wsign-compare -Wa,-adhlns=./bin/monitor-gcctest/monitor-gcc.lst
-std=c99 -I. hal.c app.c lcd4.c main.c --output bin/monitor-gcctest/monitor-gcc.elf -Wl,-Map=./bin/monitor-gcctest/monitor-gcc.map,--cref
-Wl,--gc-section -Wl,-u,vfprintf -lprintf_min

Creating load file for Flash: bin/monitor-gcctest/monitor-gcc.hex
avr-objcopy -O ihex -R .eeprom -R .fuse -R .lock -R .signature bin/monitor-gcctest/monitor-gcc.elf bin/monitor-gcctest/monitor-gcc.hex

Creating load file for EEPROM: bin/monitor-gcctest/monitor-gcc.eep
avr-objcopy -j .eeprom --set-section-flags=.eeprom="alloc,load" \
--change-section-lma .eeprom=0 --no-change-warnings -O ihex bin/monitor-gcctest/monitor-gcc.elf bin/monitor-gcctest/monitor-gcc.eep || exit 0

Creating Extended Listing: bin/monitor-gcctest/monitor-gcc.lss
avr-objdump -h -S bin/monitor-gcctest/monitor-gcc.elf > bin/monitor-gcctest/monitor-gcc.lss

Creating Symbol Table: bin/monitor-gcctest/monitor-gcc.sym
avr-nm -n bin/monitor-gcctest/monitor-gcc.elf > bin/monitor-gcctest/monitor-gcc.sym

Size after:
AVR Memory Usage
----------------
Device: atmega8

Program: 3424 bytes (41.8% Full)
(.text + .data + .bootloader)

Data: 157 bytes (15.3% Full)
(.data + .bss + .noinit)

Последний WinAVR выдал ещё на 4 байта меньше 3420.
avr-gcc (Klen's GCC package (KGP) for AVR/elf platform) 4.6.0 20100725 (experimental) выдал на 30 байт больше 3454
zhevak
Цитата(demiurg_spb @ Feb 26 2011, 22:02) *
... выдал на 30 байт больше 3454

30 байт это 1%. Мне кажется это не существенно.

(что-то все еще никак не могу засесть за свою задачу и заменить printf на более "легкие" функции.)
zhevak
Похоже что всё, приехали. Дальнейшая борьба за ужатие кода не приносит ощутимых результатов.

Я заменил вызовы sprintf() на strcpy_P(). Где -то это оказалось вообще безболезненно (изменения только в файле app.c):
Код
  case MODE_STOP:
//    strcpy(buf0, "    Spectron");
//    strcpy(buf1, " Click for start");
    strcpy_P(buf0, (PGM_P)pgm_read_word(&(str0)));
    strcpy_P(buf1, (PGM_P)pgm_read_word(&(str1)));
    break;


, а где-то сполшной туман (как потом, через полгода буду сам продираться через это код -- типа что этим кодом хотел сделать и почему нужно было так извращаться, почему нельзя было написать сразу ясно-понятно-чисто):
Код
  case MODE_0:
//    sprintf(buf0, "Channel 1:%6lu", uvchannel0);
    strcpy_P(buf0, (PGM_P)pgm_read_word(&(str4)));
    buf0[8] = '1';
    ltoa(uvchannel0, buf3, 10);
    len = strlen(buf3);
    strcpy((buf0 + (16 - len)), buf3);

    buf1[0] = 0x00;
    break;

Вот, при такой замене размер секции text даже увеличился с 3400 до 3456 байт, а размер секции data уменьшился со 114 до 86 байт.

Потом я вынес повторяющиеся участки в отдельную функцию:
Код
void preplcd(char *buf, char ach, long uv)
{
  char buf3[12];
  uint8_t len;

  strcpy_P(buf, (PGM_P)pgm_read_word(&(str4)));
  buf[8] = ach;
  ltoa(uv, buf3, 10);
  len = strlen(buf3);
  strcpy((buf + (16 - len)), buf3);
}

оставив на месте только ее вызов:
Код
//    sprintf(buf0, "Channel 1:%6lu", uvchannel0);
    preplcd(buf0, '1', uvchannel0);    

    buf1[0] = 0x00;
    break;

То размер секции text удалось еще ужать до 3420 байт.

Таким образом, размер бинарного кода для загрузки во флеш сейчас составляет 3506 байт.

Резюме всего исследования будет такое:

IAR по сравнению с gcc создает заметно более компактный код при минимальных усилиях со стороны программиста.

Увы и ах! Я так понимаю, дальнейшие изыскания не приводят к желаемому результату. К сожалению, вынужден признать, что в этот раз gcc "продул" IAR-у. Это вывод №1.

Вывод №2. Замена sprintf на серию функций не дала существенной экономии. На деле даже получился небольшой проигрыш. Но это скорее всего из-за того, что были так же взяты не чистые функции (strcpy), а функции работы с флеш-памятью (strcpy_P). Но так или иначе получается, что раз улучшения нет, то функции printf в libc не такие уж и "раздутые", как казалось ранее. Просто что-то еще улучшить в gcc или libc у их создателей уже не получается. Использовать же printf на практике вполне можно и даже нужно, ибо ясность исходного кода куда более важна, чем экономия 20 байт флеша.

Если у вас есть что добавить или опровергнуть, пожалуйста скажите, я же дальнейшие "исследования" в этом направлении прекращаю. Здесь ловить не чего.
_Pasha
Цитата(demiurg_spb @ Feb 26 2011, 20:02) *
аналогично, но у меня поменьше вышло 3424
вообще без правки исходников, лишь переписал Makefile.
***
--combine -fwhole-program
***

Это да, убийственные ключики sm.gif Только напрягает, что надо все за один пасс делать...
MrYuran
Цитата(zhevak @ Mar 1 2011, 05:14) *
IAR по сравнению с gcc создает заметно более компактный код при минимальных усилиях со стороны программиста.

Зато, по соотношению цена/качество GCC на недосягаемой высоте sm.gif
Ну, а если надо в считанные килобайты упихивать, то может, лучше вообще от си отказаться.
Есть, например, очень компактные форт-машины.
zhevak
Цитата(MrYuran @ Mar 1 2011, 12:27) *
Зато, по соотношению цена/качество GCC на недосягаемой высоте sm.gif
Ну, а если надо в считанные килобайты упихивать, то может, лучше вообще от си отказаться.
Есть, например, очень компактные форт-машины.

Ну, это уже холивар, от которого я бы хотел отойти. Мне важно не поспорить, а важно найти истину -- важно знать, что и сколько я (лично я) теряю при использовании gcc. А то, что gcc распространяется бесплатно, так это итак все знают. Но сколько при этом теряется "компактности" -- одни слухи и какие-то бездоказательные утверждения. Я, так сказать, пожертвовал своим временем и своей репутацией (вывесил сушиться свои трусы на площади). Я думаю, что народ понял мой поступок, поэтому давайте по существу. Иначе мы так и будем продолжать жить эмоциями, а не фактами.

Уйти разработчику на ассемблер или на форт -- да, наверно это можно. Но хотелось бы не менять условий, хотелось сравнить два компилятора в примерно одинаковых условиях.

Если Вас, MrYuran, это хоть как-то успокоит, то знайте, что я сожалею о "проигрыше" gcc, но тем не менее, остаюсь с ним. Как я уже где-то выше говорил, я не использую Венду вообще. Поэтому у меня нет выбора. И даже если бы сидал под Вендой, то использовать пиратский IAR мне претит мое воспитание. И тут дело даже не в неотвратимости наказания за пиратство. Тут более высокие понятия. Дети будут ржать, но все же скажу -- дело в морали. Дело в ответе на тот самый главный вопрос -- а для чего мы вообще живем. Каждым человеком движет получение удовольствия. Мы все получаем удовольствие. Только один получает удовольствие от того, что имеет много денег, а другой -- от того, что много знает и много чего умеет делать. Мне нравиться второе. Плюс, я еще это положение "дожимаю" понятиям типа "жить, оставаясь в рамках морали". (Не в рамках закона, а по совести -- почувствуйте разницу!) Мне это интересно, и я от этого получаю удовольствие. А деньги -- что! Деньги -- фигня! Сколько бы их ни было, их всегда не хватает. Определитесь со своим главным вопросом, и все придет в норму. Я никого не осуждаю. Просто каждый сам отвечает на это вопрос по-своему, а как правильно -- никто не знает.

Блин. На хрена я это все написал?
Ладно. Пусть будет. Может сгодится кому еще.
Nixon
Возможно вы просто взяли не совсем удачный проект для сравнения, слишком маленький, на котором оверхед GCC выражается в разы. Вот и получилось как в рекламных пресс-релизах. Возьмите проект посерьезнее или даже несколько, разных размеров. Это будет и позновательнее и объективнее.
Сергей Борщ
Если я правильно помню принцип работы strcpy_P, то надо делать проще: strcpy_P(buf0, str0); Не нужно читать первые два байта строки и пытаться трактовать их как адрес. Можно более красиво (если строки уникальные и не С++): strcpy_P(buf0, PSTR(" Spectron"));

А если речь уже зашла об "оптимизируем исходник, оставляя неизменной функциональность", то как минимум в дисплее можно наэкономить отказавшись от чтения готовности, от операции %20, объединив -wrc и LCD_char(). В общем "из любой программы можно выжать еще хотя бы один байтик".
_Pasha
Цитата(Nixon @ Mar 1 2011, 11:58) *
Возьмите проект посерьезнее или даже несколько, разных размеров. Это будет и позновательнее и объективнее.

Их еще поискать надо, чтоб "чистой культуры" были, не завязанной на реализациях libc
demiurg_spb
Цитата(_Pasha @ Mar 1 2011, 09:54) *
Это да, убийственные ключики sm.gif Только напрягает, что надо все за один пасс делать...

Меня не напрягает вовсе.
У меня вообще все проекты для младших AVR (до Mega162 включительно) только благодаря этому и влезают в кристалл.
Да ещё и бутлоадер....

2ТС:
Давайте потестируем на каком-нибудь опенсорсном проекте для AVR размером от 40КБ...
zhevak
Цитата(Nixon @ Mar 1 2011, 13:58) *
Возможно вы просто взяли не совсем удачный проект для сравнения, слишком маленький, на котором оверхед GCC выражается в разы. Вот и получилось как в рекламных пресс-релизах. Возьмите проект посерьезнее или даже несколько, разных размеров. Это будет и позновательнее и объективнее.

Да. Спасибо.
Я взял то, что смог окучить. Точнее -- почти окучил (т.е. имеются траблы, читайте ниже ответ Сергею). Ведь помимо этой работы -- переноса проекта в другую среду, сравнения и разборки чего-там можно отпилить еще, есть и основная работа. У Вас есть время? Вот и у меня так же. А на счет объективности... ну-у, небольшие проекты тоже имеют право на жизнь. А будет большой проект, и будет достаточно времени, обязательно попробую. Только ведь это... sm.gif наши желания редко согласуются с программой Всевышнего.

Цитата(Сергей Борщ @ Mar 1 2011, 14:53) *
Если я правильно помню принцип работы strcpy_P, то надо делать проще: strcpy_P(buf0, str0); Не нужно читать первые два байта строки и пытаться трактовать их как адрес. Можно более красиво (если строки уникальные и не С++): strcpy_P(buf0, PSTR(" Spectron"));

А если речь уже зашла об "оптимизируем исходник, оставляя неизменной функциональность", то как минимум в дисплее можно наэкономить отказавшись от чтения готовности, от операции %20, объединив -wrc и LCD_char(). В общем "из любой программы можно выжать еще хотя бы один байтик".

А-а, блин!!! Спасибо, Сергей!

Конечно же нужно так:
Код
  strcpy_P(buf, str4);

Все спешим, спешим...Это ж ведь уже готовые строки. Вот так и живем, не приходя в сознание!
На удивление, размер кода еще ужался, значит компилятор что-то там преобразовывал. Кому интересно, сейчас text = 3408 байт.

(Результаты последних компиляций я не проверял. Железка на полигоне. Мониторит процессы. Отключать, снимать не желательно. Второго экземпляра нет.)
Сергей Борщ
Взял проект из первого сообщения. Скомпилил со своим makefile, WinAVR 20100110, 3910 байт program, 157 data.
Переработал lcd.c (убрал чтение готовности, объединил вывод команд и символов, переписал SetXY, 4 строки): 3750 байт
hal.c: Добавил inline - 3738
app.c: Объявил uvchannel массивом, свернул в цикл обработку в procpack: - 3620
app.c: сделал обнуление uvchannel через memset : 3566
app.c: static inline procpack: 3554
app.c: static inline update_lcd: 3544
makefile: -lprintf_min: 3172
lcd.c: сделал 2 строки в SetXY: 3156
app.c: заменил sprintf на strcpy_P, sprintf_P - 3134 / 47 data
app.c: вынес из switch buf1[0] = '\0' - 3124
увеличил --param inline-call-cost до 2 - 3120.

Результат в приложении.
ой, ошибочку внес. После переделки на sprintf_P уже нельзя делать buf1[0] = '\0'; сейчас исправлю. Нет, можно. Все нормально.
Нажмите для просмотра прикрепленного файла

Если однократно вызываемые функции повыностить из .c в .h и сделать их static inline - можно выиграть еще.
MrYuran
Цитата(Сергей Борщ @ Mar 1 2011, 17:47) *
Если однократно вызываемые функции повыностить из .c в .h и сделать их static inline - можно выиграть еще.

А я это первым делом предлагал сделать.
Выигрыш получился бы не только по объёму, но и по скорости.
zhevak
Я не понял. Что, пьянка -- продолжается что ли? (Эт-зря я уснул в слате. Рановато получилось.)

Цитата(Сергей Борщ @ Mar 1 2011, 19:47) *
Взял проект из первого сообщения...

Сергей, отличная работа!

А Вы можете теперь проделать примерно тоже самое в IAR-e?
... и за одно учесть мнение MrYuran на счет inline.
zltigo
QUOTE (zhevak @ Mar 1 2011, 11:32) *
использовать пиратский IAR мне претит мое воспитание.

Вы, наверное, не поверите, но IAR можно купить. Не всегда стоит экономить на инструментах. Заодно не придется юродски коверкать названия продуктов.
zhevak
Цитата(zltigo @ Mar 2 2011, 01:38) *
Вы, наверное, не поверите, но IAR можно купить. Не всегда стоит экономить на инструментах. Заодно не придется юродски коверкать названия продуктов.

Вы, наверное, не поверите, но gcc распространяется бесплатно. Не всегда стоит покупать то, чему есть достойные альтернативы, удовлетворяющие вашим потребностям. Все это вопросы философии. Не имеет смысла спорить.

Цитата
Заодно не придется юродски коверкать названия продуктов.

Э-э... извините, вот тут я вообще ничего не понял. Это Вы про что?
IgorKossak
Цитата(zhevak @ Mar 2 2011, 00:46) *
Э-э... извините, вот тут я вообще ничего не понял. Это Вы про что?

Это про Венду, очевидно. И давайте замнём этот вопрос.

Модератор.
demiurg_spb
Наверное можно подвести кое какие итоги.
Я бы хотел заострить внимание на том, что прежде чем пинять на тот или иной продукт стоит его изучить и поработать в нём какое-то время. И второе но не менее важное - без хорошего знания языка программирования грешить на объём прошивки как минимум неразумно (камень в огород ТС). Компиляторы нынче весьма умные (что IAR что gcc оба достойные конкуренты друг-другу), но программист - это всё же определяющий фактор. Пусть звучит банально, но зато отражает моё личное отношение к теме.
zhevak
Цитата(demiurg_spb @ Mar 2 2011, 15:31) *
Наверное можно подвести кое какие итоги.
Я бы хотел заострить внимание на том, что прежде чем пинять на тот или иной продукт стоит его изучить и поработать в нём какое-то время. И второе но не менее важное - без хорошего знания языка программирования грешить на объём прошивки как минимум неразумно (камень в огород ТС). Компиляторы нынче весьма умные (что IAR что gcc оба достойные конкуренты друг-другу), но программист - это всё же определяющий фактор. Пусть звучит банально, но зато отражает моё личное отношение к теме.

Спасибо за критику.

Пинать продукты? Да, собственно, никто и не думал пинать. Есть исходный текст проекта, который реальный, а не гипотетический. Не идеальный (а что, разве в жизни все проекты идеальные?) На этом проекте мы поигрались. Получили какой-то результат. Я вообще не вижу никаких проблем.

Единственная проблема состоит в том, что я захотел самостоятельно на своем проекте убедиться для себя лично кое-в-каких цифрах. Да, я и не говорю, что я очень хорошо знаю язык, среду разработки и прочее, что влияет на объем и качество кода. Знаю их на каком-то своем уровне. Этот уровень меня минимально устраивает. Я делаю свою работу и как могу повышаю свою квалификацию. Это плохо?
Ну, ладно, я не подходящая кандидатура. Давайте тогда что-ли найдем идеального товарища, который согласится оставить свою работу, провести всестороннее исследование и ответить на множество вопросов. Но ведь таких людей нет! Они заняты решением своих проблем.

Вот, например, товарищ A (не буду называть его имя) -- грамотный специалист. Давайте его поспрашиваем. Что мы получим? Вместо ответов мы нарвемся на наезды, что мы делаем не то и не так, и вообще не тем занимаемся. Мы о себе много чего узнаем интересного. Но ответ на вопрос -- это уж как товарищ решит, можем и не получить.

Я попытался "испечь торт" из того, что у меня было. Вам не понравилось? Ну что ж... Хорошо. Вы можете чем-то помочь?


Блин, все-таки холливар! Словоблудие.
demiurg_spb
Пинят и пинать - два разных слова:-)
Поэтому я и предлагал использовать приличный во всех смыслах open-sourсe проект для таких вот изысканий.
Или даже больше какой-либо синтетический тест из уже существующих.
Изобретение колеса заново - не метод инженера.
MrYuran
Цитата(zhevak @ Mar 2 2011, 13:57) *
Я попытался "испечь торт" из того, что у меня было. Вам не понравилось? Ну что ж... Хорошо. Вы можете чем-то помочь?

Да всё нормально.
Я год назад сделал примерно такой же вывод - что IAR обеспечивает как минимум не худший вариант при значительно меньших усилиях и знаниях.
Ну, на то и коммерческий продукт, должен же он хоть чем-то отличаться от свободного sm.gif .

Осознав данный факт, я решил больше не дёргаться по этому поводу и оптимизировать проект только в случае действительной необходимости
(не лезет или не успевает)

Ещё, в MSPGCC остановились в своё время на версии GCC 3.2.3, потом родился параллельный проект с GCC 4xx.
Так вот, сравнение по объёму далеко не в пользу последнего, даже со всеми дополнительными ухищрениями.
А WinAVR собирается как раз на основе свежих версий GCC.

zhevak
Цитата(demiurg_spb @ Mar 2 2011, 16:56) *
Пинят и пинать - два разных слова:-)
Поэтому я и предлагал использовать приличный во всех смыслах open-sourсe проект для таких вот изысканий.
Или даже больше какой-либо синтетический тест из уже существующих.
Изобретение колеса заново - не метод инженера.

Ну, тогда уж не "пинять" а, "пенять". Извините, я действительно не знал, как понимать Ваши слова.

Ну, давайте, давайте возьмем готовый opensource-проект. Лично я не против. Другие участники, думаю, тоже не будут возражать. Вопрос только в том, кто все это будет делать? Кто все это дело будет двигать? Я не смогу. Вы предложили -- Вы и раскручивайте кампанию, а мы по мере сил Вам поможем и, уж простите, так повелось, -- покритикуем. Ну что, беретесь? Только я буду на вторых ролях, не хочу быть лидером.

MrYuran, да я такого же мнения. Жить с gcc можно. Хотя, признаться, я несколько разочарован, но ведь не смертельно ж! Тем более, что Заказчику как правило, вообще пофиг на чем написано -- хоть на Васике! Лишь бы работало согласно ТЗ, и стоимость разработки не вылезала за бюджет.
demiurg_spb
Я готов потестить под различными версиями gcc.
Вопрос в выборе теста остаётся открытым.

Народ, высказывайте Ваши предложения!
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.