ВходНаше всё Теги codebook 无线电组件 Поиск Опросы Закон Вторник
21 января
1486609
mse homjak (25.12.2024 22:36, просмотров: 3385)
Прикольненько... Тема про АВР(вернее, ВинАВР-10), но там, походу, норота меньше. Тема-то про "С". 

Есть такой код:

    for(i=0;i<16;i++)
    {
      while((flagsRegister&(1<<resieveExtData))==0){}
      flagsRegister&=~(1<<resieveExtData);
      MiS21dataArray[i]=primaryB._16_bit_data_;
    }

primaryB грузится в прерывании, выставляется флаг resieveExtData, заполняем буфер данными приходящими по прерыванию.


Компилируется в это:

      MiS21dataArray[i]=primaryB._16_bit_data_;
   190e6:	20 91 6a 1c 	lds	r18, 0x1C6A
   190ea:	30 91 6b 1c 	lds	r19, 0x1C6B     ;грузится primaryB
   190ee:	14 c0       	rjmp	.+40     	; 0x19118 <getALCpointInSubdiap+0x8e>
      while((flagsRegister&(1<<resieveExtData))==0){}
      flagsRegister&=~(1<<resieveExtData);
    }
    for(i=0;i<16;i++)
    {
      while((flagsRegister&(1<<resieveExtData))==0){}
   190f0:	80 91 74 22 	lds	r24, 0x2274     ;сюда циклится и заполняет буфер по прерыванию
   190f4:	85 ff       	sbrs	r24, 5
   190f6:	fc cf       	rjmp	.-8      	; 0x190f0 <getALCpointInSubdiap+0x66>
      flagsRegister&=~(1<<resieveExtData);
   190f8:	80 91 74 22 	lds	r24, 0x2274
   190fc:	8f 7d       	andi	r24, 0xDF	; 223
   190fe:	80 93 74 22 	sts	0x2274, r24
      MiS21dataArray[i]=primaryB._16_bit_data_;
   19102:	e9 81       	ldd	r30, Y+1	; 0x01
   19104:	f0 e0       	ldi	r31, 0x00	; 0
   19106:	ee 0f       	add	r30, r30
   19108:	ff 1f       	adc	r31, r31
   1910a:	e0 5c       	subi	r30, 0xC0	; 192
   1910c:	fa 4d       	sbci	r31, 0xDA	; 218
   1910e:	31 83       	std	Z+1, r19	; 0x01
   19110:	20 83       	st	Z, r18

for(i=0;i<16;i++) 19112: 89 81 ldd r24, Y+1 ; 0x01 19114: 8f 5f subi r24, 0xFF ; 255 19116: 89 83 std Y+1, r24 ; 0x01 19118: 89 81 ldd r24, Y+1 ; 0x01 1911a: 80 31 cpi r24, 0x10 ; 16 1911c: 48 f3 brcs .-46 ; 0x190f0 <getALCpointInSubdiap+0x66> на вершину цикла

Что интересно, primaryB меняется в процэссе, но это никого не волнует.

Т.е. primaryB читается один раз и этим значением заполняется буфер по прерываниям. Делаем primaryB volatile и всё нормально.


   190e8:	80 91 74 22 	lds	r24, 0x2274
   190ec:	85 ff       	sbrs	r24, 5
   190ee:	fc cf       	rjmp	.-8      	; 0x190e8 <getALCpointInSubdiap+0x5e>
      flagsRegister&=~(1<<resieveExtData);
   190f0:	80 91 74 22 	lds	r24, 0x2274
   190f4:	8f 7d       	andi	r24, 0xDF	; 223
   190f6:	80 93 74 22 	sts	0x2274, r24
      MiS21dataArray[i]=primaryB._16_bit_data_;
   190fa:	e9 81       	ldd	r30, Y+1	; 0x01
   190fc:	80 91 6a 1c 	lds	r24, 0x1C6A
   19100:	90 91 6b 1c 	lds	r25, 0x1C6B
   19104:	f0 e0       	ldi	r31, 0x00	; 0
   19106:	ee 0f       	add	r30, r30
   19108:	ff 1f       	adc	r31, r31
   1910a:	e0 5c       	subi	r30, 0xC0	; 192
   1910c:	fa 4d       	sbci	r31, 0xDA	; 218
   1910e:	91 83       	std	Z+1, r25	; 0x01
   19110:	80 83       	st	Z, r24

for(i=0;i<16;i++) 19112: 89 81 ldd r24, Y+1 ; 0x01 19114: 8f 5f subi r24, 0xFF ; 255 19116: 89 83 std Y+1, r24 ; 0x01 19118: 89 81 ldd r24, Y+1 ; 0x01 1911a: 80 31 cpi r24, 0x10 ; 16 1911c: 28 f3 brcs .-54 ; 0x190e8 <getALCpointInSubdiap+0x5e>

Собсно, вопрос: чо я делал не так, без волатиля? Это-ж дичь кокойты. Или просто особенность оптимизатора?