|
Winavr сокращает функцию, если переменные размещены в регистрах |
|
|
|
Jun 10 2008, 11:54
|
Участник

Группа: Свой
Сообщений: 69
Регистрация: 4-02-08
Из: Винница
Пользователь №: 34 732

|
Помогите разобраться с WINAVR. При размещении переменных в регистрах компилятор ведёт себя подозрительно: сокращает функции, в которых они используются.  Но при обычном объявлении всё работает. Подскажите, где может быть ошибка? Код #include <avr/io.h> #include <avr/interrupt.h> volatile register unsigned long count_ms asm("r4"); volatile register unsigned char flag_ms asm("r8"); ///////////////////////////////////////////////////////////////////////////////////////////////// void timer_ms(unsigned long value) { count_ms = value; flag_ms = 0; while(flag_ms == 0); } ///////////////////////////////////////////////////////////////////////////////////////////////// ISR(TIM0_COMPA_vect) { if(count_ms){--count_ms;} else{flag_ms = 1;} } ///////////////////////////////////////////////////////////////////////////////////////////////// int main(void) { TCCR0A = (0<<COM0A1)|(0<<COM0A0)|(0<<COM0B1)|(0<<COM0B0)|(1<<WGM01)|(0<<WGM00); //CTC TCCR0B = (0<<FOC0A)|(0<<FOC0B)|(0<<WGM02)|(0<<CS02)|(1<<CS01)|(0<<CS00); // FCPU/8 OCR0A = 149; TIMSK0 = (0<<OCIE0B)|(1<<OCIE0A)|(0<<TOIE0); sei(); while(1){ timer_ms(100); PORTB ^= 0x01; } }
|
|
|
|
|
 |
Ответов
|
Jun 10 2008, 12:15
|
Знающий
   
Группа: Участник
Сообщений: 596
Регистрация: 26-05-06
Из: Москва
Пользователь №: 17 484

|
Регистровые volatile переменные в GCC не работают. Анатолий AVRGCC ignores "volatile" keyword for "register" variables http://gcc.gnu.org/bugzilla/show_bug.cgi?id=17336
Сообщение отредактировал aesok - Jun 10 2008, 12:28
|
|
|
|
|
Jun 10 2008, 12:36
|
Участник

Группа: Свой
Сообщений: 69
Регистрация: 4-02-08
Из: Винница
Пользователь №: 34 732

|
Цитата(aesok @ Jun 10 2008, 15:15)  Регистровые volatile переменные в GCC не работают. Анатолий AVRGCC ignores "volatile" keyword for "register" variables http://gcc.gnu.org/bugzilla/show_bug.cgi?id=17336И каков же выход? Использовать IAR?
|
|
|
|
|
Jun 10 2008, 14:02
|
Участник

Группа: Свой
Сообщений: 69
Регистрация: 4-02-08
Из: Винница
Пользователь №: 34 732

|
Цитата(dimka76 @ Jun 10 2008, 15:55)  Используйте GPIO0, GPIO1, GPIO2. В принципе можно даже использовать любые незадействованные SFR с адресом 0х00 - 0х1F Если не трудно, подскажите как использовать SFR в дипазоне 0x09...0x13 (записать/прочитать данные 2-х или 4-х байтные)? Цитата(singlskv @ Jun 10 2008, 16:59)  Просто уберите volatile при объявлении регистровой переменной, все должно скомпилится правильно. Скомпилировалось, но не правильно. Можете сами проверить, в архиве весь проект...
|
|
|
|
|
Jun 10 2008, 16:28
|
Знающий
   
Группа: Участник
Сообщений: 596
Регистрация: 26-05-06
Из: Москва
Пользователь №: 17 484

|
Цитата(singlskv @ Jun 10 2008, 18:06)  А какая версия WinAVR ? Все версии avr-gcc так работают. Анатолий.
|
|
|
|
|
Jun 10 2008, 17:44
|
дятел
    
Группа: Свой
Сообщений: 1 681
Регистрация: 13-05-06
Из: Питер
Пользователь №: 17 065

|
Цитата(aesok @ Jun 10 2008, 20:28)  Все версии avr-gcc так работают. Ну это как минимум не так  WinAVR20060421(Gcc 3.4.6): CODE 00000048 <timer_ms>: register unsigned long count_ms asm("r4"); register unsigned char flag_ms asm("r8"); ///////////////////////////////////////////////////////////////////////////////////////////////// void timer_ms(unsigned long value) { 48: b9 2f mov r27, r25 4a: a8 2f mov r26, r24 4c: 97 2f mov r25, r23 4e: 86 2f mov r24, r22 count_ms = value; 50: 48 2e mov r4, r24 52: 59 2e mov r5, r25 54: 6a 2e mov r6, r26 56: 7b 2e mov r7, r27 flag_ms = 0; 58: 88 24 eor r8, r8 while(flag_ms == 0); 5a: 88 20 and r8, r8 5c: f1 f3 breq .-4 ; 0x5a <timer_ms+0x12> 5e: 08 95 ret
00000060 <__vector_6>: } ///////////////////////////////////////////////////////////////////////////////////////////////// ISR(TIM0_COMPA_vect) { 60: 1f 92 push r1 62: 0f 92 push r0 64: 0f b6 in r0, 0x3f ; 63 66: 0f 92 push r0 68: 11 24 eor r1, r1 if(count_ms){--count_ms;} 6a: 41 14 cp r4, r1 6c: 51 04 cpc r5, r1 6e: 61 04 cpc r6, r1 70: 71 04 cpc r7, r1 72: 31 f0 breq .+12 ; 0x80 <__vector_6+0x20> 74: 08 94 sec 76: 41 08 sbc r4, r1 78: 51 08 sbc r5, r1 7a: 61 08 sbc r6, r1 7c: 71 08 sbc r7, r1 7e: 02 c0 rjmp .+4 ; 0x84 <__vector_6+0x24> else{flag_ms = 1;} 80: 88 24 eor r8, r8 82: 83 94 inc r8 84: 0f 90 pop r0 86: 0f be out 0x3f, r0 ; 63 88: 0f 90 pop r0 8a: 1f 90 pop r1 8c: 18 95 reti
0000008e <main>: } ///////////////////////////////////////////////////////////////////////////////////////////////// int main(void) { 8e: cf e9 ldi r28, 0x9F ; 159 90: d0 e0 ldi r29, 0x00 ; 0 92: de bf out 0x3e, r29 ; 62 94: cd bf out 0x3d, r28 ; 61 TCCR0A = (0<<COM0A1)|(0<<COM0A0)|(0<<COM0B1)|(0<<COM0B0)|(1<<WGM01)|(0<<WGM00); //CTC 96: 82 e0 ldi r24, 0x02 ; 2 98: 8f bd out 0x2f, r24 ; 47 TCCR0B = (0<<FOC0A)|(0<<FOC0B)|(0<<WGM02)|(0<<CS02)|(1<<CS01)|(0<<CS00); // FCPU/8 9a: 83 bf out 0x33, r24 ; 51 OCR0A = 149; 9c: 85 e9 ldi r24, 0x95 ; 149 9e: 86 bf out 0x36, r24 ; 54 TIMSK0 = (0<<OCIE0B)|(1<<OCIE0A)|(0<<TOIE0); a0: 84 e0 ldi r24, 0x04 ; 4 a2: 89 bf out 0x39, r24 ; 57 sei(); a4: 78 94 sei while(1){ timer_ms(100); a6: 64 e6 ldi r22, 0x64 ; 100 a8: 70 e0 ldi r23, 0x00 ; 0 aa: 80 e0 ldi r24, 0x00 ; 0 ac: 90 e0 ldi r25, 0x00 ; 0 ae: cc df rcall .-104 ; 0x48 <timer_ms> PORTB ^= 0x01; b0: 88 b3 in r24, 0x18 ; 24 b2: 91 e0 ldi r25, 0x01 ; 1 b4: 89 27 eor r24, r25 b6: 88 bb out 0x18, r24 ; 24 b8: f6 cf rjmp .-20 ; 0xa6 <__stack+0x7>
как видно, оверхед только здесь: Код 48: b9 2f mov r27, r25 4a: a8 2f mov r26, r24 4c: 97 2f mov r25, r23 4e: 86 2f mov r24, r22 и здесь: Код b2: 91 e0 ldi r25, 0x01; 1 Но при этом код абсолютно корректный ! Можно ли получить такой же компактный/быстрый код на Gcc 4.x.x ???
|
|
|
|
|
Jun 10 2008, 18:12
|

