реклама на сайте
подробности

 
 
5 страниц V  < 1 2 3 4 5 >  
Reply to this topicStart new topic
> "Оптимизация" в WinAVR и как с этим бороться
ReAl
сообщение Nov 18 2011, 22:38
Сообщение #31


Нечётный пользователь.
******

Группа: Свой
Сообщений: 2 033
Регистрация: 26-05-05
Из: Бровари, Україна
Пользователь №: 5 417



Цитата(MaxiMuz @ Nov 18 2011, 18:06) *
большая - маленькая зависит от типа МК. Привожу конкретный пример:
Код
http://www.radio.ru/archive/2010/07/a19.shtml

программка писалась на асме под ATtiny2313, нехватило памяти программ под вторую таблицу мелодий для звонка. Если бы тогда писал на Си то вообще не хватилобы памяти на одну таблицу ! Это при том что я еще проводил оптимизацию программы в ассеблере sm.gif
Поверьте старому С-шнику, избегающему по мере возможности написания программ на асме -- Вам показалось.
Что Вы проводили оптимизацию этой ассемблерной программы.
Бегло просмотрел программу из архива, даже толком не вникая в алгоритмы. Просто мелкая местная оптимизация — и несколько десятков байт как с куста. А если ещё вникнуть в алгоритмы, то и того более найдётся.
Примеры:
Код
#ifndef OPTIMISED
     sbrc ModeR,BitModeAlrm
     rjmp Begin
     sbrc ModeR,BitModeWtch
     rjmp Begin
#else;;; -2
     sbrs ModeR,BitModeAlrm
     sbrc ModeR,BitModeWtch
     rjmp Begin
#endif
Там таких два места. На этой мелочи — уже 4 байта.

Любой уважающий себя С-компилятор покраснел бы от стыда за такой код:
Код
; Определение интервала 1
#ifndef OPTIMISED
; if ( MemdP <= Thr_AdP ) goto TCAdi11; else goto TCAdi12;
     cpi MemdPH,Thr_AdPH
     brcs TCAdi11
     brne TCAdi12
     cpi MemdPL,Thr_AdPL
     brcs TCAdi11
     brne TCAdi12
#else;;; -4 bytes
; if MemdP >= (Thr_AdP + 1) ) goto TCAdi12
     ldi temp, high( Thr_AdP + 1 )
     cpi MemdPL, low( Thr_AdP + 1)
     cpc MemdPH, temp
     brcc TCAdi12
#endif
Код
#ifndef OPTIMISED
; if ( MemdP <= DeltaT ) goto TCA12; esle goto TCA11;
     cp MemdPH,DeltaTH
     brcs TCA12
     brne TCA11
     cp MemdPL,DeltaTL
     brcs TCA12
     brne TCA11
#else
;;; -6
; if ( DeltaT >= MemdP ) goto TCA11;
     cp  DeltaTL,MemdPL
     cpc DeltaTH,MemdPH
     brcc TCA11
#endif
И таких мест там не одно.
Тут вообще что-то странное было.
CODE
;_________ Запись таблицы регистрации нажатий в EEPROM
;*
;*
CLI
push temp2
push ZL
push ZH
#ifndef OPTIMISED
clr ZL
clr ZH
b4: mov temp,ZL
ldi temp2,low(Edata1)
add temp,temp2
OUT EEAR,temp
ldi temp2,low(data1)
add ZL,temp2
LD temp,Z
sub ZL,temp2
OUT EEDR,temp
SBI EECR,EEMPE;
SBI EECR,EEPE
b5: sbic EECR,EEPE
rjmp b5
cpi ZL,MaxCount*2-1
breq b6
ld temp,Z+
rjmp b4
b6: ldi temp,low(EMrk1)
OUT EEAR,temp
ldi temp,0xab
OUT EEDR,temp
SBI EECR,EEMPE;
SBI EECR,EEPE

#else ;;; -14b

ldi ZL, low(data1)
clr ZH
ldi temp2, Edata1
b4:
ld temp, Z+
rcall WrEE
inc temp2
cpi temp2, MaxCount*2-1
brne b4
b6: ldi temp2,low(EMrk1)
ldi temp,0xab
rcall WrEE
#endif

pop ZH
pop ZL
pop temp2
SEI

m9:
CLR EnGen
clr count
m11:
;______ Задержка
ldi temp,ZDelayL
mov CL,temp
rcall DelayTime
Begin__:
rjmp Begin

#ifdef OPTIMISED
WrEE:
OUT EEAR,temp2
OUT EEDR,tempЯ
SBI EECR,EEMPE;
SBI EECR,EEPE
WrEEw: sbic EECR,EEPE
rjmp WrEEw
ret
#endif
Эта запись вообще дважды повторяется, в слегка разном окружении. Её всю в подпрограмму надо пустить.
Ещё tiny2313 есть регистры GPIOR, аж три штуки. Все флаги успешно летят туда без увеличения объёма кода с незначителным увеличением времени. Освобождается два регистра, причём "верхних". Явно где-то поможет сократить код.
Я бы постарался выделить регистровую пару Y под указатель на блок данных в DSEG, заменив все LDS/STS на LDD/STD. Ещё так на глаз минимум полсотни байт.
Напоминаю — это всё не особо вникая в суть кода.


--------------------
Ну, я пошёл… Если что – звоните…
Go to the top of the page
 
+Quote Post
MaxiMuz
сообщение Nov 20 2011, 11:58
Сообщение #32


Местный
***

Группа: Участник
Сообщений: 253
Регистрация: 15-04-10
Из: Волгоград
Пользователь №: 56 658



Цитата(neiver @ Nov 18 2011, 20:23) *
К сожалению, в avr-gcc LTO не работает. Компилятор к 5-ой аврстудии скомпилирован без поддержки LTO, я пытался скомпилировать avr-gcc сам со включеной LTO - не собрался, видимо чего-то в в AVR бекэнде не хватает.

У меня к сожелению, не достаточно глубокие познания в тонкостях компиляторов и знания абревиатур, да и практики маловато. Хотел узнать , что такое LTO ?

Цитата(ReAl @ Nov 19 2011, 01:38) *
Поверьте старому С-шнику, избегающему по мере возможности написания программ на асме -- Вам показалось.
Что Вы проводили оптимизацию этой ассемблерной программы.
Бегло просмотрел программу из архива, даже толком не вникая в алгоритмы. Просто мелкая местная оптимизация — и несколько десятков байт как с куста. А если ещё вникнуть в алгоритмы, то и того более найдётся.
Примеры:
Код
#ifndef OPTIMISED
     sbrc ModeR,BitModeAlrm
     rjmp Begin
     sbrc ModeR,BitModeWtch
     rjmp Begin
#else;;; -2
     sbrs ModeR,BitModeAlrm
     sbrc ModeR,BitModeWtch
     rjmp Begin
#endif
Там таких два места. На этой мелочи — уже 4 байта.

Я уважаю людей которые хорошо разбираются в С-ях ! sm.gif
Да, действительно я не достаточно тщательно провел оптимизацию данной программы ! И в приведнном примере , я возможно проглядел, либо просто не стал обращать внимание на эти мелочи ...

п.с. а про код "записи в ЕЕПРОМ" я прекрасно знал , просто в этой программе не стал его выделять в отдельную процедуру.

Цитата(ReAl @ Nov 19 2011, 01:38) *
Любой уважающий себя С-компилятор покраснел бы от стыда за такой код:
Код
; Определение интервала 1
#ifndef OPTIMISED
; if ( MemdP <= Thr_AdP ) goto TCAdi11; else goto TCAdi12;
     cpi MemdPH,Thr_AdPH
     brcs TCAdi11
     brne TCAdi12
     cpi MemdPL,Thr_AdPL
     brcs TCAdi11
     brne TCAdi12
#else;;; -4 bytes
; if MemdP >= (Thr_AdP + 1) ) goto TCAdi12
     ldi temp, high( Thr_AdP + 1 )
     cpi MemdPL, low( Thr_AdP + 1)
     cpc MemdPH, temp
     brcc TCAdi12
#endif
Код
#ifndef OPTIMISED
; if ( MemdP <= DeltaT ) goto TCA12; esle goto TCA11;
     cp MemdPH,DeltaTH
     brcs TCA12
     brne TCA11
     cp MemdPL,DeltaTL
     brcs TCA12
     brne TCA11
#else
;;; -6
; if ( DeltaT >= MemdP ) goto TCA11;
     cp  DeltaTL,MemdPL
     cpc DeltaTH,MemdPH
     brcc TCA11
#endif
И таких мест там не одно.

Суть правильная, только ваш оптимизатор почемуто в метках переходов ошибся ! при условии С=0 должна выполняться какраз противоположная ветвь !
Вот так доверяй потом оптимизаторам !!
И в данном куске, почему я сначала старшие байты решил проверять : хотел ускорить алгоритм проверки. Хотя сейчас понимаю что это не к чему было.

И всеже вернусь к использованию регистровых глобальных перемнных. В теме:заголовок
"Второй раз повторяю, GCC не поддерживает volatile register переменные. Не
поддерживает - это значит что нет гарантии что любой код использующий
volatile register переменные будет работать при любом уровне оптимизации. К
сожалению варинг сообщающий об этом пропал где-то в 2005 году и если я
правильно понял его вернули в феврале 2008. Попробуйте откомпилировать
тестовый пример с "volatile register" GCC 4.4 с клюем -Wall. Или с ключом
-Wvolatile-register-var на 4.3.

Анатолий. "
были упомянуты ключики. Я не нашел в дока назначение этих ключей, плохо ориентируюсь описании WinAVR. Есть ли возможность отключить в опциях использование компилятором конкретных регистров ?

Сообщение отредактировал MaxiMuz - Nov 20 2011, 11:15
Go to the top of the page
 
+Quote Post
ReAl
сообщение Nov 20 2011, 12:23
Сообщение #33


Нечётный пользователь.
******

Группа: Свой
Сообщений: 2 033
Регистрация: 26-05-05
Из: Бровари, Україна
Пользователь №: 5 417



Цитата(MaxiMuz @ Nov 20 2011, 12:55) *
Хотел узнать , что такое LTO ?
Link-Time-Optimiser
Зачатки его есть и в нынешнем линкере, ключ --relax. Это, например, превращение линкером длинного вызова в короткий. На этапе компиляции ещё неизвестно, насколько близко лягут куски из разных файлов и на больших кристаллах компилятром используется только длинный.
LTO делает полную оптимизацию, зная уже всё о линкуемой программе (включая устройство библиотечных функций, если они были скомпилировані с соо-тветствующим ключом).

Цитата(MaxiMuz @ Nov 20 2011, 12:55) *
Да,
действительно я не достаточно тщательно провел оптимизацию данной
программы ! И в приведнном примере , я возможно проглядел, либо просто
не стал обращать внимание на эти мелочи ...
Ну там дальше и не такие мелочи на cp/cpc набегают, как тут на пропусках.

Цитата(MaxiMuz @ Nov 20 2011, 12:55) *
п.с. а про код "записи в ЕЕПРОМ" я прекрасно знал , просто в этой программе не стал его выделять в отдельную процедуру.

И какой смысл после этого было говорить, что "на ассемблере влезла одна мелодия и то после оптимизации, а С и одна не влезла бы" ? ;-)
У С по длине выигрывает не любая ассемблерная реализация — только потому, что она ассемблерная biggrin.gif — а только действительно вылизанная.
Прикидочно, оценивая возможное ужатие Вашего кода байт на 150-200, — тут и С-шная реализация должна легко влезть.

Цитата(MaxiMuz @ Nov 20 2011, 13:58) *
Суть правильная, только ваш оптимизатор почемуто в метках переходов ошибся ! при условии С=0 должна выполняться какраз противоположная ветвь !
Ну там в одном из мест я для нужной нестрогости сравнивания поменял порядок операндов, мог забыть про смену полярности перехода. Это не важно, ошибки в коде любой длины бывают. Главное то, что код можно написать короче.
Там ещё ошибки есть, например, в одном из мест надо так:
Код
cpi    temp2, Edata1 + MaxCount*2-1
Это до меня уже в субботу утром, в метро по дороге на работу в дрёме дошло.
Отмазки:
1) Ну дак в пол второго ночи и наспех (вставать-то в шесть), да копипастом-редактированием (из головы я бы сразу правильно писал) и не такого наворотить можно
2) А С-компилятор и не ошибся бы с "полярностью" перехода.

Цитата(MaxiMuz @ Nov 20 2011, 13:58) *
Есть ли возможность отключить в опциях использование компилятором конкретных регистров ?
-ffixed-reg, например
-ffixed-reg=r2
Только нужно быть уверенным, что библиотека тоже этот регистр не использует.


--------------------
Ну, я пошёл… Если что – звоните…
Go to the top of the page
 
+Quote Post
MaxiMuz
сообщение Nov 23 2011, 11:30
Сообщение #34


Местный
***

Группа: Участник
Сообщений: 253
Регистрация: 15-04-10
Из: Волгоград
Пользователь №: 56 658



Цитата(ReAl @ Nov 20 2011, 15:23) *
........................................
-ffixed-reg, например
-ffixed-reg=r2
Только нужно быть уверенным, что библиотека тоже этот регистр не использует.

После вставики в Makefile
Код
CFLAGS += -ffixed-reg=r16
CFLAGS += -ffixed-reg=r18

Компилятор выдал ошибку:
Код
cc1.exe: warning: unknown register name: reg=r16
cc1.exe: warning: unknown register name: reg=r18

Что я не так делаю ?
И где можно найти описание всех ключей компилятора GCC
Go to the top of the page
 
+Quote Post
demiurg_spb
сообщение Nov 23 2011, 13:39
Сообщение #35


неотягощённый злом
******

Группа: Свой
Сообщений: 2 746
Регистрация: 31-01-08
Из: Санкт-Петербург
Пользователь №: 34 643



Цитата(MaxiMuz @ Nov 23 2011, 15:30) *
где можно найти описание всех ключей компилятора GCC
Как всегда в гугле, забив в строке поиска:
gcc optimization options


--------------------
“Будьте внимательны к своим мыслям - они начало поступков” (Лао-Цзы)
Go to the top of the page
 
+Quote Post
AHTOXA
сообщение Nov 23 2011, 14:40
Сообщение #36


фанат дивана
******

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



Код
CFLAGS    += -ffixed-r16
CFLAGS    += -ffixed-r18


--------------------
Если бы я знал, что такое электричество...
Go to the top of the page
 
+Quote Post
ReAl
сообщение Nov 23 2011, 21:19
Сообщение #37


Нечётный пользователь.
******

Группа: Свой
Сообщений: 2 033
Регистрация: 26-05-05
Из: Бровари, Україна
Пользователь №: 5 417



Тьху, ну конечно, -ffixed-reg
Что-то меня на = потянуло :-)

Цитата(demiurg_spb @ Nov 23 2011, 15:39) *
Как всегда в гугле, забив в строке поиска:
gcc optimization options
Если бы гугл умел посылать пользователя на его локальный диск в

file:///C:/WinAVR/doc/gcc/HTML/gcc-4.3.2/gcc/index.html

в частности,
file:///C:/WinAVR/doc/gcc/HTML/gcc-4.3.2/gcc/AVR-options.html
file:///C:/WinAVR/doc/gcc/HTML/gcc-4.3.2/gcc/Code-Gen-Options.html

а также

file:///C:/WinAVR/doc/avr-libc/avr-libc-user-manual/index.html

так он ещё бы трафик пользователю сэкономил.

___________________________
— А я так XP-шку до конца и не прошёл...
— Так это же не игрушка, а ОС
— Откуда инфа 8-O ???


--------------------
Ну, я пошёл… Если что – звоните…
Go to the top of the page
 
+Quote Post
MaxiMuz
сообщение Nov 25 2011, 08:40
Сообщение #38


Местный
***

Группа: Участник
Сообщений: 253
Регистрация: 15-04-10
Из: Волгоград
Пользователь №: 56 658



Спасибо за ответы !

Опять я возвращаюсь к своим любимым регистровым глобальным переменным.
Вначале программы обычно происходит инициализация переменных. В моей программе три регистровых глобальных переменных. Одна из них обьявленна как битовая область, и с ней проблем нет. Две других как беззнаковый байт (см. программу). В месте задания им начальных значений, компилятор игнорировал эти операции, чтобы я не делал. Все уровни оптимизации , кроме -O0 исключали эти команды. Но, после перемещения блока инициализации в отдельную подпрограмму , компилятор всеже их заметил, и правильно откомпилировал! У меня возникла мысль, что какието ключи не позволяют оптимизатору игнорировать команды в подпрограммах.
Хотел бы услышать ваши предположения.

Код
#include <avr/io.h>
#include <avr/interrupt.h>  // задает макросы sei() , cli()
#include <inttypes.h>

//=====================================================================
// определение регистров:
volatile register uint8_t FLCnt asm("r16"); //фоновый счетчик длительности переключения свдиода
volatile register uint8_t DBKCnt asm("r18"); //фоновый счетчик для отсчета периода блокировки опроса кнопок
volatile register struct
{
  uint8_t bDbRKey : 1;
  uint8_t bFLed : 1;
} RFGP asm ("r17");

//;----------------------------------------------------------------------------------------------------------------------------------------
//=== Определение макросов
#define sbi(p,b) (p |= (1<<b)) //Установить бит
//;----------------------------------------------------------------------------------------------------------------------------------------
//Определение портов:
/* направление для порта В*/
#define DIRB 0b00010001
/* Pull-ups для порта В*/
#define PUPB 0b00000101

//;----------------------------------------------------------------------------------------------------------------------------------------
//Определение контактов
#define Control1 PB4 /* линия управления VT (1 - откр; 0 - закр ) */
#define Btn1 PB2 /* линия кнопки (на общ.пров) */
#define Led PB0 /* линия светодиода ("1" - вкл. ч/з резистор на общ.) */

//;----------------------------------------------------------------------------------------------------------------------------------------
/* длительность запрета на опрос клавиш t=(101-1)*0,1=10 sec */
#define Vl_DBKCnt 101

/* t=5*0,1=0,5 sec */
#define Vl_FLCnt 5

// Маска кнопок:"Btn"
#define  KeyMask (1<<Btn1)|(1<<1)


//=====================================================================
//=====================================================================
SIGNAL ( SIG_OUTPUT_COMPARE0A)
{//______ Моргание светодиода t=5*0,1=0,5 sec
if (!(--FLCnt))
{//__ Переключение свдиода
  FLCnt=Vl_FLCnt;// перезагрузка ф.счетчика              !!!!
  ~(RFGP.bFLed);
  sbi (PINB,Led);// ________ Переключение свдиода !
}

//______ Формирование запрета на опрос клавиш t=(101-1)*0,1=10 sec
if (RFGP.bDbRKey==1)
{ //__ проверка на первый запуск
   if (DBKCnt == 0 )
    DBKCnt=Vl_DBKCnt;
   --DBKCnt;//__ продолжение счета
   if (DBKCnt==0) // checking of =0
   { //__ сброс флага
     RFGP.bDbRKey=0;
     DBKCnt=Vl_DBKCnt;
   }
}
}

//=============================================================================
//=============================================================================
int main (void)
{
//_________________________ ИНИЦИАЛИЗАЦИЯ _____________________________
uint8_t temp;

PORTB=PUPB; //иницализация порта B
DDRB=DIRB; // задание направления для порта B
TIMSK0=(1<<OCIE0A); /* установка разр. прер-ия по совпадению т/сч.0 с регистром OCR0A */
OCR0A=234; //загрузка регистра совпадения OCR0A коэф. деления
TCCR0A= (1<<WGM01); //установка режима СТС - обнуление Т/С0 при совпадении с регистром OCR0A
TCCR0B=(1<<CS02)|(1<<CS00); // <---- конфигурация и запуск сч-ка в реж. СТС с предделителем ckl/1024
RFGP.bDbRKey=0;
RFGP.bFLed=0;
[color="#ff0000"]DBKCnt=Vl_DBKCnt; //задание начальных значений для счетчиков
FLCnt=(uint8_t)Vl_FLCnt;[/color]

sei (); // Разрешение общего прерывания
//____________________ ЦИКЛ РАБОЧЕЙ ПРОГРАММЫ ______________________
while (1)
{ //____ Считывание кнопки
  temp=~(PINB);
  temp &= KeyMask;
  if (temp)
  {  //______ Обработка нажатия кн."Btn"
   if ( RFGP.bDbRKey==0)//____ проверка на запрет считывания кнопок
   { RFGP.bDbRKey=1; // sbr RFGP,(1<<bDbRKey)
     sbi (PINB,Control1); // ________ Переключение линии Control1 _______________!!!!!
   }
  }
}
}


Go to the top of the page
 
+Quote Post
Сергей Борщ
сообщение Nov 25 2011, 09:27
Сообщение #39


Гуру
******

Группа: Модераторы
Сообщений: 8 455
Регистрация: 15-05-06
Из: Рига, Латвия
Пользователь №: 17 095



QUOTE (MaxiMuz @ Nov 25 2011, 11:40) *
Хотел бы услышать ваши предположения.
Прочитайте еще раз про яйцо и микроволновку. Мне лень считать, сколько раз вам писали, что регистровую переменную нельзя делать volatile, о чем прямым текстом пишут создатели компилятора. Вы же с упорством пьяного продолжаете писать register volatile и пенять на компилятор.


--------------------
На любой вопрос даю любой ответ
"Write code that is guaranteed to work, not code that doesn’t seem to break" (C++ FAQ)
Go to the top of the page
 
+Quote Post
MaxiMuz
сообщение Nov 25 2011, 12:07
Сообщение #40


Местный
***

Группа: Участник
Сообщений: 253
Регистрация: 15-04-10
Из: Волгоград
Пользователь №: 56 658



Цитата(Сергей Борщ @ Nov 25 2011, 12:27) *
Прочитайте еще раз про яйцо и микроволновку. Мне лень считать, сколько раз вам писали, что регистровую переменную нельзя делать volatile, о чем прямым текстом пишут создатели компилятора. Вы же с упорством пьяного продолжаете писать register volatile и пенять на компилятор.

Извиняюсь что возмутил вас употребением и применением volatile !
Кстати сказать, из ответ на вопрос о использовании Volatile к регистровым глобальным переменным я со своим плохим знанием английского понял что компилятор уже считает регистровые переменные как volatile. Другими словами использование квалификатора бессмысленно.
Я убрал в обьявлении переменных FLCnt, DBKCnt volatile, результат тотже !
Вопрос остается открытым
Go to the top of the page
 
+Quote Post
AHTOXA
сообщение Nov 25 2011, 14:16
Сообщение #41


фанат дивана
******

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



Цитата(MaxiMuz @ Nov 25 2011, 18:07) *
Вопрос остается открытым

Какой?


--------------------
Если бы я знал, что такое электричество...
Go to the top of the page
 
+Quote Post
ReAl
сообщение Nov 25 2011, 14:35
Сообщение #42


Нечётный пользователь.
******

Группа: Свой
Сообщений: 2 033
Регистрация: 26-05-05
Из: Бровари, Україна
Пользователь №: 5 417



Цитата(AHTOXA @ Nov 25 2011, 16:16) *
Какой?

Почему регистровые переменную, вне зависимости от наличя слова volatile, компилятор, предупредивший о своём отношении к таким объявлениям, не рассматривает как volatile и выкидывает из main() их инициализацию, так как в этой же main() к переменным больше обращений нет, а про обращение к ним из прерываний компилятор «не знает».


--------------------
Ну, я пошёл… Если что – звоните…
Go to the top of the page
 
+Quote Post
AHTOXA
сообщение Nov 25 2011, 19:17
Сообщение #43


фанат дивана
******

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



По-моему, на этот вопрос тоже уже ответили, и не раз sm.gif
Я на всякий случай ещё раз повторю ответ: да, в этом моменте компилятор работает криво.
Варианты решения проблемы тоже вроде все предложены:
  1. Не использовать регистровые переменные.
  2. Использовать, но не в качестве volatile-переменных.
  3. Использовать, но для обращения к этим переменным применять подпрограммы на (инлайн-)ассемблере.



--------------------
Если бы я знал, что такое электричество...
Go to the top of the page
 
+Quote Post
ReAl
сообщение Nov 25 2011, 20:32
Сообщение #44


Нечётный пользователь.
******

Группа: Свой
Сообщений: 2 033
Регистрация: 26-05-05
Из: Бровари, Україна
Пользователь №: 5 417



Провёл маленький эксперимент.
Убрал все эти register... asm()
Начало файла стало выглядеть так:

Код
//=====================================================================
// определение регистров:
volatile uint8_t FLCnt;
volatile uint8_t DBKCnt;

#define DbRKey 0x01
#define FLed   0x02


Обработчик прерывания так:
Код
SIGNAL(SIG_OUTPUT_COMPARE0A)
{        
    uint8_t temp;

    temp = FLCnt;
    if (!(--temp)) {
        temp = Vl_FLCnt;
        //    ~(RFGP.bFLed);  Эта штука ничего осмысленного не делает.
        //    и в выходном коде от неё ничего И НЕ БЫЛО
        PINB |= _BV(Led);
    }
    FLCnt = temp;

    if ( GPIOR0 & DbRKey ) {
        temp = DBKCnt;
        // на мой взгляд странные манипуляции, но оставил как есть
        if (temp == 0)
            temp = Vl_DBKCnt;
        --temp;        
        if (temp == 0){    
            GPIOR0 &= ~DbRKey;
            temp = Vl_DBKCnt;
        }
        DBKCnt = temp;
        }
}

При компиляции для atmega168 количество команд в обработчиках прерывания для старого и нового варианта кода сохранилось.
Все push/pop в начале и в конце обработчика совпадают, общий ход практически тот же. Просто несколько команд mov заменилось на lds, sts.
В итоге длина в байтах для нового варианта увеличилась на 8 байт и стала 66 байт.
Время выполнения увеличилось на 4 такта.
Только время тут «абсолютно», а вот освобождение трёх зафиксированных до этого регистров освободит руки компилятору в других местах и общая длина кода всей программы ещё и уменьшиться может.

За что боролись?

Думаю, сначала нужно научиться просто на С писать, а потом про все эти зафиксированные регистры думать.


--------------------
Ну, я пошёл… Если что – звоните…
Go to the top of the page
 
+Quote Post
MaxiMuz
сообщение Nov 28 2011, 10:59
Сообщение #45


Местный
***

Группа: Участник
Сообщений: 253
Регистрация: 15-04-10
Из: Волгоград
Пользователь №: 56 658



AHTOXA с вами не поспоришь sm.gif

ReAl По сути , кусок из вашего варианта :
Код
   temp = FLCnt;
    if (!(--temp)) {

подобен коду сформированному с использованием регистровых переменных:
Код
         if (!(--FLCnt))
  2e: 80 2f        mov r24, r16
  30: 81 50        subi r24, 0x01; 1
  32: 08 2f        mov r16, r24
  34: 11 f4        brne .+4

Но даже если закрыть глаза на бессмысленные mov rd,rs , как вы сами признали чуть быстрее и меньше по коду. И в использование возможностей железа по максимуму, даже учитывая корявость компилятора, нет ничего предосудительного sm.gif А абстрагирование от железа приводит к появлению таких опусов как Win7 ! с неоправданно раздутым кодом и тормозным ядром !
А если используется мощн.математический аппарат, то как я себе это представляю, здесь полезно оценить что важнее, быстый доступ к регистровым переменным или быстрое выполнение мат.операций.
Код
if ( GPIOR0 & DbRKey )
кстати в ATtiny13 (под него я пишу код) нет таких регистров вв./выв. которые можно так использовать!

Цитата(ReAl @ Nov 25 2011, 23:32) *
..........................
Думаю, сначала нужно научиться просто на С писать, а потом про все эти зафиксированные регистры думать.

с вами полностью согласен , но гибкое использование железа тоже часть "знания Си"

Сообщение отредактировал MaxiMuz - Nov 28 2011, 10:56
Go to the top of the page
 
+Quote Post

5 страниц V  < 1 2 3 4 5 >
Reply to this topicStart new topic
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 


RSS Текстовая версия Сейчас: 27th June 2025 - 13:25
Рейтинг@Mail.ru


Страница сгенерированна за 0.01564 секунд с 7
ELECTRONIX ©2004-2016