Оптимизация задержек

Микроконтроллеры обычно работают напрямую с физическим миром, а не только с астрактным миром цифр. А реальность не терпит поспешностей. Иногда нужно немного подождать. Казалось бы, чего уж проще - написать процедуру задержки. А ведь нет! Написать то легко, а вот каков результат будет в машинных кодах? Три команды или тридцать три?

Вот и мне потребовалось реализовать задержку в сишной программе для ATtiny2313. Микроконтроллер ресурсами не блещет, а потому каждая команда на счету.

Первоначально, я применил подсмотренную где-то методу написания задержки:

volatile uint8_t i; for(i=0; i<8; i++) ; 

На первый взгляд просто и понятно. На второй взгляд:

     std Y+1,__zero_reg__
     rjmp .L10
 .L11:
     ldd r24,Y+1
     subi r24,lo8(-(1))
     std Y+1,r24
 .L10:
     ldd r24,Y+1
     cpi r24,lo8(8)
     brlo .L11 

На второй взгляд - плохо. Компилятор разложил цикл по учебнику и разместил переменную в памяти, она же volatile. А цикл без volatile переменной оптимизатор выкинет, как ничего полезного не делающий. Значит нам надо делать “полезную” работу в цикле, а от volatile переменной отказаться.

uint8_t i; for(i=0; i<8; i++) asm volatile ("nop"); 

Код уже получается не таким элегантным, и уже условно переносимым (операция nop в разных ассемблерах как правило означает одно и тоже).

     ldi r25,lo8(0)
 .L11:
     nop
     subi r25,lo8(-(1))
     cpi r25,lo8(8)
     brne .L11 

Уже лучше, но не идеально. Есть, есть ещё куда рости. А потому проделаем следующее. Сделаем цикл не по инкременту, а по декременту (зачем нам сравнение). И выкинем из ассемблерной вставки вообще все команды:

uint8_t i; for(i=7; i; i--) asm volatile (""); 

Бинго! Наш код очистился!

   ldi r25,lo8(7)
 .L11:
     subi r25,lo8(-(-1))
     brne .L11 

Если мы возьмём этот код и скомпилируем его для ARM ядра, получим схожую картину:

   mov r0, #77
 .L2:
     subs r0, r0, #1
     bne .L2 

Все компиляции производились компилятором GCC, точнее его кросс-версиями avr-gcc и arm-none-eabi-gcc. Ключ оптимизации выставлялся -Os. Для других ключей и компиляторов результат может быть иной.

 
comments powered by Disqus