LeoLabs 0 16 июня, 2005 Опубликовано 16 июня, 2005 · Жалоба Компилю текст: #pragma vector = TIMER2_OVF_vect __interrupt void system_timer() { blink_timer++; } и выдает: #pragma vector = TIMER2_OVF_vect __interrupt void system_timer() ST -Y, R31 ST -Y, R30 ST -Y, R17 ST -Y, R16 IN R17, 0x3F } blink_timer++; LDI R30, LOW(blink_timer) LDI R31, (blink_timer) >> 8 LD R16, Z INC R16 ST Z, R16 } OUT 0x3F, R17 LD R16, Y+ LD R17, Y+ LD R30, Y+ LD R31, Y+ RETI при максимальной оптимизации. Не пойму почему бы ему не использовать STS? или я что-то не так пишу или хваленый иар не спосбен на подвиги? ЧТО Я НЕ ТАК ДЕЛАЮ? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
vet 0 16 июня, 2005 Опубликовано 16 июня, 2005 · Жалоба Не пойму почему бы ему не использовать STS? или я что-то не так пишу или хваленый иар не спосбен на подвиги? <{POST_SNAPBACK}> Похоже, всё-таки не способен... Вот как это скомпилировал CodeVision, для сравнения: 26 char blink_timer; ;27 ;28 // Timer 0 output compare A interrupt service routine ;29 interrupt [TIM0_COMPA] void timer0_compa_isr(void) ;30 { .CSEG _timer0_compa_isr: ST -Y,R30 IN R30,SREG ;31 blink_timer++; INC R2 ;32 } OUT SREG,R30 LD R30,Y+ RETI вариант с переменной в памяти: ;26 volatile char blink_timer; _blink_timer: .BYTE 0x1 ;27 ;28 // Timer 0 output compare A interrupt service routine ;29 interrupt [TIM0_COMPA] void timer0_compa_isr(void) ;30 { .CSEG _timer0_compa_isr: ST -Y,R30 IN R30,SREG ST -Y,R30 ;31 blink_timer++; LDS R30,_blink_timer SUBI R30,-LOW(1) STS _blink_timer,R30 ;32 } LD R30,Y+ OUT SREG,R30 LD R30,Y+ RETI Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
LeoLabs 0 17 июня, 2005 Опубликовано 17 июня, 2005 · Жалоба не верю! ну не может такого быть! Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
vet 0 17 июня, 2005 Опубликовано 17 июня, 2005 · Жалоба Ещё немного сравнительных результатов от ICC v6.30C и GCC 20040720 соответственно: ; char blink_timer; ; #pragma interrupt_handler timer:4 timer:5 ; void timer() { .dbline 44 ; blink_timer++; lds R24,_blink_timer subi R24,255 ; addi 1 sts _blink_timer,R24 .dbline -2 L7: ld R24,y+ out 0x3f,R24 ld R25,y+ ld R24,y+ .dbline 0; func end reti ;char blink_timer; ;SIGNAL (SIG_OVERFLOW1) ;{ ; blink_timer++; ;} .LM1: /* prologue: frame size=0 */ push __zero_reg__ push __tmp_reg__ in __tmp_reg__,__SREG__ push __tmp_reg__ clr __zero_reg__ push r24 /* prologue end (size=6) */ .stabn 68,0,69,.LM2-__vector_14 .LM2: lds r24,blink_timer subi r24,lo8(-(1)) sts blink_timer,r24 /* epilogue: frame size=0 */ pop r24 pop __tmp_reg__ out __SREG__,__tmp_reg__ pop __tmp_reg__ pop __zero_reg__ reti Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
AlexOr 0 20 июня, 2005 Опубликовано 20 июня, 2005 · Жалоба Нет слов. Только маты. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
AlexOr 0 20 июня, 2005 Опубликовано 20 июня, 2005 · Жалоба Кстати, LDI R30, LOW(blink_timer) LDI R31, (blink_timer) >> 8 LD R16, Z INC R16 ST Z, R16 занимает столько же места как и LDS R30,_blink_timer SUBI R30,-LOW(1) STS _blink_timer,R30 но последнее в прерывании намного выгоднее (быстрее и менее расходно по регистрам). Черт меня дернул сделать проект на IAR. Сейчас взглянул на прологи/эпилоги и Ужаснулся. Вопрос вдогонку: Этот замечательный CodeVision умеет также легко работать с EEPROM как IAR? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
vet 0 20 июня, 2005 Опубликовано 20 июня, 2005 · Жалоба Кстати, LDI R30, LOW(blink_timer) LDI R31, (blink_timer) >> 8 LD R16, Z INC R16 ST Z, R16 занимает столько же места как и LDS R30,_blink_timer SUBI R30,-LOW(1) STS _blink_timer,R30 но последнее в прерывании намного выгоднее (быстрее и менее расходно по регистрам). Черт меня дернул сделать проект на IAR. Сейчас взглянул на прологи/эпилоги и Ужаснулся. Вопрос вдогонку: Этот замечательный CodeVision умеет также легко работать с EEPROM как IAR? <{POST_SNAPBACK}> Да, практически так же: eeprom struct tag_conf { char block; char RegionString[16]; char data[64]; } eeConf; unsigned int char CheckEEPROM(void) { //вычисление контрольной суммы структуры eeConf в EEPROM char eeprom *p; unsigned int sum; char i; sum = 0; p = &eeConf; for (i=0; i<sizeof(eeConf); i++) sum += *p++; return sum; } Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
LeoLabs 0 21 июня, 2005 Опубликовано 21 июня, 2005 · Жалоба Задал этот вопрос (почему через указатели а не через STS) разработчикам, жду ответа, но т.к. у меня нет лицензии ждать придется долго, если вообще дождусь. Но что я накопал: в applications notes лежит pdfник "Efficient C Coding for AVR". наткнулся я там на следующее: When accessing the global variables as structures the compiler is using the Z-pointer and the LDD and STD (Load/store with displacement) instructions to access the data. When the global variables are accessed without structures the compiler use LDS and STS (Load/store direct to SRAM). , что по-русски значит: если переменная объявлена как структура, то компилятор будет использовать указатели, если нет то через LDS и STS. вот такие дела. однако переменная у меня объявлена: unsigned char blink_timer = 0; где не вижу я структуры. , еще не стоит я думаю горячиться по поводу прологов, эпилогов и т.п. Не редко проблемы с компилятором называются "сам дурак". P.S. pdfник "Efficient C Coding for AVR" ориентирован на иаровский компилятор. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
dxp 56 21 июня, 2005 Опубликовано 21 июня, 2005 · Жалоба Кстати, LDI R30, LOW(blink_timer) LDI R31, (blink_timer) >> 8 LD R16, Z INC R16 ST Z, R16 занимает столько же места как и LDS R30,_blink_timer SUBI R30,-LOW(1) STS _blink_timer,R30 но последнее в прерывании намного выгоднее (быстрее и менее расходно по регистрам). Это до тех пор, пока у Вас единственное обращение к однобайтовой переменной. Сделайте эту переменную интом, выигрыш не замедлит проявиться. Или, к примеру, если там не к одной переменной обращение, а к нескольким, лежащим в пределах досягаемости указателя (для этого их надо объявлять вместе). Или к структуре обращение. Словом, когда ситуация уходить от первого простейшего случая, результат меняется Черт меня дернул сделать проект на IAR. Сейчас взглянул на прологи/эпилоги и Ужаснулся. <{POST_SNAPBACK}> Не стОит так переживать из-за этой мелочи. Она погоду не делает совершенно. Наоборот, способность IAR'а приводить обращения к косвенным дает очень приличный выигрыш на деле. AVR-GCC имеет весьма неплохой кодогенератор, но он проигрывает IAR'у именно на этом моменте - AVR-GCC злоупотребляет lds/sts, из-за чего размер кода там получается больше. Не знаю, как сегодня обстоит дело, но некоторое время назад остальные компляторы - CodeVision, ImageCraft уступали по качеству кодогенерации обоим - и IAR'у, и AVR-GCC. Может сейчас что-то изменилось, но сомневаюсь. Сравнивать надо не на коде из трех строк, а на реальных проектах. Попробуйте, увидите, что IAR рулит. :) Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
LeoLabs 0 21 июня, 2005 Опубликовано 21 июня, 2005 · Жалоба Не стОит так переживать из-за этой мелочи. Она погоду не делает совершенно. Наоборот, способность IAR'а приводить обращения к косвенным дает очень приличный выигрыш на деле. AVR-GCC имеет весьма неплохой кодогенератор, но он проигрывает IAR'у именно на этом моменте - AVR-GCC злоупотребляет lds/sts, из-за чего размер кода там получается больше. <{POST_SNAPBACK}> Но прерывание ИАР слишком раздул, а надо то тока инкрементировать глобальную переменную. кстати это системный таймер и я думаю, что там не одна переменная может быть, но и несколько, а если они не подряд - то работа с указателями это только проигрыш. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
dxp 56 21 июня, 2005 Опубликовано 21 июня, 2005 · Жалоба Но прерывание ИАР слишком раздул, а надо то тока инкрементировать глобальную переменную. кстати это системный таймер и я думаю, что там не одна переменная может быть, но и несколько, а если они не подряд - то работа с указателями это только проигрыш. <{POST_SNAPBACK}> Ну и сколько это байт оверхеда на фоне всего проекта? Сравнивайте весь проект (или хотя бы более-менее значимую часть), скомпиленные одним компиятором и другим. Переменным не обязательно быть подряд. Им достаточно быть в пределах досягаемости указателя - 64 байта. Для того, чтобы они были вместе, достаточно их объявить вместе и включить оптимизацию clustering variables, которая, afair, включена по умолчанию. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
LeoLabs 0 21 июня, 2005 Опубликовано 21 июня, 2005 · Жалоба Но прерывание ИАР слишком раздул, а надо то тока инкрементировать глобальную переменную. кстати это системный таймер и я думаю, что там не одна переменная может быть, но и несколько, а если они не подряд - то работа с указателями это только проигрыш. <{POST_SNAPBACK}> Ну и сколько это байт оверхеда на фоне всего проекта? Сравнивайте весь проект (или хотя бы более-менее значимую часть), скомпиленные одним компиятором и другим. Переменным не обязательно быть подряд. Им достаточно быть в пределах досягаемости указателя - 64 байта. Для того, чтобы они были вместе, достаточно их объявить вместе и включить оптимизацию clustering variables, которая, afair, включена по умолчанию. <{POST_SNAPBACK}> ну что ж: вот расстояние между байтами 19, а как обрабатывается - при полной оптимизации, включая Clustering of variables. 5 #pragma vector = TIMER2_OVF_vect \ In segment CODE, align 2, keep-with-next 6 __interrupt void system_timer(void) \ system_timer: 7 { \ 00000000 93FA ST -Y, R31 \ 00000002 93EA ST -Y, R30 \ 00000004 931A ST -Y, R17 \ 00000006 930A ST -Y, R16 \ 00000008 B71F IN R17, 0x3F 8 blink_timer++; \ 0000000A .... LDI R30, 0x66 \ 0000000C .... LDI R31, 0x01 \ 0000000E 8100 LD R16, Z \ 00000010 9503 INC R16 \ 00000012 8300 ST Z, R16 9 mySREG++; \ 00000014 .... LDI R30, 0x79 \ 00000016 .... LDI R31, 0x01 \ 00000018 8100 LD R16, Z \ 0000001A 9503 INC R16 \ 0000001C 8300 ST Z, R16 10 } \ 0000001E BF1F OUT 0x3F, R17 \ 00000020 9109 LD R16, Y+ \ 00000022 9119 LD R17, Y+ \ 00000024 91E9 LD R30, Y+ \ 00000026 91F9 LD R31, Y+ \ 00000028 9518 RETI В чем дело то? может у меня завихрения? да и в прерываниях, которые очень критичны к скорости, совсем ни к чему указатели. а по поводу памяти - то ее почти всегда хватит, напротив быстродействия всегда мало. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
vet 0 21 июня, 2005 Опубликовано 21 июня, 2005 · Жалоба Это до тех пор, пока у Вас единственное обращение к однобайтовой переменной. Сделайте эту переменную интом, выигрыш не замедлит проявиться. Или, к примеру, если там не к одной переменной обращение, а к нескольким, лежащим в пределах досягаемости указателя (для этого их надо объявлять вместе). Или к структуре обращение. Словом, когда ситуация уходить от первого простейшего случая, результат меняется Черт меня дернул сделать проект на IAR. Сейчас взглянул на прологи/эпилоги и Ужаснулся. <{POST_SNAPBACK}> Не стОит так переживать из-за этой мелочи. Она погоду не делает совершенно. Наоборот, способность IAR'а приводить обращения к косвенным дает очень приличный выигрыш на деле. AVR-GCC имеет весьма неплохой кодогенератор, но он проигрывает IAR'у именно на этом моменте - AVR-GCC злоупотребляет lds/sts, из-за чего размер кода там получается больше. Не знаю, как сегодня обстоит дело, но некоторое время назад остальные компляторы - CodeVision, ImageCraft уступали по качеству кодогенерации обоим - и IAR'у, и AVR-GCC. Может сейчас что-то изменилось, но сомневаюсь. Сравнивать надо не на коде из трех строк, а на реальных проектах. Попробуйте, увидите, что IAR рулит. :) <{POST_SNAPBACK}> Прямо сейчас скомпилировал реальный проект средних размеров на меге162. Результаты: speed size CodeVision: 12956 12580 IAR: 12394 11182 Как видим, выигрыш не так уж велик. Лично меня CodeVision привлекает тем, что генерирует предсказуемый код, отлично интегрируется с ассемблером, а также лучше IAR'а использует аппаратные ресурсы AVR. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
dxp 56 21 июня, 2005 Опубликовано 21 июня, 2005 · Жалоба ну что ж: вот расстояние между байтами 19, а как обрабатывается - при полной оптимизации, включая Clustering of variables. Непонятно, как Вы объявили переменные. Нужно, чтобы они были вместе объявлены, чтобы компилятор видел их одновременно. Если они в разных файлах объявлены, то, ессно, компилятор тут ничего поделать не сможет (даже если они реально попали в предел 64 байта один от другого), т.к. просто не знает, что они рядом и не может рулить их размещением. А вот как это получается: char blink_timer1; char buf[200]; char blink_timer2; #pragma vector = TIMER2_OVF_vect __interrupt void system_timer() { blink_timer1++; blink_timer2++; } результат: __interrupt void system_timer() ??system_timer: { 93FA ST -Y, R31 93EA ST -Y, R30 931A ST -Y, R17 930A ST -Y, R16 B71F IN R17, 0x3F blink_timer1++; .... LDI R30, LOW(blink_timer1) .... LDI R31, (blink_timer1) >> 8 8100 LD R16, Z 9503 INC R16 8300 ST Z, R16 blink_timer2++; 8101 LDD R16, Z+1 9503 INC R16 8301 STD Z+1, R16 } BF1F OUT 0x3F, R17 9109 LD R16, Y+ 9119 LD R17, Y+ 91E9 LD R30, Y+ 91F9 LD R31, Y+ 9518 RETI Заметьте, что смещение при обращении ко второй переменной равно 1, несмотря на то, что при объявлении между ними массив в 200 байт. Т.е. компилятор эффективно расположил обе переменные последовательно - имеет право. Это и есть clustering variables. Т.е. достаточно, чтобы оба объявления были доступны компилятору в одной единице компиляции. да и в прерываниях, которые очень критичны к скорости, совсем ни к чему указатели. а по поводу памяти - то ее почти всегда хватит, напротив быстродействия всегда мало. <{POST_SNAPBACK}> Если Вам мало быстродействия, при этом у Вас просто инкремент байта - напишите это на асме и не страдайте. Я не спорю с тем, что в данном конкретном случае IAR делает не лучшим образом - злоупотреляет переходами к косвенным обращениям, - но поверьте, в целом зачастую именно это дает ему значимое преимущество. Об этом их backfire следует сообщить разработчикам, чтобы они в дальнейшем поработали над поведением компилятора в ISR. Хотя, думается, что если до сих пор не исправили, то это по той причине, что никого [из пользователей] этот факт особенно не волнует. Ведь и в самом деле, если работоспособность и устойчивость системы зависит от пары тактов, то тут явно что-то не то в дизайне. Всегда должен быть какой-то запас. На устойчивость. На развитие. В конечном итоге все упирается в "успевает - не успевает". Если один успевает на три такта быстрее, чем успевает другой, то конечный результат будет одним и тем же. Понятно, что хочется получить результат по максисмуму, но надо быть реалистами. Ни один МК, ни один компилятор не может быть лучше других по всем пунктам. Если бы это было так, то мы сейчас уже давно имели один МК и один компилятор для него.. :) По совокупности надо смотреть. И сравнивать тоже по совокупности. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
dxp 56 21 июня, 2005 Опубликовано 21 июня, 2005 · Жалоба Прямо сейчас скомпилировал реальный проект средних размеров на меге162. Результаты: speed size CodeVision: 12956 12580 IAR: 12394 11182 Как видим, выигрыш не так уж велик. Но он есть! :) И по скорости, и по размеру кода. Несмотря на несуразности в ISR. И не такой уж маленький. Почти 5% в первом случае и более 12 во втором. Представте, что проект занимает не 12 кил, а 15. Тут уже вопрос встает - "влезет/не влезет", а это серьезно. Кстати, для МК этого калибра размер проекта не такой маленький. Неужели можно так просто взять реальный проект и пересобрать другим пакетом?! Там же куча тулзозависимых вещей типа директив компилятора, расширенных ключевых слов и прочего. Т.е. требуется основательная доработка напильником. Лично меня CodeVision привлекает там, что генерирует предсказуемый код, Что непредсказуемого в кодогенерации у IAR? отлично интегрируется с ассемблером, Не понял, что имеется в виду. а также лучше IAR'а использует аппаратные ресурсы AVR. <{POST_SNAPBACK}> Опять, простите, не понял. Какие ресурсы? В чем "лучшесть"? Кстати, сравнивать эти два компилятора в некотором роде не совсем корректно - IAR несравненно богаче по возможностям - там есть ++. Это дорогого стОит. Предвижу возражение, что Вам это не надо. Не надо, так не надо. А мне надо. И весьма. Я не агитирую за IAR, не предлагаю бросить используемый инструмент и переходить на него. Смысл всего сказанного в том, что на сегодняшний день в целом IAR (при всех его недостатках) объективно является лучшим пакетом для AVR. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться