| Микроконтроллеры, АЦП, память и т.д Темы касающиеся микроконтроллеров разных производителей, памяти, АЦП/ЦАП, периферийных модулей... |
Может ли меняться логика откомпилированной программы при использовании разных режимов оптимизации?
14.07.2010, 01:40
|
|
|
Почётный гражданин KAZUS.RUN
Регистрация: 13.12.2004
Сообщений: 3,168
Сказал спасибо: 11
Сказали Спасибо 691 раз(а) в 503 сообщении(ях)
|
Re: Может ли меняться логика откомпилированной программы при использовании разных режимов оптимизации?
Сообщение от Godzilla82
|
|
Это при том, что некоторые говорят, что в CodeVision всё работает медленно и печально...
|
Вы видимо удивитесь, но
|
Код:
|
PORTD |= (1‹‹PD4); //GCC
PORTD.4 = 1; //CV |
Работают ровно одинаковое время.
Возьмите нормальный тест.
Ну например
|
Код:
|
volatile unsigned char ii = 0;
volatile double a = 5.0;
volatile double b = 25.0;
volatile double c;
void CalcC(void)
{
c = a * b;
}
int main(void)
{
CalcC();
while(1)
{
ii++;
}
} |
Сколько тактов в CV выполняется CalcC? GCC - 156.
Тоже вроде простейший тест. Под мегу 8.
Вообще посмотрите https://kazus.run/forums/showthread.php?t=13936
Я там похожей фигней занимался. Правда тестировался ИАР в основном в сравнении с GCC, но кое где и для CV результаты есть.
Кстати - посмотрите листинг от CV с Вашим примером. CV count держит в регистрах! Т.е. переменная совсем не глобальная. Попробуйте добавить обработчик прерывания, где будет использоваться count. И померяйте такты снова. Это кстати офигенный хомут, код из под CV не верный! И еще - для увеличения/уменьшения count служит
|
Код:
|
000083 01f1 MOVW R30,R2
000084 9631 ADIW R30,1
_0xB:
000085 011f MOVW R2,R30 |
Но нигде в коде R31 не обнулялся! Там при включении мусор может быть. В железе ес-но, не в симуляторе. Да и вообще непонятно есть ли старший байт у count или нет. CV похоже на эту переменную просто забил.
И собирайте с отладочной инфой, шагать по дизассемблеру не комфортно.
И версию CV огласите - чтоб пересобрать можно было.
Последний раз редактировалось kison; 14.07.2010 в 02:32.
|
|
|
|
14.07.2010, 03:58
|
|
|
Почётный гражданин KAZUS.RUN
Регистрация: 29.10.2006
Сообщений: 1,449
Сказал спасибо: 99
Сказали Спасибо 318 раз(а) в 234 сообщении(ях)
|
Re: Может ли меняться логика откомпилированной программы при использовании разных режимов оптимизации?
Сообщение от kison
|
Кстати - посмотрите листинг от CV с Вашим примером. CV count держит в регистрах! Т.е. переменная совсем не глобальная. Попробуйте добавить обработчик прерывания, где будет использоваться count. И померяйте такты снова.
...
Но нигде в коде R31 не обнулялся! Там при включении мусор может быть. В железе ес-но, не в симуляторе. Да и вообще непонятно есть ли старший байт у count или нет. CV похоже на эту переменную просто забил.
И собирайте с отладочной инфой, шагать по дизассемблеру не комфортно.
И версию CV огласите - чтоб пересобрать можно было.
|
Есть реальная железка. В ней по прерыванию от USI передаются данные count. Передаёт оба байта. И старший, и младший. И количество тактов там - 20/28. И всё работает корректно.
По большому счёту, мне абсолютно пофиг, где и в чём хранит CVAVR значение переменной count. Факт в том, что в данном случае код, который даёт CVAVR работает быстрее на 5 тактов. Это на 15% быстрее WinAVR...
Ладно, может это и не существенно. Но! CVAVR предсказуем и даёт стабильный результат, не зависящий от оптимизации. Чего нельзя сказать про WinAVR. Там приходится шаманить...
Вот есть функции отправки/приёма байта по SPI (для меги 64):
|
Код:
|
void SPI_Write_Byte (unsigned char byte)
{
SPDR = byte;
while (!(SPSR & _BV(7)));
}
unsigned char SPI_Read_Byte (void)
{
SPDR = 0;
while (!(SPSR & _BV(7)));
return(SPDR);
} |
При включении оптимизации код перестаёт работать. До уровня ассемблера и команд не вникал. Но момент неприятный.
А без оптимизации размер кода возрастает в разы, не говоря уже про быстродействие... Вот уж действительно, печально: быстро (не работает), медленно (от чего само по себе не весело)
P.S. CodeVision AVR v1.25.9
Последний раз редактировалось Godzilla82; 14.07.2010 в 04:04.
|
|
|
|
14.07.2010, 06:13
|
|
|
Почётный гражданин KAZUS.RUN
Регистрация: 13.12.2004
Сообщений: 3,168
Сказал спасибо: 11
Сказали Спасибо 691 раз(а) в 503 сообщении(ях)
|
Re: Может ли меняться логика откомпилированной программы при использовании разных режимов оптимизации?
Сообщение от Godzilla82
|
|
Есть реальная железка. В ней по прерыванию от USI передаются данные count. Передаёт оба байта. И старший, и младший. И количество тактов там - 20/28. И всё работает корректно.
|
Конечно разместив count в регистрах можно сэкономить. Пока в программе две-три переменных. Стоит же ей чуть подрасти, и тактов станет резко больше.
Ну вот Вам такой же вариант под GCC
|
Код:
|
************************************************** **/
#define F_CPU 10000000UL
#include ‹avr/io.h›
#include ‹util/delay.h›
register volatile unsigned int count asm("r4");
int main(void)
{
char a;
char b;
char c=1;
char d=0;
char t;
char pa=0;
char pb=0;
PORTA=0x00;
DDRA=0x00;
PORTB=0x00;
DDRB=0x00;
PORTD=0x00;
DDRD=0x01;
TCCR0A=0x00;
TCCR0B=0x00;
TCNT0=0x00;
OCR0A=0x00;
OCR0B=0x00;
TCCR1A=0x00;
TCCR1B=0x00;
TCNT1H=0x00;
TCNT1L=0x00;
ICR1H=0x00;
ICR1L=0x00;
OCR1AH=0x00;
OCR1AL=0x00;
OCR1BH=0x00;
OCR1BL=0x00;
GIMSK=0x00;
MCUCR=0x00;
TIMSK=0x00;
USICR=0x00;
ACSR=0x80;
count = 0;
begin:
PORTD=c;
t=PINB;
a=(t & 0b00010000);
b=(t & 0b00100000) ›› 1;
if (a!=pa) {
pa=a;
if (a!=b) count++;
else count--;
}
if (b!=pb) {
pb=b;
if (a!=b) count--;
else count++;
}
PORTD=d;
goto begin;
} |
Количество тактов оцените сами - на Os оптимизации.
Сообщение от Godzilla82
|
|
При включении оптимизации код перестаёт работать.
|
Ну причина явно в другом месте. Такие функции оптимизатору не интересны, что без оптимизации, что с ней - код одинаковый.
ЗЫ. Ночами нужно спать - я выше ошибся. Обнулять то надо R3, а не R31. А R3 действительно получает 0.
|
|
|
|
14.07.2010, 11:15
|
|
|
Гражданин KAZUS.RUN
Регистрация: 04.08.2006
Сообщений: 911
Сказал спасибо: 28
Сказали Спасибо 180 раз(а) в 139 сообщении(ях)
|
Re: Может ли меняться логика откомпилированной программы при использовании разных режимов оптимизации?
Сообщение от kison
|
|
Кстати - посмотрите листинг от CV с Вашим примером. CV count держит в регистрах! Т.е. переменная совсем не глобальная. Попробуйте добавить обработчик прерывания, где будет использоваться count. И померяйте такты снова. Это кстати офигенный хомут, код из под CV не верный! И еще - для увеличения/уменьшения count служит
|
Тогда всё понятно. А то думаю, чё за лажа.
Сделал такой вариант
|
Код:
|
/************************************************** ***
Chip type : ATtiny2313
Clock frequency : 10,000000 MHz
Memory model : Tiny
External SRAM size : 0
Data Stack size : 32
************************************************** ***/
#include ‹iotiny2313.h›
#include "inavr.h"
#include "stdio.h"
#include "stdint.h"
// Энкодер
#define ENC_P_PIN 4
#define ENC_N_PIN 5
#define ENC_PIN PINB
#define ENC_PORT PORTB
#define ENC_DDR DDRB
#define ENC_P (ENC_PIN & (1‹‹ENC_P_PIN))
#define ENC_N (ENC_PIN & (1‹‹ENC_N_PIN))
#define ENC_MASKA ((1‹‹ENC_P_PIN) | (1‹‹ENC_N_PIN))
#define ENC_B (ENC_PIN & ENC_MASKA)
char P4;
char P5;
char a=1;
char b=0;
signed char const __flash sw[16] =
{
0, -1, 1, 0, 1, 0, 0, -1, -1, 0, 0, 1, 0, 1, -1, 0
};
volatile
unsigned int count=0;
void main(void)
{
char pnew, pold, cnt;
CLKPR=0x80;
CLKPR=0x00;
PORTA=0x00;
DDRA=0x00;
PORTB=0x00;
DDRB=0x00;
PORTD=0x00;
DDRD=0x01;
TCCR0A=0x00;
TCCR0B=0x00;
TCNT0=0x00;
OCR0A=0x00;
OCR0B=0x00;
TCCR1A=0x00;
TCCR1B=0x00;
TCNT1H=0x00;
TCNT1L=0x00;
ICR1H=0x00;
ICR1L=0x00;
OCR1AH=0x00;
OCR1AL=0x00;
OCR1BH=0x00;
OCR1BL=0x00;
GIMSK=0x00;
MCUCR=0x00;
TIMSK=0x00;
USICR=0x00;
ACSR=0x80;
pold=ENC_B ›› 2;
for( ; ; )
{
PORTD=a;
pnew=__swap_nibbles(ENC_B);
cnt = sw[pnew|pold];
if(cnt)
{
count += cnt;
pold = pnew‹‹2;
}
PORTD=b;
}
} |
Результат компиляции IARом меня вполне удовлетворяют, но вижу в листинге некоторые вещи, которые явно увеличивают время исполнения:
|
Код:
|
76 PORTD=a;
\ ??main_0:
\ 0000004A .... LDI R30, count
\ 0000004C 8102 LDD R16, Z+2
\ 0000004E BB02 OUT 0x12, R16
.....
84 PORTD=b;
\ ??main_1:
\ 00000080 .... LDI R30, count
\ 00000082 8103 LDD R16, Z+3
\ 00000084 BB02 OUT 0x12, R16 |
Здесь, например видно, что IAR честно поступает с глобальной переменной (a и b). Если CV размещает как угодно, то тогда понятен выигрыш. Но я ведь, это смогу сделать и на IAR, только честным путём, слегка модифицируя листинг.
Как только я вношу переменные a и b в качестве локальных, то получаю:
|
Код:
|
76 PORTD=a;
\ ??main_0:
\ 0000004A E001 LDI R16, 1
\ 0000004C BB02 OUT 0x12, R16
....
\ ??main_1:
\ 0000007C E000 LDI R16, 0
\ 0000007E BB02 OUT 0x12, R16 |
Count делать в качестве локальной - нельзя, равно как и размещать их в регистрах. Это очевидный бред. Иначе вы не сможете до неё достучаться в прерывании.
Можно конечно сделать финт ушами, если прога состоит из пару страниц текста.
Выглядеть это будет так:
|
Код:
|
/************************************************** ***
Chip type : ATtiny2313
Clock frequency : 10,000000 MHz
Memory model : Tiny
External SRAM size : 0
Data Stack size : 32
************************************************** ***/
#include ‹iotiny2313.h›
#include "inavr.h"
#include "stdio.h"
#include "stdint.h"
// Ýíêîäåð
#define ENC_P_PIN 4
#define ENC_N_PIN 5
#define ENC_PIN PINB
#define ENC_PORT PORTB
#define ENC_DDR DDRB
#define ENC_P (ENC_PIN & (1‹‹ENC_P_PIN))
#define ENC_N (ENC_PIN & (1‹‹ENC_N_PIN))
#define ENC_MASKA ((1‹‹ENC_P_PIN) | (1‹‹ENC_N_PIN))
#define ENC_B (ENC_PIN & ENC_MASKA)
char P4;
char P5;
signed char const __flash sw[16] =
{
0, -1, 1, 0, 1, 0, 0, -1, -1, 0, 0, 1, 0, 1, -1, 0
};
volatile
__regvar __no_init unsigned int count @14;
void main(void)
{
char pnew, pold, cnt;
char a=1;
char b=0;
CLKPR=0x80;
CLKPR=0x00;
PORTA=0x00;
DDRA=0x00;
PORTB=0x00;
DDRB=0x00;
PORTD=0x00;
DDRD=0x01;
TCCR0A=0x00;
TCCR0B=0x00;
TCNT0=0x00;
OCR0A=0x00;
OCR0B=0x00;
TCCR1A=0x00;
TCCR1B=0x00;
TCNT1H=0x00;
TCNT1L=0x00;
ICR1H=0x00;
ICR1L=0x00;
OCR1AH=0x00;
OCR1AL=0x00;
OCR1BH=0x00;
OCR1BL=0x00;
GIMSK=0x00;
MCUCR=0x00;
TIMSK=0x00;
USICR=0x00;
ACSR=0x80;
count = 0;
pold=ENC_B ›› 2;
for( ; ; )
{
PORTD=a;
pnew=__swap_nibbles(ENC_B);
cnt = sw[pnew|pold];
if(cnt)
{
count += cnt;
pold = pnew‹‹2;
}
PORTD=b;
}
} |
В результате
// 140 bytes of CODE memory (+ 4 bytes shared)
// 2 bytes of DATA memory (+ 30 bytes shared)
По тактам - следующее 21/26
|
|
|
|
14.07.2010, 11:53
|
|
|
Почётный гражданин KAZUS.RUN
Регистрация: 13.12.2004
Сообщений: 3,168
Сказал спасибо: 11
Сказали Спасибо 691 раз(а) в 503 сообщении(ях)
|
Re: Может ли меняться логика откомпилированной программы при использовании разных режимов оптимизации?
Сообщение от SasaVitebsk
|
|
По тактам - следующее 21/26
|
Вариант, что я дал выше с регистровым count - 16/23
|
Код:
|
@0000004D: begin
51: PORTD=c;
+0000004D: E081 LDI R24,0x01 Load immediate
+0000004E: BB82 OUT 0x12,R24 Out to I/O location
52: t=PINB;
+0000004F: B386 IN R24,0x16 In from I/O location
53: a=(t & 0b00010000);
+00000050: 2F98 MOV R25,R24 Copy register
+00000051: 7190 ANDI R25,0x10 Logical AND with immediate
54: b=(t & 0b00100000) ›› 1;
+00000052: 9586 LSR R24 Logical shift right
+00000053: 7180 ANDI R24,0x10 Logical AND with immediate
55: if (a!=pa) {
+00000054: 1793 CP R25,R19 Compare
+00000055: F051 BREQ PC+0x0B Branch if equal
57: if (a!=b) count++;
+00000056: 1798 CP R25,R24 Compare
+00000057: F021 BREQ PC+0x05 Branch if equal
+00000058: 9408 SEC Set Carry
+00000059: 1C41 ADC R4,R1 Add with carry
+0000005A: 1C51 ADC R5,R1 Add with carry
+0000005B: C003 RJMP PC+0x0004 Relative jump
58: else count--;
+0000005C: 9408 SEC Set Carry
+0000005D: 0841 SBC R4,R1 Subtract with carry
+0000005E: 0851 SBC R5,R1 Subtract with carry
+0000005F: 2F39 MOV R19,R25 Copy register
60: if (b!=pb) {
+00000060: 1782 CP R24,R18 Compare
+00000061: F059 BREQ PC+0x0C Branch if equal
62: if (a!=b) count--;
+00000062: 1798 CP R25,R24 Compare
+00000063: F029 BREQ PC+0x06 Branch if equal
+00000064: 9408 SEC Set Carry
+00000065: 0841 SBC R4,R1 Subtract with carry
+00000066: 0851 SBC R5,R1 Subtract with carry
+00000067: 2F28 MOV R18,R24 Copy register
+00000068: C004 RJMP PC+0x0005 Relative jump
63: else count++;
+00000069: 9408 SEC Set Carry
+0000006A: 1C41 ADC R4,R1 Add with carry
+0000006B: 1C51 ADC R5,R1 Add with carry
+0000006C: 2F29 MOV R18,R25 Copy register
65: PORTD=d;
+0000006D: BA12 OUT 0x12,R1 Out to I/O location
+0000006E: CFDE RJMP PC-0x0021 Relative jump |
Сообщение от SasaVitebsk
|
Count делать в качестве локальной - нельзя, равно как и размещать их в регистрах. Это очевидный бред. Иначе вы не сможете до неё достучаться в прерывании.
Можно конечно сделать финт ушами, если прога состоит из пару страниц текста.
|
CV из прерывания доступ все же имеет. Там нет линкера и исходник один файл. Берет переменную прямо из регистров. Так что для маленьких проектов типа полный контроль. Для средних и больших - уже просто помойка. Более того, CV даже по указателю умудряется работать с регистровыми переменными, хотя стандарт Си говорит что это невозможно.
|
|
|
|
14.07.2010, 18:21
|
|
|
Почётный гражданин KAZUS.RUN
Регистрация: 29.10.2006
Сообщений: 1,449
Сказал спасибо: 99
Сказали Спасибо 318 раз(а) в 234 сообщении(ях)
|
Re: Может ли меняться логика откомпилированной программы при использовании разных режимов оптимизации?
Сообщение от kison
|
Ну вот Вам такой же вариант под GCC[/code]
Количество тактов оцените сами - на Os оптимизации.
|
WinAVR 2010... Разница тактов 15/16... странно, да? При отключении оптимизации код вообще не работает. То есть, до PORTD=1 не доходит
Сообщение от SasaVitebsk
|
Сделал такой вариант
...
По тактам - следующее 21/26
|
Ну вот терь хоть в симуляторе запускается 
Спасибо, а можете теперь объяснить поподробнее, что вы сделали?
Последний раз редактировалось Godzilla82; 14.07.2010 в 18:25.
|
|
|
|
14.07.2010, 18:39
|
|
|
Почётный гражданин KAZUS.RUN
Регистрация: 13.12.2004
Сообщений: 3,168
Сказал спасибо: 11
Сказали Спасибо 691 раз(а) в 503 сообщении(ях)
|
Re: Может ли меняться логика откомпилированной программы при использовании разных режимов оптимизации?
Сообщение от Godzilla82
|
|
WinAVR 2010... Разница тактов 15/16... странно, да?
|
Разница между чем и чем?
Сообщение от Godzilla82
|
|
При отключении оптимизации код вообще не работает.
|
Листинг в студию. Циклов там нет, так что подвиснуть ничего не может. Точку останова ставьте одну, в начале вечноо цикла. Например на PORTD=c;
Если же Вы ставите две, то результаты у Вас выходят меньше на время команды RJMP - на 2 такта. У меня WinAvr20071221.
|
|
|
|
14.07.2010, 18:40
|
|
|
Прописка
Регистрация: 26.01.2009
Сообщений: 249
Сказал спасибо: 23
Сказали Спасибо 102 раз(а) в 61 сообщении(ях)
|
Re: Может ли меняться логика откомпилированной программы при использовании разных режимов оптимизации?
Сообщение от SasaVitebsk
|
|
Код:
|
count = 0;
pold=ENC_B ›› 2;
for( ; ; )
{
PORTD=a;
pnew=__swap_nibbles(ENC_B);
cnt = sw[pnew|pold];
if(cnt)
{
count += cnt;
pold = pnew‹‹2;
}
PORTD=b;
}
} |
|
Обратите внимание на выбранные строки: из-за них код будет работать только на соседних ножках 4 и 5. Какой смысл было выносить их номера в константы-то? Ведь пройдет год - и понадобится нам перенести один из входов с 4-ой на 3-ю, замените Вы определение, тогда программа и упадет, а Вы уже и "помнить забудете", что в программе есть привязка.
|
|
|
|
14.07.2010, 18:49
|
|
|
Почётный гражданин KAZUS.RUN
Регистрация: 29.10.2006
Сообщений: 1,449
Сказал спасибо: 99
Сказали Спасибо 318 раз(а) в 234 сообщении(ях)
|
Re: Может ли меняться логика откомпилированной программы при использовании разных режимов оптимизации?
Сообщение от kison
|
Разница между чем и чем?
Листинг в студию. Циклов там нет, так что подвиснуть ничего не может. Точку останова ставьте одну, в начале вечноо цикла. Например на PORTD=c;
Если же Вы ставите две, то результаты у Вас выходят меньше на время команды RJMP - на 2 такта. У меня WinAvr20071221.
|
Я смотрю в VMLAB осциллографом. Компилил на 2010... Ещё раз говорю, с включённой оптимизацией 15/16 тактов (без изменений сигнала с датчика/при изменении сигналов с датчиков)...
В общем, как ни крути, быстрее 25 тактов не прыгнешь. Может, у кого есть более быстрый алгоритм?
Последний раз редактировалось Godzilla82; 14.07.2010 в 18:55.
|
|
|
|
14.07.2010, 19:23
|
|
|
Почётный гражданин KAZUS.RUN
Регистрация: 13.12.2004
Сообщений: 3,168
Сказал спасибо: 11
Сказали Спасибо 691 раз(а) в 503 сообщении(ях)
|
Re: Может ли меняться логика откомпилированной программы при использовании разных режимов оптимизации?
Сообщение от Godzilla82
|
|
Я смотрю в VMLAB осциллографом.
|
Ну так листинг то дайте. Интересно же посмотреть в чем проблемы.
Сообщение от Godzilla82
|
|
В общем, как ни крути, быстрее 25 тактов не прыгнешь
|
Возьмите не последнюю версию компилятора. Я же дал - 16/23. Это меньше 25-ти.
|
|
|
|
Ваши права в разделе
|
Вы не можете создавать новые темы
Вы не можете отвечать в темах
Вы не можете прикреплять вложения
Вы не можете редактировать свои сообщения
HTML код Выкл.
|
|
|
Часовой пояс GMT +4, время: 11:46.
|
|