ScrambledStamp 0 8 октября, 2008 Опубликовано 8 октября, 2008 · Жалоба Помогите оптимизировать код, надо его сделать побыстрее, очень не хочется уменьшать разрядность. . unsigned char pwma[256], pwmb[256], pwmc[256]; unsigned char pwmstep; // PWM main interrupt interrupt [TIM2_COMP] void timer2_comp_isr(void) { // Place your code here PORTA=pwma[pwmstep]; PORTB=pwmb[pwmstep]; PORTC=pwmc[pwmstep]; pwmstep++; } Компилятор (кодевижн) выдает такой листинг: ; 189 // PWM main interrupt ; 190 interrupt [TIM2_COMP] void timer2_comp_isr(void) ; 191 { _timer2_comp_isr: ST -Y,R30 ST -Y,R31 IN R30,SREG ST -Y,R30 ; 192 // Place your code here ; 193 PORTA=pwma[pwmstep]; MOV R30,R9 LDI R31,0 SUBI R30,LOW(-_pwma) SBCI R31,HIGH(-_pwma) LD R30,Z OUT 0x1B,R30 ; 194 PORTB=pwmb[pwmstep]; MOV R30,R9 LDI R31,0 SUBI R30,LOW(-_pwmb) SBCI R31,HIGH(-_pwmb) LD R30,Z OUT 0x18,R30 ; 195 PORTC=pwmc[pwmstep]; MOV R30,R9 LDI R31,0 SUBI R30,LOW(-_pwmc) SBCI R31,HIGH(-_pwmc) LD R30,Z OUT 0x15,R30 ; 196 pwmstep++; INC R9 ; 197 } _0xF0: LD R30,Y+ OUT SREG,R30 LD R31,Y+ LD R30,Y+ RETI ; 198 Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
VCucumber 0 8 октября, 2008 Опубликовано 8 октября, 2008 · Жалоба interrupt [TIM2_COMP] void timer2_comp_isr(void) { PORTA=pwm[pwmstep++]; PORTB=pwm[pwmstep++]; PORTC=pwm[pwmstep++]; } Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
WHILE 0 8 октября, 2008 Опубликовано 8 октября, 2008 · Жалоба Может,все-таки { PORTA=pwm[pwmstep]; PORTB=pwm[pwmstep]; PORTC=pwm[pwmstep++]; } Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
sergeeff 1 8 октября, 2008 Опубликовано 8 октября, 2008 · Жалоба Можно попробовать так (компилятора нет под рукой для AVR): typedef struct { unsigned char a; unsigned char b; unsigned char c; } PWM; PWM pwm[256]; unsigned char pwmstep = 0; interrupt [TIM2_COMP] void timer2_comp_isr(void) { // Place your code here PWM *tmp = &pwm[pwmstep++]; PORTA=tmp->a; PORTB=tmp->b; PORTC=tmp->c; } Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
NullPointer 0 8 октября, 2008 Опубликовано 8 октября, 2008 · Жалоба Я идею подам, остальные результативно поругают :rolleyes: Из трех массивов сделать один, расположив данные из них как [pwma0][pwmb0][pwmc0]...[pwmaN][pwmbN][pwmcN], и: PORTA = thatArray[pwmstep]; PORTB = thatArray[pwmstep + 1]; PORTC = thatArray[pwmstep + 2]; pwmstep += 3; Но ручками переписать на asm'е было бы самое то (он для того и нужен - оптимизировать). Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
DpInRock 0 8 октября, 2008 Опубликовано 8 октября, 2008 · Жалоба Тогда уж так: PORTA = thatArray[pwmstep++]; PORTB = thatArray[pwmstep ++]; PORTC = thatArray[pwmstep ++]; Скорее всего именно так будет самое короткое. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Tiro 0 8 октября, 2008 Опубликовано 8 октября, 2008 · Жалоба Мне кажется, постановка задачи немного неполна: насчитаны ли массивы заранее? Или они считаются между прерываниями? Если считаются по ходу времени, то лучше иметь 3 глобальные переменные. Теперь по существу. K&R говорят, что быстрее всего изменяется последний индекс массива. То есть массив pwm[256][3] даст самый быстрый доступ к элементам. Об этом уже сказали неявно предыдущие ораторы. Из практических советов - следует избегать адресной арифметики в прерывании в зависимости от мощности оптимизатора. Возможно, потребуется ручками указать последовательность действий. Можно написать так (не проверял, только для иллюстрации идеи): unsigned char pwm [256] [3]; volatile unsigned char pwmstep; // PWM main interrupt interrupt [TIM2_COMP] void timer2_comp_isr(void) { // Place your code here register unsigned char step = pwmstep; register unsigned char * sample = pwm [step]; PORTA=sample[0]; // *(sample ++) PORTB=sample[1]; // *(sample ++) PORTC=sample[2]; // *(sample ++) step++; pwmstep = step; } Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Сергей Борщ 123 9 октября, 2008 Опубликовано 9 октября, 2008 · Жалоба Можно попробовать так (компилятора нет под рукой для AVR):Навскидку: размер получившегося массива 3 байта, компилятор будет вызывать умножение на 3. Можно попробовать вот так: typedef struct { uint8_t a; uint8_t b; uint8_t c; } pwm_point_t union { pwm_point_t point[256]; uint8_t raw[]; } PWM; uint8_t *pIndex = PWM.raw; // PWM main interrupt interrupt [TIM2_COMP] void timer2_comp_isr(void) { // Place your code here PORTA = *pIndex++; PORTB = *pIndex++; PORTC = *pIndex++; if(pIndex == (uint8_t *)(&PWM + 1)) { pIndex = PWM.raw; } } PWM.point[x] использовать для заполнения массива. По ним тоже можно шагать указателем. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
VCucumber 0 9 октября, 2008 Опубликовано 9 октября, 2008 · Жалоба PORTA = *pIndex++; На сколько я помню свои эксперименты, результат компиляции будет совершенно одинаков с PORTA=pwm[pwmstep++]; Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Сергей Борщ 123 9 октября, 2008 Опубликовано 9 октября, 2008 · Жалоба На сколько я помню свои эксперименты, результат компиляции будет совершенно одинаков с PORTA=pwm[pwmstep++];Не должен. *pIndex++ указателю один раз за 256 итераций присваивается значение адреса, и дальше вычислять смещение уже не нужно. Собственно проверить-то просто: typedef struct { uint8_t a; uint8_t b; uint8_t c; } pwm_point_t; union { pwm_point_t point[256]; uint8_t raw[]; } PWM; uint8_t *pIndex = PWM.raw; uint16_t Index; // PWM main interrupt ISR(TIMER1_OVF_vect) { // Place your code here uint8_t *pTmp = pIndex; PORTD = *pTmp++; PORTB = *pTmp++; PORTC = *pTmp++; if(++pTmp == (uint8_t *)(&PWM + 1)) { pTmp = PWM.raw; } pIndex = pTmp; } ISR(TIMER0_OVF_vect) { // Place your code here uint16_t Tmp = Index; PORTD = PWM.raw[Tmp++]; PORTB = PWM.raw[Tmp++]; PORTC = PWM.raw[Tmp++]; if(++Tmp == sizeof(PWM.raw)) Tmp = 0; Index = Tmp; } и листинг (WinAVR). Первый вариант: 54 .section .text.__vector_9,"ax",@progbits 55 .global __vector_9 57 __vector_9: 58 .LFB25: 59 .LSM0: 60 /* prologue: frame size=0 */ 61 0000 1F92 push __zero_reg__ 62 0002 0F92 push __tmp_reg__ 63 0004 0FB6 in __tmp_reg__,__SREG__ 64 0006 0F92 push __tmp_reg__ 65 0008 1124 clr __zero_reg__ GAS LISTING D:/Temp/ccreYbyY.s page 2 66 000a 8F93 push r24 67 000c AF93 push r26 68 000e BF93 push r27 69 0010 CF93 push r28 70 0012 DF93 push r29 71 0014 EF93 push r30 72 0016 FF93 push r31 73 /* prologue end (size=12) */ 74 .LBB19: 75 .LSM1: 76 0018 A091 0000 lds r26,pIndex ; pTmp.68, pIndex 77 001c B091 0000 lds r27,(pIndex)+1 ; pTmp.68, pIndex 78 .LVL0: 79 .LSM2: 80 0020 FD01 movw r30,r26 ; pTmp.69, pTmp.68 81 .LVL1: 82 0022 8191 ld r24,Z+ ; D.2508, 83 0024 82BB out 50-0x20,r24 ; , D.2508 84 .LSM3: 85 0026 ED01 movw r28,r26 ; , pTmp.68 86 0028 8981 ldd r24,Y+1 ; temp.66, 87 002a 88BB out 56-0x20,r24 ; , temp.66 88 .LSM4: 89 002c 8181 ldd r24,Z+1 ; temp.67, 90 002e 85BB out 53-0x20,r24 ; , temp.67 91 .LSM5: 92 0030 1496 adiw r26,4 ; pTmp, 93 .LVL2: 94 0032 80E0 ldi r24,hi8(PWM+768) ; , 95 0034 A030 cpi r26,lo8(PWM+768) ; pTmp, 96 0036 B807 cpc r27,r24 ; pTmp, 97 0038 01F4 brne .L2 ; , 98 .LSM6: 99 003a A0E0 ldi r26,lo8(PWM) ; pTmp, 100 003c B0E0 ldi r27,hi8(PWM) ; pTmp, 101 .L2: 102 .LSM7: 103 003e B093 0000 sts (pIndex)+1,r27 ; pIndex, pTmp 104 0042 A093 0000 sts pIndex,r26 ; pIndex, pTmp 105 .LBE19: 106 /* epilogue: frame size=0 */ 107 0046 FF91 pop r31 108 0048 EF91 pop r30 109 004a DF91 pop r29 110 004c CF91 pop r28 111 004e BF91 pop r27 112 0050 AF91 pop r26 113 0052 8F91 pop r24 114 0054 0F90 pop __tmp_reg__ 115 0056 0FBE out __SREG__,__tmp_reg__ 116 0058 0F90 pop __tmp_reg__ 117 005a 1F90 pop __zero_reg__ 118 005c 1895 reti Второй вариант: 123 .section .text.__vector_8,"ax",@progbits 124 .global __vector_8 126 __vector_8: 127 .LFB26: 128 .LSM8: 129 /* prologue: frame size=0 */ 130 0000 1F92 push __zero_reg__ 131 0002 0F92 push __tmp_reg__ 132 0004 0FB6 in __tmp_reg__,__SREG__ 133 0006 0F92 push __tmp_reg__ 134 0008 1124 clr __zero_reg__ 135 000a 2F93 push r18 136 000c 4F93 push r20 137 000e 5F93 push r21 138 0010 8F93 push r24 139 0012 9F93 push r25 140 0014 AF93 push r26 141 0016 BF93 push r27 142 0018 EF93 push r30 143 001a FF93 push r31 144 /* prologue end (size=14) */ 145 .LBB20: 146 .LSM9: 147 001c 4091 0000 lds r20,IndexRaw ; Tmp, IndexRaw 148 0020 5091 0000 lds r21,(IndexRaw)+1 ; Tmp, IndexRaw 149 .LVL3: 150 .LSM10: 151 0024 80E0 ldi r24,lo8(PWM) ; tmp47, 152 0026 90E0 ldi r25,hi8(PWM) ; tmp47, 153 0028 FA01 movw r30,r20 ; tmp48, Tmp 154 002a E80F add r30,r24 ; tmp48, tmp47 155 002c F91F adc r31,r25 ; tmp48, tmp47 156 002e 2081 ld r18,Z ; D.2520, PWM.raw 157 0030 22BB out 50-0x20,r18 ; , D.2520 158 0032 FA01 movw r30,r20 ; Tmp.97, Tmp 159 .LVL4: 160 0034 3196 adiw r30,1 ; Tmp.97, 161 .LSM11: 162 0036 DF01 movw r26,r30 ; tmp51, Tmp.97 163 0038 A80F add r26,r24 ; tmp51, tmp47 164 003a B91F adc r27,r25 ; tmp51, tmp47 165 003c 2C91 ld r18,X ; temp.100, PWM.raw 166 003e 28BB out 56-0x20,r18 ; , temp.100 167 .LSM12: 168 0040 FD01 movw r30,r26 ; Tmp.97, tmp51 169 0042 8181 ldd r24,Z+1 ; temp.101, PWM.raw 170 0044 85BB out 53-0x20,r24 ; , temp.101 171 .LSM13: 172 0046 4C5F subi r20,lo8(-(4)) ; Tmp, 173 0048 5F4F sbci r21,hi8(-(4)) ; Tmp, 174 004a 5093 0000 sts (IndexRaw)+1,r21 ; IndexRaw, Tmp 175 004e 4093 0000 sts IndexRaw,r20 ; IndexRaw, Tmp 176 .LBE20: 177 /* epilogue: frame size=0 */ 178 0052 FF91 pop r31 179 0054 EF91 pop r30 180 0056 BF91 pop r27 181 0058 AF91 pop r26 182 005a 9F91 pop r25 183 005c 8F91 pop r24 184 005e 5F91 pop r21 185 0060 4F91 pop r20 186 0062 2F91 pop r18 187 0064 0F90 pop __tmp_reg__ 188 0066 0FBE out __SREG__,__tmp_reg__ 189 0068 0F90 pop __tmp_reg__ 190 006a 1F90 pop __zero_reg__ 191 006c 1895 reti Третий вариант: 196 .section .text.__vector_4,"ax",@progbits 197 .global __vector_4 199 __vector_4: 200 .LFB27: 201 .LSM14: 202 /* prologue: frame size=0 */ 203 0000 1F92 push __zero_reg__ 204 0002 0F92 push __tmp_reg__ 205 0004 0FB6 in __tmp_reg__,__SREG__ 206 0006 0F92 push __tmp_reg__ 207 0008 1124 clr __zero_reg__ 208 000a 2F93 push r18 209 000c 8F93 push r24 210 000e 9F93 push r25 211 0010 EF93 push r30 212 0012 FF93 push r31 213 /* prologue end (size=10) */ 214 .LBB21: 215 .LSM15: 216 0014 2091 0000 lds r18,Index ; Tmp, Index 217 .LVL5: 218 .LSM16: 219 0018 822F mov r24,r18 ; D.2529, Tmp 220 001a 9927 clr r25 ; D.2529 221 001c FC01 movw r30,r24 ; tmp50, D.2529 222 001e EE0F lsl r30 ; tmp50 223 0020 FF1F rol r31 ; tmp50 224 .LVL6: 225 0022 E80F add r30,r24 ; tmp50, D.2529 226 0024 F91F adc r31,r25 ; tmp50, D.2529 227 0026 E050 subi r30,lo8(-(PWM)) ; tmp50, 228 0028 F040 sbci r31,hi8(-(PWM)) ; tmp50, 229 002a 8081 ld r24,Z ; D.2530, <variable>.a 230 002c 82BB out 50-0x20,r24 ; , D.2530 231 .LSM17: 232 002e 8181 ldd r24,Z+1 ; D.2532, <variable>.b 233 0030 88BB out 56-0x20,r24 ; , D.2532 234 .LSM18: 235 0032 8281 ldd r24,Z+2 ; D.2534, <variable>.c 236 0034 85BB out 53-0x20,r24 ; , D.2534 237 .LBE21: 238 /* epilogue: frame size=0 */ 239 0036 FF91 pop r31 240 0038 EF91 pop r30 GAS LISTING D:/Temp/ccreYbyY.s page 5 241 003a 9F91 pop r25 242 003c 8F91 pop r24 243 003e 2F91 pop r18 244 0040 0F90 pop __tmp_reg__ 245 0042 0FBE out __SREG__,__tmp_reg__ 246 0044 0F90 pop __tmp_reg__ 247 0046 1F90 pop __zero_reg__ 248 0048 1895 reti Итого, победил sergeeff. Хотя другой компилятор может дать другие результаты. Совершенно непонятно, зачем компилятор в первом случае задействовал Y. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
VCucumber 0 9 октября, 2008 Опубликовано 9 октября, 2008 · Жалоба Не должен. Таки да, сэкономил полсотни байт. Видимо, куда-то не туда я смотрел. Там было копирование из флеша в массив vs загрузка массива константами. Но копирование по-прежнему побеждает, не смотря на то, что загрузка уменьшилась раза в два после замены индекса на указатель. Видимо, есть еще куда колдовать ) Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
VCucumber 0 9 октября, 2008 Опубликовано 9 октября, 2008 (изменено) · Жалоба Однако, радует то, что я все же не сглючил. Вот во что компилится инициализация массива с использованием индекса @000000D0: Get_serial_number 37: { +000000D0: 01FC MOVW R30,R24 Copy register pair 39: aValue[0] = (unsigned char)(Device_serial_number_3 >> 24); +000000D1: ED83 LDI R24,0xD3 Load immediate +000000D2: 8380 STD Z+0,R24 Store indirect with displacement 40: aValue[1] = (unsigned char)(Device_serial_number_3 >> 16); +000000D3: E987 LDI R24,0x97 Load immediate +000000D4: 8381 STD Z+1,R24 Store indirect with displacement 41: aValue[2] = (unsigned char)(Device_serial_number_3 >> 8); +000000D5: E585 LDI R24,0x55 Load immediate +000000D6: 8382 STD Z+2,R24 Store indirect with displacement 42: aValue[3] = (unsigned char)(Device_serial_number_3 >> 0); +000000D7: E082 LDI R24,0x02 Load immediate +000000D8: 8383 STD Z+3,R24 Store indirect with displacement 43: aValue[4] = (unsigned char)(Device_serial_number_2 >> 24); +000000D9: E284 LDI R24,0x24 Load immediate +000000DA: 8384 STD Z+4,R24 Store indirect with displacement А это с использованием указателя +000000D0: 01FC MOVW R30,R24 Copy register pair 56: *aValue++ = (unsigned char)(Device_serial_number_3 >> 24); +000000D1: ED83 LDI R24,0xD3 Load immediate +000000D2: 9381 ST Z+,R24 Store indirect and postincrement 57: *aValue++ = (unsigned char)(Device_serial_number_3 >> 16); +000000D3: E987 LDI R24,0x97 Load immediate +000000D4: 9381 ST Z+,R24 Store indirect and postincrement 58: *aValue++ = (unsigned char)(Device_serial_number_3 >> 8); +000000D5: E585 LDI R24,0x55 Load immediate +000000D6: 9381 ST Z+,R24 Store indirect and postincrement 59: *aValue++ = (unsigned char)(Device_serial_number_3 >> 0); +000000D7: E082 LDI R24,0x02 Load immediate +000000D8: 9381 ST Z+,R24 Store indirect and postincrement 60: *aValue++ = (unsigned char)(Device_serial_number_2 >> 24); +000000D9: E284 LDI R24,0x24 Load immediate +000000DA: 8380 STD Z+0,R24 Store indirect with displacement Т.е. разница, конечно, есть, но только не в размере и не в скорости выполнения. И такое сохранится до размера массива до 64 байт, т.е. пока будет хватать смещения (6 бит) в команде STD Z+disp, *. Для LDD могло бы быть так же. Изменено 9 октября, 2008 пользователем Огурцов Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
maik-vs 0 14 октября, 2008 Опубликовано 14 октября, 2008 · Жалоба Из трех массивов сделать один, расположив данные из них как [pwma0][pwmb0][pwmc0]...[pwmaN] Так лучше. Тогда получается LD Yh,high(pwmstep) LD Yl,low(pwmstep) ; load pointer LD tmp,Y+ OUT PORTA,tmp LD tmp,Y+ OUT PORTB,tmp LD tmp,Y+ OUT PORTC,tmp ST high(pwmstep),Yh ST low(pwmstep),Yl ; save pointer 17 циклов. Если unsigned char pwm [3][256], то нужно добавить inc Yh после каждого OUT - это дополнительно 3 цикла, плюс вычислить новый pwmstep это пахнет ещё 4-мя цмклами. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться