Перейти к содержанию
    

Компилю текст:

#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? или я что-то не так пишу или хваленый иар не спосбен на подвиги?

ЧТО Я НЕ ТАК ДЕЛАЮ?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Не пойму почему бы ему не использовать STS? или я что-то не так пишу или хваленый иар не спосбен на подвиги?

 

Похоже, всё-таки не способен...

 

Вот как это скомпилировал 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

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Ещё немного сравнительных результатов от 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

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Кстати,

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?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Кстати,

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?

 

Да, практически так же:

  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;
}

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Задал этот вопрос (почему через указатели а не через 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" ориентирован на иаровский компилятор.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Кстати,

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.

Сейчас взглянул на прологи/эпилоги и Ужаснулся.

Не стОит так переживать из-за этой мелочи. Она погоду не делает совершенно. Наоборот, способность IAR'а приводить обращения к косвенным дает очень приличный выигрыш на деле. AVR-GCC имеет весьма неплохой кодогенератор, но он проигрывает IAR'у именно на этом моменте - AVR-GCC злоупотребляет lds/sts, из-за чего размер кода там получается больше.

 

Не знаю, как сегодня обстоит дело, но некоторое время назад остальные компляторы - CodeVision, ImageCraft уступали по качеству кодогенерации обоим - и IAR'у, и AVR-GCC. Может сейчас что-то изменилось, но сомневаюсь. Сравнивать надо не на коде из трех строк, а на реальных проектах. Попробуйте, увидите, что IAR рулит. :)

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

 

Не стОит так переживать из-за этой мелочи. Она погоду не делает совершенно. Наоборот, способность IAR'а приводить обращения к косвенным дает очень приличный выигрыш на деле. AVR-GCC имеет весьма неплохой кодогенератор, но он проигрывает IAR'у именно на этом моменте - AVR-GCC злоупотребляет lds/sts, из-за чего размер кода там получается больше.

 

 

Но прерывание ИАР слишком раздул, а надо то тока инкрементировать глобальную переменную. кстати это системный таймер и я думаю, что там не одна переменная может быть, но и несколько, а если они не подряд - то работа с указателями это только проигрыш.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Но прерывание ИАР слишком раздул, а надо то тока инкрементировать глобальную переменную. кстати это системный таймер и я думаю, что там не одна переменная может быть, но и несколько, а если они не подряд - то работа с указателями это только проигрыш.

Ну и сколько это байт оверхеда на фоне всего проекта? Сравнивайте весь проект (или хотя бы более-менее значимую часть), скомпиленные одним компиятором и другим.

 

Переменным не обязательно быть подряд. Им достаточно быть в пределах досягаемости указателя - 64 байта. Для того, чтобы они были вместе, достаточно их объявить вместе и включить оптимизацию clustering variables, которая, afair, включена по умолчанию.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Но прерывание ИАР слишком раздул, а надо то тока инкрементировать глобальную переменную. кстати это системный таймер и я думаю, что там не одна переменная может быть, но и несколько, а если они не подряд - то работа с указателями это только проигрыш.

Ну и сколько это байт оверхеда на фоне всего проекта? Сравнивайте весь проект (или хотя бы более-менее значимую часть), скомпиленные одним компиятором и другим.

 

Переменным не обязательно быть подряд. Им достаточно быть в пределах досягаемости указателя - 64 байта. Для того, чтобы они были вместе, достаточно их объявить вместе и включить оптимизацию clustering variables, которая, afair, включена по умолчанию.

 

ну что ж: вот расстояние между байтами 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

 

 

В чем дело то? может у меня завихрения?

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

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Это до тех пор, пока у Вас единственное обращение к однобайтовой переменной. Сделайте эту переменную интом, выигрыш не замедлит проявиться. Или, к примеру, если там не к одной переменной обращение, а к нескольким, лежащим в пределах досягаемости указателя (для этого их надо объявлять вместе). Или к структуре обращение. Словом, когда ситуация уходить от первого простейшего случая, результат меняется

Черт меня дернул сделать проект на IAR.

Сейчас взглянул на прологи/эпилоги и Ужаснулся.

Не стОит так переживать из-за этой мелочи. Она погоду не делает совершенно. Наоборот, способность IAR'а приводить обращения к косвенным дает очень приличный выигрыш на деле. AVR-GCC имеет весьма неплохой кодогенератор, но он проигрывает IAR'у именно на этом моменте - AVR-GCC злоупотребляет lds/sts, из-за чего размер кода там получается больше.

 

Не знаю, как сегодня обстоит дело, но некоторое время назад остальные компляторы - CodeVision, ImageCraft уступали по качеству кодогенерации обоим - и IAR'у, и AVR-GCC. Может сейчас что-то изменилось, но сомневаюсь. Сравнивать надо не на коде из трех строк, а на реальных проектах. Попробуйте, увидите, что IAR рулит. :)

 

Прямо сейчас скомпилировал реальный проект средних размеров на меге162.

Результаты:

                     speed    size
CodeVision:        12956    12580
IAR:               12394    11182

Как видим, выигрыш не так уж велик.

Лично меня CodeVision привлекает тем, что генерирует предсказуемый код, отлично интегрируется с ассемблером, а также лучше IAR'а использует аппаратные ресурсы AVR.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

ну что ж: вот расстояние между байтами 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. Т.е. достаточно, чтобы оба объявления были доступны компилятору в одной единице компиляции.

 

 

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

Если Вам мало быстродействия, при этом у Вас просто инкремент байта - напишите это на асме и не страдайте. Я не спорю с тем, что в данном конкретном случае IAR делает не лучшим образом - злоупотреляет переходами к косвенным обращениям, - но поверьте, в целом зачастую именно это дает ему значимое преимущество.

 

Об этом их backfire следует сообщить разработчикам, чтобы они в дальнейшем поработали над поведением компилятора в ISR. Хотя, думается, что если до сих пор не исправили, то это по той причине, что никого [из пользователей] этот факт особенно не волнует. Ведь и в самом деле, если работоспособность и устойчивость системы зависит от пары тактов, то тут явно что-то не то в дизайне. Всегда должен быть какой-то запас. На устойчивость. На развитие. В конечном итоге все упирается в "успевает - не успевает". Если один успевает на три такта быстрее, чем успевает другой, то конечный результат будет одним и тем же.

 

Понятно, что хочется получить результат по максисмуму, но надо быть реалистами. Ни один МК, ни один компилятор не может быть лучше других по всем пунктам. Если бы это было так, то мы сейчас уже давно имели один МК и один компилятор для него.. :) По совокупности надо смотреть. И сравнивать тоже по совокупности.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Прямо сейчас скомпилировал реальный проект средних размеров на меге162.

Результаты:

                     speed    size
CodeVision:        12956    12580
IAR:               12394    11182

Как видим, выигрыш не так уж велик.

Но он есть! :) И по скорости, и по размеру кода. Несмотря на несуразности в ISR. И не такой уж маленький. Почти 5% в первом случае и более 12 во втором. Представте, что проект занимает не 12 кил, а 15. Тут уже вопрос встает - "влезет/не влезет", а это серьезно.

 

Кстати, для МК этого калибра размер проекта не такой маленький. Неужели можно так просто взять реальный проект и пересобрать другим пакетом?! Там же куча тулзозависимых вещей типа директив компилятора, расширенных ключевых слов и прочего. Т.е. требуется основательная доработка напильником.

 

Лично меня CodeVision привлекает там, что генерирует предсказуемый код,

Что непредсказуемого в кодогенерации у IAR?

отлично интегрируется с ассемблером,

Не понял, что имеется в виду.

 

а также лучше IAR'а использует аппаратные ресурсы AVR.

Опять, простите, не понял. Какие ресурсы? В чем "лучшесть"?

 

Кстати, сравнивать эти два компилятора в некотором роде не совсем корректно - IAR несравненно богаче по возможностям - там есть ++. Это дорогого стОит. Предвижу возражение, что Вам это не надо. Не надо, так не надо. А мне надо. И весьма. Я не агитирую за IAR, не предлагаю бросить используемый инструмент и переходить на него. Смысл всего сказанного в том, что на сегодняшний день в целом IAR (при всех его недостатках) объективно является лучшим пакетом для AVR.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Присоединяйтесь к обсуждению

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

Гость
К сожалению, ваш контент содержит запрещённые слова. Пожалуйста, отредактируйте контент, чтобы удалить выделенные ниже слова.
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...