|
WinAVR обновился до 20081118rc2, Похоже, скоро релиз появится! |
|
|
|
Nov 20 2008, 12:22
|
Частый гость
 
Группа: Свой
Сообщений: 106
Регистрация: 13-05-05
Пользователь №: 4 977

|
Release Candidate 20081118rc2File Release Notes and Changelog Release Name: 20081118rc2 Notes: Below is just a sample of what's new. - New version of GNU Binutils: 2.19 - New version of GCC: 4.3.2 - New version of AVR-LibC: 1.6.4 - New version of Programmers Notepad: 2.0.8.718 - New devices supported: * ATxmega64A3 * ATxmega128A3 * ATxmega256A3 * ATxmega256A3B * ATmega32U6 - Various bugs fixed.
|
|
|
|
3 страниц
1 2 3 >
|
 |
Ответов
(1 - 41)
|
Nov 21 2008, 09:12
|
Знающий
   
Группа: Свой
Сообщений: 771
Регистрация: 16-07-07
Из: Волгодонск
Пользователь №: 29 153

|
Цитата(sonycman @ Nov 21 2008, 12:02)  А вчера вообще в куске кода вида: unsigned char a, b; if (a > (b +10)) ... заметил, что байтные переменные обрабатывались как слова... :-( Все по стандарту - в арифметических выражениях unsigned char продвигается до unsigned int ... GCC по-идее. так же будет работать.
|
|
|
|
|
Nov 21 2008, 13:52
|

Любитель
    
Группа: Свой
Сообщений: 1 864
Регистрация: 20-08-06
Из: Тольятти
Пользователь №: 19 695

|
Цитата(Непомнящий Евгений @ Nov 21 2008, 13:12)  Все по стандарту - в арифметических выражениях unsigned char продвигается до unsigned int ... GCC по-идее. так же будет работать. Так и думал, что типа так положено. Кто только не придумывает эти стандарты... Однако, при максимальной оптимизации по скорости и по размеру кода, это выражение выглядит просто дико - тогда, когда оно могло было быть в два раза быстрее и в два раза меньше Не менее глупо выглядит такое: unsigned char a, b; if (a > (byte)(b +10)) ... но код становится правильным Цитата(_Pasha @ Nov 21 2008, 13:45)  А Вы хотели, чтобы если b=250, а=16, то (b+10) чтоб резко стало меньше а  Да нет, слава богу, пока такое не задумывал Цитата(Сергей Борщ @ Nov 21 2008, 14:47)  он определяет по расширению исходного файла. .cpp компилируется в режиме С++. Будьте готовы в ближайшее время изучать make и язык его makefile, ибо то, что генерит студия вас скоро перестанет устраивать. Хм, да, пошарился тут по сети, и кое-какие заявления о том, что для поддержки С++ нужно что-то там пересобрать (перекомпилировать???) ставят в тупик... б-рр-р, ох уже этот линукс Цитата(demiurg_spb @ Nov 21 2008, 15:02)  Забудьте про IDE:) FAR+colorer+makefile и в путь! Ну, я пока неплохо себя чувствую со SlickEdit и IAR. Хочу просто сравнить компиляторы. Вдруг понравится? Спасибо всем за помощь!
|
|
|
|
|
Nov 21 2008, 15:50
|

Любитель
    
Группа: Свой
Сообщений: 1 864
Регистрация: 20-08-06
Из: Тольятти
Пользователь №: 19 695

|
Цитата(Rst7 @ Nov 21 2008, 18:29)  Например? А вот эту тему посмотрите: тута. Вы же тогда сами мне подсказывали ЗЫ: видимо AVR Studio с интегрированным WinAVR никак не заставить компилировать C++. Среда отказывается компилировать файлы с расширением, отличным от .с... Через внешний makefile это возможно, но что-то не особо прельщает искать ошибки по номерам строчек в файлах, так как клик по сообщению не работает... Млин, каменный век какой-то... Может, когда времени больше будет
|
|
|
|
|
Nov 21 2008, 20:02
|

Любитель
    
Группа: Свой
Сообщений: 1 864
Регистрация: 20-08-06
Из: Тольятти
Пользователь №: 19 695

|
Цитата(Сергей Борщ @ Nov 21 2008, 22:11)  Очень странно. У меня работало. Просто в настройках проекта указать Custom (или External?) Makefile и все. Парсер вывода ведь никуда не денется. А еще можно отказаться от студии и работать в Эклипсе, а студию изредка использовать как симулятор, загружая в нее .elf. Эклипс? Не юзал пока. А СликЭдит не подойдёт? Скомпильнул небольшой код, и мне оптимизация ГНУ показалась интересной. Есть некоторые моменты, которые ИАР (5.10) даже не пытался затронуть, в отличие от, так сказать. Правда, очень уж любит ГНУ разворачивать подпрограммы, размерчик в итоге, думаю, получится посолидней... Тестил ГНУ на О3 и на Оs, а ИАР на макс. по скорости... ЗЫ: вот напоследок перл от ИАРА: Дано: Код #define RPM_MIN 0 #define RPM_MED 1 #define RPM_MAX 2
typedef unsigned char byte;
struct frDatatable { byte min_speed; byte med_speed; byte max_speed; byte min_temp; byte max_temp; } data;
byte RPMval[3]; byte minTEMPval; byte maxTEMPval;
void CFanRegulator::SetData(frDatatable *data) { RPMval[RPM_MIN] = data->min_speed; RPMval[RPM_MED] = data->med_speed; RPMval[RPM_MAX] = data->max_speed; minTEMPval = data->min_temp; maxTEMPval = data->max_temp; } Вроде проще некуда. В итоге имеем: Код void CFanRegulator::SetData(frDatatable *data) \ ??SetData: 15 { 16 RPMval[RPM_MIN] = data->min_speed; \ 00000000 01F9 MOVW R31:R30, R19:R18 \ 00000002 8140 LD R20, Z \ 00000004 01F8 MOVW R31:R30, R17:R16 \ 00000006 8345 STD Z+5, R20 17 RPMval[RPM_MED] = data->med_speed; \ 00000008 01F9 MOVW R31:R30, R19:R18 \ 0000000A 8141 LDD R20, Z+1 \ 0000000C 01F8 MOVW R31:R30, R17:R16 \ 0000000E 8346 STD Z+6, R20 18 RPMval[RPM_MAX] = data->max_speed; \ 00000010 01F9 MOVW R31:R30, R19:R18 \ 00000012 8142 LDD R20, Z+2 \ 00000014 01F8 MOVW R31:R30, R17:R16 \ 00000016 8347 STD Z+7, R20 19 minTEMPval = data->min_temp; \ 00000018 01F9 MOVW R31:R30, R19:R18 \ 0000001A 8143 LDD R20, Z+3 \ 0000001C 01F8 MOVW R31:R30, R17:R16 \ 0000001E 8740 STD Z+8, R20 20 maxTEMPval = data->max_temp; \ 00000020 01F9 MOVW R31:R30, R19:R18 \ 00000022 8124 LDD R18, Z+4 \ 00000024 01F8 MOVW R31:R30, R17:R16 \ 00000026 8721 STD Z+9, R18 21 } \ 00000028 9508 RET Просто аццкая куча кода Раз указатель грузится каждый раз заново - зачем он здесь вообще нужен? К чему так заморачиваться - надо было авторам LDS использовать - эффект тот-же И такое встречается частенько. Вроде хороший компилер, но работа с указателями похабная. Из трёх регистровых пар практически используется только одна. А вот ГНУ такой фигнёй, похоже, не страдает
|
|
|
|
|
Nov 21 2008, 20:49
|
Профессионал
    
Группа: Участник
Сообщений: 1 264
Регистрация: 17-06-08
Из: бандустан
Пользователь №: 38 347

|
Цитата А вот ГНУ такой фигнёй, похоже, не страдает ну дык, зачем тогда платить ? новые версии выходят регулярно, комьюнити и охват ахитектур огромные.
|
|
|
|
|
Nov 21 2008, 22:29
|

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

|
Цитата(sonycman @ Nov 21 2008, 22:02)  Эклипс? Не юзал пока. А СликЭдит не подойдёт? Пойдет. Лично не пользовал, но уважаемые форумчане хвалят. Цитата(sonycman @ Nov 21 2008, 22:02)  Тестил ГНУ на О3 и на Оз, а ИАР на макс. по скорости... Дык... O3 - это для больших машин с кучей памяти. Инлайн и разворот циклов где только можно в погоне за скоростью. Для AVR оптимальным является Os. Кроме того там есть еще куча ключей для тонкой настройки. Ваш код действительно дал какой-то неадекватный результат. Для ИАРа оптимизация по скорости очень часто дает меньший код, чем оптимизация по размеру (парадокс!). Попробуйте включить кластеризацию переменных, и вообще все галочки, которые доступны в дополнительных параметрах оптимизации.
--------------------
На любой вопрос даю любой ответ"Write code that is guaranteed to work, not code that doesn’t seem to break" ( C++ FAQ)
|
|
|
|
|
Nov 21 2008, 22:30
|

Местный
  
Группа: Участник
Сообщений: 403
Регистрация: 14-05-07
Из: Россия, г.Пенза
Пользователь №: 27 719

|
Цитата(Сергей Борщ @ Nov 21 2008, 21:11)  А еще можно отказаться от студии и работать в Эклипсе, а студию изредка использовать как симулятор, загружая в нее .elf. Вот вот, именно так и я делаю. Разделение труда. Пакет ГНУ для кода, а Студия для отладки. И все работает как часы...
--------------------
" Многие вещи нам непонятны не потому, что наши понятия слабы; но потому, что сии вещи не входят в круг наших понятий." (с) К.Прутков.
|
|
|
|
|
Nov 22 2008, 02:01
|

Любитель
    
Группа: Свой
Сообщений: 1 864
Регистрация: 20-08-06
Из: Тольятти
Пользователь №: 19 695

|
Цитата(Сергей Борщ @ Nov 22 2008, 02:29)  Пойдет. Лично не пользовал, но уважаемые форумчане хвалят.Дык... O3 - это для больших машин с кучей памяти. Инлайн и разворот циклов где только можно в погоне за скоростью. Для AVR оптимальным является Os. Кроме того там есть еще куча ключей для тонкой настройки. Ваш код действительно дал какой-то неадекватный результат. Для ИАРа оптимизация по скорости очень часто дает меньший код, чем оптимизация по размеру (парадокс!). Попробуйте включить кластеризацию переменных, и вообще все галочки, которые доступны в дополнительных параметрах оптимизации. Пробовал - не помогает. Исправляюсь - кроме О3 тестил ещё и на Os. Да, последний режим давал более приемлимые результаты Цитата(IgorKossak @ Nov 22 2008, 02:50)  Поставьте перед функцией __z, а ещё лучше __x (передавать указатель через регистровую пару весьма разумно) или оптимизацию установите по объёму и будет Вам счастье. Не всё так просто. Не спасает ничего, кроме установки перед функцией ключа __x_z. Но почему я должен каждую микроскопическую функцию проверять и персонально настраивать под оптимальную генерацию руками? На это нужна куча времени!
|
|
|
|
|
Nov 23 2008, 08:22
|
Группа: Участник
Сообщений: 6
Регистрация: 16-12-05
Пользователь №: 12 291

|
Цитата(Alex_NEMO @ Nov 20 2008, 15:22)  ... - Various bugs fixed. Вот с ЭТОГО бы места да поподробнее.
|
|
|
|
|
Nov 23 2008, 10:07
|
Частый гость
 
Группа: Свой
Сообщений: 106
Регистрация: 13-05-05
Пользователь №: 4 977

|
Цитата(NetTracer @ Nov 23 2008, 11:22)  Вот с ЭТОГО бы места да поподробнее.  Не по адресу вопрос! Когда релиз выйдет, возможно, распишут более подробно! Но то, что новых добавят - это несомненно! (См. ветку)
|
|
|
|
|
Nov 24 2008, 15:23
|

Любитель
    
Группа: Свой
Сообщений: 1 864
Регистрация: 20-08-06
Из: Тольятти
Пользователь №: 19 695

|
Портировал я свою программу с IARа на GCC. Оптимизация максимальная по скорости у первого, и Os с ключами -mcall-prologues -fno-inline-small-functions -fno-threadsafe-statics -ffunction-sections --gc-sections --relax у второго. В результате код IARа - 6 090 bytes of CODE memory + 493 bytes of DATA memory. Код GCC - Program: 7120 bytes + Data: 363 bytes. Код иара компактнее свыше чем на килобайт. Правда, некоторые функции "тюнингованы" специальными ключами (типа __z_x и т.д.) для оптимальной генерации. Добавление некоторых аттрибутов для функций в GCC в аналогичных целях, к сожалению, не дало абсолютно никакого результата... На первый взгляд, скомпилированный GCC код весьма красив и аккуратен, за исключением излишней любви к LDS и STS, например: исходный текст: Код case USART_SEND_DATA_EX: length = 4 + 4 + 4 + 20; *pb++ = length + 1; *pb++ = command; *pb++ = temperature.cpu; *pb++ = temperature.gpu; *pb++ = temperature.amb; *pb++ = temperature.hdd; *pb++ = fan_speed[0]; *pb++ = fan_speed[1]; *pb++ = fan_speed[2]; *pb++ = fan_speed[3]; *pb++ = cpuFan.GetCurrentSpeed(); *pb++ = rearFan.GetCurrentSpeed(); *pb++ = sideFan.GetCurrentSpeed(); *pb++ = frontFan.GetCurrentSpeed(); *pb++ = cpuFan.RPMval[RPM_MIN]; *pb++ = cpuFan.RPMval[RPM_MED]; *pb++ = cpuFan.RPMval[RPM_MAX]; *pb++ = cpuFan.minTEMPval; *pb++ = cpuFan.maxTEMPval; *pb++ = rearFan.RPMval[RPM_MIN]; *pb++ = rearFan.RPMval[RPM_MED]; *pb++ = rearFan.RPMval[RPM_MAX]; *pb++ = rearFan.minTEMPval; *pb++ = rearFan.maxTEMPval; *pb++ = sideFan.RPMval[RPM_MIN]; *pb++ = sideFan.RPMval[RPM_MED]; *pb++ = sideFan.RPMval[RPM_MAX]; *pb++ = sideFan.minTEMPval; *pb++ = sideFan.maxTEMPval; *pb++ = frontFan.RPMval[RPM_MIN]; *pb++ = frontFan.RPMval[RPM_MED]; *pb++ = frontFan.RPMval[RPM_MAX]; *pb++ = frontFan.minTEMPval; *pb++ = frontFan.maxTEMPval; break; результат IARа: Код 105 case USART_SEND_DATA_EX: 106 length = 4 + 4 + 4 + 20; \ ??usartSendCommand_4: \ 000000C4 E280 LDI R24, 32 107 *pb++ = length + 1; \ 000000C6 E201 LDI R16, 33 \ 000000C8 930D ST X+, R16 108 *pb++ = command; \ 000000CA 934D ST X+, R20 109 *pb++ = temperature.cpu; \ 000000CC 9100.... LDS R16, temperature \ 000000D0 930D ST X+, R16 110 *pb++ = temperature.gpu; \ 000000D2 9100.... LDS R16, (temperature + 1) \ 000000D6 930D ST X+, R16 111 *pb++ = temperature.amb; \ 000000D8 9100.... LDS R16, (temperature + 2) \ 000000DC 930D ST X+, R16 112 *pb++ = temperature.hdd; \ 000000DE 9100.... LDS R16, (temperature + 3) \ 000000E2 930D ST X+, R16 113 *pb++ = fan_speed[0]; \ 000000E4 9100.... LDS R16, fan_speed \ 000000E8 930D ST X+, R16 114 *pb++ = fan_speed[1]; \ 000000EA 9100.... LDS R16, (fan_speed + 1) \ 000000EE 930D ST X+, R16 115 *pb++ = fan_speed[2]; \ 000000F0 9100.... LDS R16, (fan_speed + 2) \ 000000F4 930D ST X+, R16 116 *pb++ = fan_speed[3]; \ 000000F6 9100.... LDS R16, (fan_speed + 3) \ 000000FA 930D ST X+, R16 117 *pb++ = cpuFan.GetCurrentSpeed(); \ 000000FC .... LDI R16, LOW(cpuFan) \ 000000FE .... LDI R17, (cpuFan) >> 8 \ 00000100 .... RCALL ??GetCurrentSpeed \ 00000102 930D ST X+, R16 118 *pb++ = rearFan.GetCurrentSpeed(); \ 00000104 .... LDI R16, LOW(rearFan) \ 00000106 .... LDI R17, (rearFan) >> 8 \ 00000108 .... RCALL ??GetCurrentSpeed \ 0000010A 930D ST X+, R16 119 *pb++ = sideFan.GetCurrentSpeed(); \ 0000010C .... LDI R16, LOW(sideFan) \ 0000010E .... LDI R17, (sideFan) >> 8 \ 00000110 .... RCALL ??GetCurrentSpeed \ 00000112 930D ST X+, R16 120 *pb++ = frontFan.GetCurrentSpeed(); \ 00000114 .... LDI R16, LOW(frontFan) \ 00000116 .... LDI R17, (frontFan) >> 8 \ 00000118 .... RCALL ??GetCurrentSpeed \ 0000011A 930D ST X+, R16 121 *pb++ = cpuFan.RPMval[RPM_MIN]; \ 0000011C 9100.... LDS R16, (cpuFan + 5) \ 00000120 930D ST X+, R16 122 *pb++ = cpuFan.RPMval[RPM_MED]; \ 00000122 9100.... LDS R16, (cpuFan + 6) \ 00000126 930D ST X+, R16 123 *pb++ = cpuFan.RPMval[RPM_MAX]; \ 00000128 9100.... LDS R16, (cpuFan + 7) \ 0000012C 930D ST X+, R16 124 *pb++ = cpuFan.minTEMPval; \ 0000012E 9100.... LDS R16, (cpuFan + 8) \ 00000132 930D ST X+, R16 125 *pb++ = cpuFan.maxTEMPval; \ 00000134 9100.... LDS R16, (cpuFan + 9) \ 00000138 930D ST X+, R16 126 *pb++ = rearFan.RPMval[RPM_MIN]; \ 0000013A 9100.... LDS R16, (rearFan + 5) \ 0000013E 930D ST X+, R16 127 *pb++ = rearFan.RPMval[RPM_MED]; \ 00000140 9100.... LDS R16, (rearFan + 6) \ 00000144 930D ST X+, R16 128 *pb++ = rearFan.RPMval[RPM_MAX]; \ 00000146 9100.... LDS R16, (rearFan + 7) \ 0000014A 930D ST X+, R16 129 *pb++ = rearFan.minTEMPval; \ 0000014C 9100.... LDS R16, (rearFan + 8) \ 00000150 930D ST X+, R16 130 *pb++ = rearFan.maxTEMPval; \ 00000152 9100.... LDS R16, (rearFan + 9) \ 00000156 930D ST X+, R16 131 *pb++ = sideFan.RPMval[RPM_MIN]; \ 00000158 9100.... LDS R16, (sideFan + 5) \ 0000015C 930D ST X+, R16 132 *pb++ = sideFan.RPMval[RPM_MED]; \ 0000015E 9100.... LDS R16, (sideFan + 6) \ 00000162 930D ST X+, R16 133 *pb++ = sideFan.RPMval[RPM_MAX]; \ 00000164 9100.... LDS R16, (sideFan + 7) \ 00000168 930D ST X+, R16 134 *pb++ = sideFan.minTEMPval; \ 0000016A 9100.... LDS R16, (sideFan + 8) \ 0000016E 930D ST X+, R16 135 *pb++ = sideFan.maxTEMPval; \ 00000170 9100.... LDS R16, (sideFan + 9) \ 00000174 930D ST X+, R16 136 *pb++ = frontFan.RPMval[RPM_MIN]; \ 00000176 9100.... LDS R16, (frontFan + 5) \ 0000017A 930D ST X+, R16 137 *pb++ = frontFan.RPMval[RPM_MED]; \ 0000017C 9100.... LDS R16, (frontFan + 6) \ 00000180 930D ST X+, R16 138 *pb++ = frontFan.RPMval[RPM_MAX]; \ 00000182 9100.... LDS R16, (frontFan + 7) \ 00000186 930D ST X+, R16 139 *pb++ = frontFan.minTEMPval; \ 00000188 9100.... LDS R16, (frontFan + 8) \ 0000018C 930D ST X+, R16 140 *pb++ = frontFan.maxTEMPval; \ 0000018E 9100.... LDS R16, (frontFan + 9) \ 00000192 CF96 RJMP ??usartSendCommand_12 141 break; вполне прилично. А вот у GCC: Код case USART_SEND_DATA_EX: length = 4 + 4 + 4 + 20; *pb++ = length + 1; 153c: 81 e2 ldi r24, 0x21; 33 153e: 80 93 ed 01 sts 0x01ED, r24 *pb++ = command; 1542: 90 93 ee 01 sts 0x01EE, r25 *pb++ = temperature.cpu; 1546: 80 91 34 01 lds r24, 0x0134 154a: 80 93 ef 01 sts 0x01EF, r24 *pb++ = temperature.gpu; 154e: 80 91 35 01 lds r24, 0x0135 1552: 80 93 f0 01 sts 0x01F0, r24 *pb++ = temperature.amb; 1556: 80 91 36 01 lds r24, 0x0136 155a: 80 93 f1 01 sts 0x01F1, r24 *pb++ = temperature.hdd; 155e: 80 91 37 01 lds r24, 0x0137 1562: 80 93 f2 01 sts 0x01F2, r24 *pb++ = fan_speed[0]; 1566: 80 91 6f 01 lds r24, 0x016F 156a: 80 93 f3 01 sts 0x01F3, r24 *pb++ = fan_speed[1]; 156e: 80 91 70 01 lds r24, 0x0170 1572: 80 93 f4 01 sts 0x01F4, r24 *pb++ = fan_speed[2]; 1576: 80 91 71 01 lds r24, 0x0171 157a: 80 93 f5 01 sts 0x01F5, r24 *pb++ = fan_speed[3]; 157e: 80 91 72 01 lds r24, 0x0172 1582: 80 93 f6 01 sts 0x01F6, r24 *pb++ = cpuFan.GetCurrentSpeed(); 1586: 87 e3 ldi r24, 0x37; 55 1588: 92 e0 ldi r25, 0x02; 2 158a: 4c d7 rcall .+3736 ; 0x2424 <__data_load_end+0x6fe> 158c: 80 93 f7 01 sts 0x01F7, r24 *pb++ = rearFan.GetCurrentSpeed(); 1590: 81 e4 ldi r24, 0x41; 65 1592: 92 e0 ldi r25, 0x02; 2 1594: 47 d7 rcall .+3726 ; 0x2424 <__data_load_end+0x6fe> 1596: 80 93 f8 01 sts 0x01F8, r24 *pb++ = sideFan.GetCurrentSpeed(); 159a: 8b e4 ldi r24, 0x4B; 75 159c: 92 e0 ldi r25, 0x02; 2 159e: 42 d7 rcall .+3716 ; 0x2424 <__data_load_end+0x6fe> 15a0: 80 93 f9 01 sts 0x01F9, r24 *pb++ = frontFan.GetCurrentSpeed(); 15a4: 85 e5 ldi r24, 0x55; 85 15a6: 92 e0 ldi r25, 0x02; 2 15a8: 3d d7 rcall .+3706 ; 0x2424 <__data_load_end+0x6fe> 15aa: 80 93 fa 01 sts 0x01FA, r24 *pb++ = cpuFan.RPMval[RPM_MIN]; 15ae: 80 91 3c 02 lds r24, 0x023C 15b2: 80 93 fb 01 sts 0x01FB, r24 *pb++ = cpuFan.RPMval[RPM_MED]; 15b6: 80 91 3d 02 lds r24, 0x023D 15ba: 80 93 fc 01 sts 0x01FC, r24 *pb++ = cpuFan.RPMval[RPM_MAX]; 15be: 80 91 3e 02 lds r24, 0x023E 15c2: 80 93 fd 01 sts 0x01FD, r24 *pb++ = cpuFan.minTEMPval; 15c6: 80 91 3f 02 lds r24, 0x023F 15ca: 80 93 fe 01 sts 0x01FE, r24 *pb++ = cpuFan.maxTEMPval; 15ce: 80 91 40 02 lds r24, 0x0240 15d2: 80 93 ff 01 sts 0x01FF, r24 *pb++ = rearFan.RPMval[RPM_MIN]; 15d6: 80 91 46 02 lds r24, 0x0246 15da: 80 93 00 02 sts 0x0200, r24 *pb++ = rearFan.RPMval[RPM_MED]; 15de: 80 91 47 02 lds r24, 0x0247 15e2: 80 93 01 02 sts 0x0201, r24 *pb++ = rearFan.RPMval[RPM_MAX]; 15e6: 80 91 48 02 lds r24, 0x0248 15ea: 80 93 02 02 sts 0x0202, r24 *pb++ = rearFan.minTEMPval; 15ee: 80 91 49 02 lds r24, 0x0249 15f2: 80 93 03 02 sts 0x0203, r24 *pb++ = rearFan.maxTEMPval; 15f6: 80 91 4a 02 lds r24, 0x024A 15fa: 80 93 04 02 sts 0x0204, r24 *pb++ = sideFan.RPMval[RPM_MIN]; 15fe: 80 91 50 02 lds r24, 0x0250 1602: 80 93 05 02 sts 0x0205, r24 *pb++ = sideFan.RPMval[RPM_MED]; 1606: 80 91 51 02 lds r24, 0x0251 160a: 80 93 06 02 sts 0x0206, r24 *pb++ = sideFan.RPMval[RPM_MAX]; 160e: 80 91 52 02 lds r24, 0x0252 1612: 80 93 07 02 sts 0x0207, r24 *pb++ = sideFan.minTEMPval; 1616: 80 91 53 02 lds r24, 0x0253 161a: 80 93 08 02 sts 0x0208, r24 *pb++ = sideFan.maxTEMPval; 161e: 80 91 54 02 lds r24, 0x0254 1622: 80 93 09 02 sts 0x0209, r24 *pb++ = frontFan.RPMval[RPM_MIN]; 1626: 80 91 5a 02 lds r24, 0x025A 162a: 80 93 0a 02 sts 0x020A, r24 *pb++ = frontFan.RPMval[RPM_MED]; 162e: 80 91 5b 02 lds r24, 0x025B 1632: 80 93 0b 02 sts 0x020B, r24 *pb++ = frontFan.RPMval[RPM_MAX]; 1636: 80 91 5c 02 lds r24, 0x025C 163a: 80 93 0c 02 sts 0x020C, r24 *pb++ = frontFan.minTEMPval; 163e: 80 91 5d 02 lds r24, 0x025D 1642: 80 93 0d 02 sts 0x020D, r24 *pb++ = frontFan.maxTEMPval; 1646: 80 91 5e 02 lds r24, 0x025E 164a: 80 93 0e 02 sts 0x020E, r24 164e: 10 e2 ldi r17, 0x20; 32 1650: cf e0 ldi r28, 0x0F; 15 1652: d2 e0 ldi r29, 0x02; 2 1654: 08 c0 rjmp .+16 ; 0x1666 <_Z16usartSendCommandhPKvh+0x24e> break; жаль, не догадался компилер использовать указатель А зря. Итог - внушительный, в два раза больший, размер функции. Также в коде есть одна немаленькая static inline функция, которая используется всего один раз (и то, понятно, инлайнится в тело вызывающей функции), но непонятно, почему остаётся её вторая копия? За короткое время знакомства с GCC понравилось: удобная реализация атомарности через макросы ATOMIC_BLOCK(), удобная обёртка для обработчиков прерываний вида ISR(vector_name){}. Что не понравилось: гиморрой с обработкой данных, расположенных во флеш - для их чтения необходимо использовать специальный макрос pgm_read_...(). В ИАРе достаточно объявить указатель типа __flash и можно работать с ним совершенно обычным образом Также не очень удобно каждый раз пользоваться PSTR() для обозначения in-line строк вида: printText(PSTR("some")). ИАР тут опять на высоте со своим __flash, так как подобная функция в нём декларируется как printText(char const __flash __flash * pointer), и вызов делается просто: printText("that`s cool")
|
|
|
|
|
Nov 24 2008, 19:57
|

Любитель
    
Группа: Свой
Сообщений: 1 864
Регистрация: 20-08-06
Из: Тольятти
Пользователь №: 19 695

|
Цитата(IgorKossak @ Nov 24 2008, 20:59)  Боком выйдет то, что локальные переменные располагаются в стеке, что для больших массивов неоправданно расточительно. Да нет, массив всего 32 байта размером. Самое место на стёке. Лишь бы не уничтожился раньше времени Цитата(IgorKossak @ Nov 24 2008, 20:59)  Разве в случае известных адресов оптимизация не нужна? Действительно. При наличии статических данных тупо юзается абсолютная адресация. Никакой толковой оптимизации. Эх, чем дольше я сравниваю IAR и GCC и чем больше лазию по генерируемому ими коду, тем больше убеждаюсь - не стоит ждать от них хорошего, наиболее приближенного к "ручному" ассемблеру коду. Косячат оба. У GCC, также, как и у IAR, часто в циклах попадаются "обёрточные" конструкции: Код movw r26, r16 st X+, r30 movw r16, r26 А также гну очень любит юзать в циклах копирования данных в качестве счётчиков итераций 16-ти битные слова (это даже если переменная изначально имеет 8 бит ширины  ). Точнее, "счётчика" как такового не создаётся, вычисление окончания идёт путём сравнения адреса одного из указателей. Это, конечно, универсальное решение, но в случае небольших циклов (до 256 итераций) неоправданно расходуется память и производительность... Раз уже сел за Си, то лучше всего взять камень "потолще", побыстрее, и не париться
|
|
|
|
|
Nov 24 2008, 23:45
|

Любитель
    
Группа: Свой
Сообщений: 1 864
Регистрация: 20-08-06
Из: Тольятти
Пользователь №: 19 695

|
Цитата(_Pasha @ Nov 25 2008, 01:56)  Вот так они, эти сишники и зомбируют. А что мешает узкие места прописывать асмом? Причем, не просто асмом, а асм+ срр... Ну если только совсем уж узкие Посмотрев как-то на инлайн-ассемблер я просто ужаснулся нагромождению скобок и кавычек: Код __asm__ __volatile__ ( "/* START EEPROM WRITE CRITICAL SECTION */\n\t" "in r0, %[__sreg] \n\t" "cli \n\t" "sbi %[__eecr], %[__eemwe] \n\t" "sbi %[__eecr], %[__eewe] \n\t" "out %[__sreg], r0 \n\t" "/* END EEPROM WRITE CRITICAL SECTION */" : : [__eecr] "i" (_SFR_IO_ADDR(EECR)), [__sreg] "i" (_SFR_IO_ADDR(SREG)), [__eemwe] "i" (EEMWE), [__eewe] "i" (EEWE) : "r0" ); Это не дело, так мучаться. А как делать правильно?
|
|
|
|
|
Nov 24 2008, 23:49
|
дятел
    
Группа: Свой
Сообщений: 1 681
Регистрация: 13-05-06
Из: Питер
Пользователь №: 17 065

|
Цитата(sonycman @ Nov 24 2008, 18:23)  жаль, не догадался компилер использовать указатель А зря. Итог - внушительный, в два раза больший, размер функции. А вы попробуйте чуть помочь компилятору примерно в таком ключе: Код unsigned char buffer[10];
typedef struct { unsigned char b0; unsigned char b1; } SimpleStruct;
typedef struct { unsigned char b0; unsigned char b1; unsigned char b2; unsigned char b3; unsigned char b4; SimpleStruct ss; unsigned char b5; unsigned char b6; unsigned char b7; unsigned char b8; } MyStruct;
MyStruct mystruct;
void copy(unsigned char *pd, MyStruct *ps) { MyStruct *p = ps; *pd++ = p->b7; *pd++ = p->b1; *pd++ = p->b5; *pd++ = p->ss.b0; *pd++ = p->b2; *pd++ = p->b0; *pd++ = p->ss.b1; *pd++ = p->b1; *pd++ = p->b3; *pd++ = p->b4; }
int main() { copy(buffer, &mystruct);
while (1); } И получите код ну никак не хуже IAR: Код void copy(unsigned char *pd, MyStruct *ps) { 5c: cf 93 push r28 5e: df 93 push r29 60: fc 01 movw r30, r24 62: db 01 movw r26, r22 MyStruct *p = ps; *pd++ = p->b7; 64: eb 01 movw r28, r22 66: 89 85 ldd r24, Y+9; 0x09 68: 81 93 st Z+, r24 *pd++ = p->b1; 6a: 89 81 ldd r24, Y+1; 0x01 6c: 81 93 st Z+, r24 *pd++ = p->b5; 6e: 8f 81 ldd r24, Y+7; 0x07 70: 81 93 st Z+, r24 *pd++ = p->ss.b0; 72: 8d 81 ldd r24, Y+5; 0x05 74: 81 93 st Z+, r24 *pd++ = p->b2; 76: 8a 81 ldd r24, Y+2; 0x02 78: 81 93 st Z+, r24 *pd++ = p->b0; 7a: 8c 91 ld r24, X 7c: 81 93 st Z+, r24 *pd++ = p->ss.b1; 7e: 8e 81 ldd r24, Y+6; 0x06 80: 81 93 st Z+, r24 *pd++ = p->b1; 82: 89 81 ldd r24, Y+1; 0x01 84: 81 93 st Z+, r24 *pd++ = p->b3; 86: 8b 81 ldd r24, Y+3; 0x03 88: 81 93 st Z+, r24 *pd++ = p->b4; 8a: 8c 81 ldd r24, Y+4; 0x04 8c: 80 83 st Z, r24 8e: df 91 pop r29 90: cf 91 pop r28 92: 08 95 ret Увы, у каждого компилятора свои фенечки...
|
|
|
|
|
Nov 25 2008, 09:51
|

Любитель
    
Группа: Свой
Сообщений: 1 864
Регистрация: 20-08-06
Из: Тольятти
Пользователь №: 19 695

|
Цитата(singlskv @ Nov 25 2008, 03:49)  Увы, у каждого компилятора свои фенечки...  Да, можно попробовать копировать структуры/массивы циклом, а не передавать их по одному... Скажите, а можно-ли копировать структуры таким образом: Код struct somestruct { byte a; byte b; byte c; byte d; byte e; byte f; } some;
byte size = sizeof(some); byte * ps = (byte*)&some; byte * pd = ... while (size--) *pd++ = *ps++; Или правильнее будет юзать массивы?
|
|
|
|
|
Nov 25 2008, 11:15
|
дятел
    
Группа: Свой
Сообщений: 1 681
Регистрация: 13-05-06
Из: Питер
Пользователь №: 17 065

|
Цитата(sonycman @ Nov 25 2008, 12:51)  Да, можно попробовать копировать структуры/массивы циклом, а не передавать их по одному...
Скажите, а можно-ли копировать структуры таким образом: Или правильнее будет юзать массивы? Можно по любому, я в своем примере просто показал что если сделать внешнюю функцию копирования и передавать указатель на буфер и на структуру, то gcc даже при перемешивании полей структуры в буфере будет делать компактный код: Код *pd++ = p->b1; 6a: 89 81 ldd r24, Y+1; 0x01 6c: 81 93 st Z+, r24 *pd++ = p->b5; 6e: 8f 81 ldd r24, Y+7; 0x07 70: 81 93 st Z+, r24 то есть вобще без LDS и STS и с использованием 2x указателей.
|
|
|
|
|
Nov 25 2008, 17:27
|

Любитель
    
Группа: Свой
Сообщений: 1 864
Регистрация: 20-08-06
Из: Тольятти
Пользователь №: 19 695

|
Цитата(demiurg_spb @ Nov 25 2008, 14:51)  Следует уяснить себе раз и навсегда, что структура или какой-либо иной объект не является таким уж абстрактным, а занимает конкретный блок той или иной памяти размером sizeof(object) выделенный под её хранение (представление). Это всё понятно. Но дело в том, что эти данные будут копироваться на PC в подобные им структуры. Есть-ли гарантия того, что размер этих структур будет одинаков? Особенно, если в структуре будут различные размеру данные? И особенно, если учесть, что программы написаны в разных компиляторах...
|
|
|
|
|
Nov 25 2008, 20:30
|

неотягощённый злом
     
Группа: Свой
Сообщений: 2 746
Регистрация: 31-01-08
Из: Санкт-Петербург
Пользователь №: 34 643

|
Цитата(sonycman @ Nov 25 2008, 20:27)  Это всё понятно. Но дело в том, что эти данные будут копироваться на PC в подобные им структуры. Есть-ли гарантия того, что размер этих структур будет одинаков? Особенно, если в структуре будут различные размеру данные? И особенно, если учесть, что программы написаны в разных компиляторах... Совершенно неважно какой компилятор Вы используете. В каждом из них имеются свои средства задающие размер блока на который происходит выравнивание полей структуры. К примеру для borland'a можно использовать прагмы или задавать через параметры проекта. Код #pragma pack(push,1) // Выравнивание полей структур = 1 байт.
typedef struct { float Amplifier[3]; float Bias[3]; } TInputConfig;
#pragma pack(pop) // возврат к выравниванию "по умолчанию" Цитата(Сергей Борщ @ Nov 25 2008, 18:40)  А если быть точно уверенным, что размер структуры никогда не будет равным нулю, то можно и do *dst++ = *src++; while (--size); - код должен быть еще компактнее. Но быть точно уверенным не всегда получается, а так я с Вами полностью согласен.
--------------------
“Будьте внимательны к своим мыслям - они начало поступков” (Лао-Цзы)
|
|
|
|
|
Nov 26 2008, 06:43
|
Знающий
   
Группа: Свой
Сообщений: 771
Регистрация: 16-07-07
Из: Волгодонск
Пользователь №: 29 153

|
Цитата(Сергей Борщ @ Nov 25 2008, 18:40)  А если быть точно уверенным, что размер структуры никогда не будет равным нулю ... Насколько я понимаю, размер структуры никогда не будет равен 0. Размер пустой структуры struct A {}; - 1 байт. Сделано для того, чтобы не порушить операции с указателями на массиве таких структур. Оптимизация пустых структур идет в некоторых случаях в С++ при наследовании. например, struct A {}; struct B : A {}; обычно за счет такой оптимизации sizeof( B )==sizeof( A ).
|
|
|
|
|
Dec 11 2008, 01:50
|

кекс
     
Группа: Свой
Сообщений: 3 825
Регистрация: 17-12-05
Из: Киев
Пользователь №: 12 326

|
Цитата(sonycman @ Nov 25 2008, 19:27)  Есть-ли гарантия того, что размер этих структур будет одинаков? Размер одной и той же структуры может изменяться взависимости от правил выравнивания (Alignment). Для 8-ми битных процов каковым есть AVR - выравнивание обычно - 1 (на границу байта). А вот на PC выравнивание может быть 4 (на границу DWORD, Win32), 2 (WORD под DOS), 8 (QWORD под Win64). В многих компиляторах (не только C и C++) выравнивание полей на границу байта задается ключевым словом packed/__packed. например: __packed struct tagSOME_STRUCT { .... } ...; Но может задаваться и по-другому, см. описание конкретного компилятора на тему как задать выравнивание струтуры (ключевые слова для поиска "Alignment/Align/Pack/Packed").
|
|
|
|
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|