фанат дивана
     
Группа: Свой
Сообщений: 3 387
Регистрация: 9-08-07
Из: Уфа
Пользователь №: 29 684

|
Цитата(singlskv @ Jun 10 2008, 23:44)  Можно ли получить такой же компактный/быстрый код на Gcc 4.x.x ??? Увы Без оптимизации выходит: Код void timer_ms(unsigned long value) { 48: df 93 push r29 4a: cf 93 push r28 4c: 00 d0 rcall .+0 ; 0x4e <timer_ms+0x6> 4e: 00 d0 rcall .+0 ; 0x50 <timer_ms+0x8> 50: cd b7 in r28, 0x3d; 61 52: de b7 in r29, 0x3e; 62 54: 69 83 std Y+1, r22; 0x01 56: 7a 83 std Y+2, r23; 0x02 58: 8b 83 std Y+3, r24; 0x03 5a: 9c 83 std Y+4, r25; 0x04 count_ms = value; 5c: 49 80 ldd r4, Y+1; 0x01 5e: 5a 80 ldd r5, Y+2; 0x02 60: 6b 80 ldd r6, Y+3; 0x03 62: 7c 80 ldd r7, Y+4; 0x04 flag_ms = 0; 64: 88 24 eor r8, r8 while(flag_ms == 0); 66: 88 2d mov r24, r8 68: 88 23 and r24, r24 6a: e9 f3 breq .-6 ; 0x66 <timer_ms+0x1e> } 6c: 0f 90 pop r0 6e: 0f 90 pop r0 70: 0f 90 pop r0 72: 0f 90 pop r0 74: cf 91 pop r28 76: df 91 pop r29 78: 08 95 ret и так далее, а начиная с -O1: Код void timer_ms(unsigned long value) { 48: ff cf rjmp .-2 ; 0x48 <timer_ms> Это avr-gcc (GCC) 4.4.0 20080530 (experimental).
--------------------
Если бы я знал, что такое электричество...
|
|
|
|
|
Jun 10 2008, 19:32
|

Местный
  
Группа: Участник
Сообщений: 340
Регистрация: 25-10-05
Из: Пермь, Россия
Пользователь №: 10 091

|
Цитата(AHTOXA @ Jun 10 2008, 23:12)  и так далее, а начиная с -O1: Код void timer_ms(unsigned long value) { 48: ff cf rjmp .-2 ; 0x48 <timer_ms> Это avr-gcc (GCC) 4.4.0 20080530 (experimental). gcc-4.2.2 начиная c -O1: Код 7:test.c **** void timer_ms(unsigned long value) 8:test.c **** { 79 /* prologue: frame size=0 */ 80 /* prologue end (size=0) */ 9:test.c **** count_ms = value; 83 0000 2B01 movw r4,r22 84 0002 3C01 movw r6,r24 10:test.c **** flag_ms = 0; 87 0004 8824 clr r8 88 .L2: 11:test.c **** while(flag_ms == 0); 91 0006 8820 tst r8 92 0008 01F0 breq .L2 93 /* epilogue: frame size=0 */ 94 000a 0895 ret 95 /* epilogue end (size=1) */ 96 /* function timer_ms size 6 (5) */ 12:test.c **** }
--------------------
Всего наилучшего, Alex Mogilnikov
|
|
|
|
|
Jun 11 2008, 12:33
|

фанат дивана
     
Группа: Свой
Сообщений: 3 387
Регистрация: 9-08-07
Из: Уфа
Пользователь №: 29 684

|
Цитата(alx2 @ Jun 11 2008, 01:32)  gcc-4.2.2 начиная c -O1: Странно... avr-gcc.exe (GCC) 4.2.2 (WinAVR 20071221): Код 00000048 <timer_ms>: 48: 2b 01 movw r4, r22 4a: 3c 01 movw r6, r24 4c: 88 24 eor r8, r8 4e: ff cf rjmp .-2 ; 0x4e <timer_ms+0x6> avr-gcc.exe (GCC) 4.1.2 (WinAVR 20070525): Код void timer_ms(unsigned long value) { 4a: 46 2e mov r4, r22 4c: 57 2e mov r5, r23 4e: 68 2e mov r6, r24 50: 79 2e mov r7, r25 count_ms = value; flag_ms = 0; 52: 88 24 eor r8, r8 54: ff cf rjmp .-2 ; 0x54 <timer_ms+0xa> А у Вас какой GCC 4.2.2? Хочу такой же
--------------------
Если бы я знал, что такое электричество...
|
|
|
|
|
Jun 11 2008, 18:48
|
дятел
    
Группа: Свой
Сообщений: 1 681
Регистрация: 13-05-06
Из: Питер
Пользователь №: 17 065

|
Цитата(AHTOXA @ Jun 11 2008, 21:44)  Это без volatile. Да, похоже единственный правильный вариант для gcc 4.x.x без раздувания кода и данных это с асм вставкой: Код #include <avr/io.h> #include <avr/interrupt.h>
///////////////////////////////////////////////////////////////////////////////////////////////// volatile register unsigned long count_ms asm("r4"); register unsigned char flag_ms asm("r8");
static void timer_ms(unsigned long value) { count_ms = value; flag_ms = 0; __asm__ __volatile__("and r8,r8\n\t"\ "breq .-4"); } ///////////////////////////////////////////////////////////////////////////////////////////////// ISR(TIM0_COMPA_vect) { if(count_ms){--count_ms;} else{flag_ms = 1;} } ///////////////////////////////////////////////////////////////////////////////////////////////// int main(void) { TCCR0A = (0<<COM0A1)|(0<<COM0A0)|(0<<COM0B1)|(0<<COM0B0)|(1<<WGM01)|(0<<WGM00); //CTC TCCR0B = (0<<FOC0A)|(0<<FOC0B)|(0<<WGM02)|(0<<CS02)|(1<<CS01)|(0<<CS00); // FCPU/8 OCR0A = 149; TIMSK0 = (0<<OCIE0B)|(1<<OCIE0A)|(0<<TOIE0); sei(); while(1){ timer_ms(100); PORTB ^= 0x01; } } При этом код правильный и компактный WinAVR20070525: Код 88: 94 e6 ldi r25, 0x64; 100 8a: 49 2e mov r4, r25 8c: 51 2c mov r5, r1 8e: 61 2c mov r6, r1 90: 71 2c mov r7, r1 92: 88 20 and r8, r8 94: f1 f3 breq .-4 ; 0x92 <main+0x1a> while(1){ timer_ms(100); PORTB ^= 0x01; 96: 88 b3 in r24, 0x18; 24 98: 91 e0 ldi r25, 0x01; 1 9a: 89 27 eor r24, r25 9c: 88 bb out 0x18, r24; 24 9e: f4 cf rjmp .-24 ; 0x88 <main+0x10> Цитата(aesok @ Jun 10 2008, 16:15)  AVRGCC ignores "volatile" keyword for "register" variables А вот это не совсем так, оно не игнорируется целиком, но логика работы при этом мягко говоря странная...  результат при компиляции прерывания: volatile register unsigned long count_ms asm("r4"); Код ISR(TIM0_COMPA_vect) { 4a: 1f 92 push r1 4c: 0f 92 push r0 4e: 0f b6 in r0, 0x3f; 63 50: 0f 92 push r0 52: 11 24 eor r1, r1 if(count_ms){--count_ms;} 54: 41 14 cp r4, r1 56: 51 04 cpc r5, r1 58: 61 04 cpc r6, r1 5a: 71 04 cpc r7, r1 5c: 31 f0 breq .+12 ; 0x6a <__vector_6+0x20> 5e: 08 94 sec 60: 41 08 sbc r4, r1 62: 51 08 sbc r5, r1 64: 61 08 sbc r6, r1 66: 71 08 sbc r7, r1 68: 02 c0 rjmp .+4 ; 0x6e <__vector_6+0x24> else{flag_ms = 1;} 6a: 88 24 eor r8, r8 6c: 83 94 inc r8 6e: 0f 90 pop r0 70: 0f be out 0x3f, r0; 63 72: 0f 90 pop r0 74: 1f 90 pop r1 76: 18 95 reti Здесь все ок. без volatile, register unsigned long count_ms asm("r4"); Код ISR(TIM0_COMPA_vect) { 4a: 1f 92 push r1 4c: 0f 92 push r0 4e: 0f b6 in r0, 0x3f; 63 50: 0f 92 push r0 52: 11 24 eor r1, r1 54: 8f 93 push r24 56: 9f 93 push r25 58: af 93 push r26 5a: bf 93 push r27 if(count_ms){--count_ms;} 5c: 41 14 cp r4, r1 5e: 51 04 cpc r5, r1 60: 61 04 cpc r6, r1 62: 71 04 cpc r7, r1 64: 31 f0 breq .+12 ; 0x72 <__vector_6+0x28> 66: 08 94 sec 68: 41 08 sbc r4, r1 6a: 51 08 sbc r5, r1 6c: 61 08 sbc r6, r1 6e: 71 08 sbc r7, r1 70: 02 c0 rjmp .+4 ; 0x76 <__vector_6+0x2c> else{flag_ms = 1;} 72: 81 e0 ldi r24, 0x01; 1 74: 88 2e mov r8, r24 76: bf 91 pop r27 78: af 91 pop r26 7a: 9f 91 pop r25 7c: 8f 91 pop r24 7e: 0f 90 pop r0 80: 0f be out 0x3f, r0; 63 82: 0f 90 pop r0 84: 1f 90 pop r1 86: 18 95 reti Ну и зачем здесь сохраняются r24-r27 ? и почему нельзя было обойтись eor r8,r8 inc r8 как в предыдущем коде ? замечу при этом что добавляли/убирали volatile ВООБЩЕ У ДРУГОЙ ПЕРЕМЕННОЙ !
|
|
|
|
Сообщений в этой теме
A.l.e.x. Winavr сокращает функцию Jun 10 2008, 11:54     A.l.e.x. Цитата(singlskv @ Jun 10 2008, 17:06) А к... Jun 10 2008, 14:33              singlskv Цитата(aesok @ Jun 11 2008, 23:04) Второй... Jun 11 2008, 19:33               aesok Цитата(singlskv @ Jun 11 2008, 23:23) Но ... Jun 11 2008, 19:47                singlskv Цитата(aesok @ Jun 11 2008, 23:47) GCC не... Jun 11 2008, 20:13               aesok Цитата(singlskv @ Jun 11 2008, 23:33) Ну ... Jun 11 2008, 20:57                singlskv Цитата(aesok @ Jun 12 2008, 00:39) Только... Jun 11 2008, 21:15                 aesok Цитата(singlskv @ Jun 12 2008, 01:15) а н... Jun 11 2008, 22:08                  singlskv Цитата(aesok @ Jun 12 2008, 01:43) Все ва... Jun 11 2008, 22:21          alx2 Цитата(AHTOXA @ Jun 11 2008, 17:33) Стран... Jun 12 2008, 11:50           singlskv Цитата(alx2 @ Jun 12 2008, 15:50) Я компи... Jun 12 2008, 12:22            alx2 Цитата(singlskv @ Jun 12 2008, 17:22) ИТО... Jun 12 2008, 20:51            aesok сори, ошибочный пост Jun 15 2008, 14:34  singlskv Цитата(A.l.e.x. @ Jun 10 2008, 16:36) И к... Jun 10 2008, 13:59  Сергей Борщ Цитата(A.l.e.x. @ Jun 10 2008, 15:36) И к... Jun 10 2008, 14:19   A.l.e.x. Цитата(Сергей Борщ @ Jun 10 2008, 17:19) ... Jun 11 2008, 06:39    Сергей Борщ Цитата(A.l.e.x. @ Jun 11 2008, 09:39) Мож... Jun 11 2008, 14:54     A.l.e.x. Цитата(Сергей Борщ @ Jun 11 2008, 17:54) ... Jun 11 2008, 15:41      Сергей Борщ Цитата(A.l.e.x. @ Jun 11 2008, 18:41) Я и... Jun 11 2008, 16:48       A.l.e.x. Цитата(Сергей Борщ @ Jun 11 2008, 19:48) ... Jun 12 2008, 06:21 mdmitry Разные версии WinAvr разрешают располагать регистр... Jun 11 2008, 16:37 _Pasha Тоже хотел недавно "поджать" компилер в ... Jun 12 2008, 05:36 AHTOXA Цитата(alx2 @ Jun 12 2008, 17:50) Я компи... Jun 12 2008, 18:20 singlskv Цитата(AHTOXA @ Jun 12 2008, 22:20) А я к... Jun 12 2008, 19:04
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|