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

Winavr сокращает функцию

Помогите разобраться с WINAVR. При размещении переменных в регистрах компилятор ведёт себя подозрительно: сокращает функции, в которых они используются. :07: Но при обычном объявлении всё работает. Подскажите, где может быть ошибка?

 

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

timer_ms.rar

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


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

Регистровые volatile переменные в GCC не работают.

 

Анатолий

 

AVRGCC ignores "volatile" keyword for "register" variables

http://gcc.gnu.org/bugzilla/show_bug.cgi?id=17336

Изменено пользователем aesok

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


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

Регистровые volatile переменные в GCC не работают.

 

Анатолий

 

AVRGCC ignores "volatile" keyword for "register" variables

http://gcc.gnu.org/bugzilla/show_bug.cgi?id=17336

 

И каков же выход? Использовать IAR?

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


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

И каков же выход? Использовать IAR?

 

Используйте GPIO0, GPIO1, GPIO2. В принципе можно даже использовать любые незадействованные SFR с адресом 0х00 - 0х1F

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


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

И каков же выход?
Просто уберите volatile при объявлении регистровой переменной,

все должно скомпилится правильно.

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


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

Используйте GPIO0, GPIO1, GPIO2. В принципе можно даже использовать любые незадействованные SFR с адресом 0х00 - 0х1F

Если не трудно, подскажите как использовать SFR в дипазоне 0x09...0x13 (записать/прочитать данные 2-х или 4-х байтные)?

 

 

Просто уберите volatile при объявлении регистровой переменной,

все должно скомпилится правильно.

Скомпилировалось, но не правильно. Можете сами проверить, в архиве весь проект...

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


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

Скомпилировалось, но не правильно. Можете сами проверить, в архиве весь проект...
А какая версия WinAVR ?

Скомпилируйте с листингом и покажите его.

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


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

И каков же выход?
Конкретно в этом простом случае можно написать вставку на инлайновом ассемблере.

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


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

А какая версия WinAVR ?

Скомпилируйте с листингом и покажите его.

 

WinAVR-20080512

 

> "make.exe" all

-------- begin --------
avr-gcc (WinAVR 20080512) 4.3.0
Copyright (C) 2008 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.


Compiling C: main.c
avr-gcc -c -mmcu=attiny13 -I. -gdwarf-2 -DF_CPU=1200000UL -Os -funsigned-char -funsigned-bitfields -fpack-struct -fshort-enums -Wall -Wstrict-prototypes -pedantic -Wa,-adhlns=./main.lst  -std=gnu99 -Wundef -MMD -MP -MF .dep/main.o.d main.c -o main.o 
main.c:4: warning: file-scope declaration of 'count_ms' specifies 'register'
main.c:5: warning: file-scope declaration of 'flag_ms' specifies 'register'

Linking: main.elf
avr-gcc -mmcu=attiny13 -I. -gdwarf-2 -DF_CPU=1200000UL -Os -funsigned-char -funsigned-bitfields -fpack-struct -fshort-enums -Wall -Wstrict-prototypes -pedantic -Wa,-adhlns=main.o  -std=gnu99 -Wundef -MMD -MP -MF .dep/main.elf.d main.o --output main.elf -Wl,-Map=main.map,--cref     -lm

Creating load file for Flash: main.hex
avr-objcopy -O ihex -R .eeprom -R .fuse -R .lock main.elf main.hex

Creating load file for EEPROM: main.eep
avr-objcopy -j .eeprom --set-section-flags=.eeprom="alloc,load" \
    --change-section-lma .eeprom=0 --no-change-warnings -O ihex main.elf main.eep || exit 0

Creating Extended Listing: main.lss
avr-objdump -h -S -z main.elf > main.lss

Creating Symbol Table: main.sym
avr-nm -n main.elf > main.sym

Size after:
AVR Memory Usage
----------------
Device: attiny13

Program:     158 bytes (15.4% Full)
(.text + .data + .bootloader)

Data:          0 bytes (0.0% Full)
(.data + .bss + .noinit)

 

 

-------- end --------

timer_ms_.rar

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


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

Все версии avr-gcc так работают.
Ну это как минимум не так :)

 

WinAVR20060421(Gcc 3.4.6):

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 ???

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


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

Можно ли получить такой же компактный/быстрый код на 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).

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


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

и так далее, а начиная с -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        **** }

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


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

Конкретно в этом простом случае можно написать вставку на инлайновом ассемблере.

Можно ли подобно макросу _SFR_IO16(io_addr) расположить 32-битную переменную в область SFR?

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


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

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? Хочу такой же:)

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


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

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

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

Гость
Ответить в этой теме...

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

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

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

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

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

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