Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: Как бы оптимальней закодировать алгоритм
Форум разработчиков электроники ELECTRONIX.ru > Микроконтроллеры (MCs) > AVR
_Артём_
Здраствуйте.
Посоветуйте как оптимальней (по скорости исполнения) реализовать алгоритм для xmega256A3:
Обрабатываются 8 каналов ацп A и 8 каналов ацп B.
Каждый канал ацп суммируется 16 раз в прерывании таймера, кроме того каналы ацп а могут использоваться как логические входы (пороги задаются), и также перепады могут фиксироваться (инкремент счётчика). В каждом прерывании считываются и запускается 4 преобразования ацп а и 4 ацп Б.
CODE
#ifndef adc_h__
#define adc_h__

#include "avr_compiler.h"
#include "adc_driver.h"



#include "adc_driver.h"

struct TADC_AChannel {// данные канала на АЦП А
unsigned char Cnt;// счётчик передов
unsigned char CntUp;// считать фронт
unsigned char CntDown;// считать срез
unsigned char State;// состояние входа
unsigned char NextMux;// значение MUX
unsigned short LvlH, LvlL;// уровни 1 и 0
unsigned short Sum;// накопленная сумма
void Init(
unsigned short level_h, // уровень 1
unsigned short level_l, // уровень 0
unsigned char cnt_mode, // счёт. импульсов/ аналоговый вход
unsigned char state // начальное логическое состояние
) {
Cnt=0;
LvlH=level_h;
LvlL=level_l;
CntUp = (cnt_mode&1) ? (1) : (0);
CntDown = (cnt_mode&2) ? (1) : (0);
State=state;
}
void Exec(unsigned short new_value) {
if (Cnt) {
// режим счёта импульсов
if (State) {
if (new_value<LvlL) {
State=0;
if (CntDown)
Cnt++;
}
}
else {
if (new_value>LvlH) {
State=1;
if (CntUp)
Cnt++;
}
}
}
Sum+=new_value;
}
};

struct TADC_BChannel {// данные канала на АЦП А
unsigned short Sum;// накопление суммы
unsigned char NextMux;
void Exec(unsigned short new_value) {
Sum+=new_value;
}
};



class TAdc {
unsigned char ADCAMode;
volatile unsigned char ActiveArray;
volatile unsigned char SumReady;
struct TADC_AChannel AdcA[2][8];
struct TADC_BChannel AdcB[2][8];

volatile unsigned char ADCReady;
unsigned char CycleCnt;


public:
void StartNextConvervion()
{
TADC_AChannel *adc_ptr;

// определение текущего блока памяти для записи
unsigned char active_block = (ActiveArray) ? (1) : (0);
adc_ptr= (active_block) ? (&AdcA[1][0]) : (&AdcA[0][0]);

if (CycleCnt&1)
adc_ptr+=4; // чтение каналов 4-7
unsigned short adc_result;

// виртуальный канал 0 АЦП А
adc_result=ADCA.CH0.RES;
adc_ptr->Exec(adc_result);
ADCA.CH0.MUXCTRL=adc_ptr->NextMux;
adc_ptr++;

// виртуальный канал 1 АЦП А
adc_result=ADCA.CH1.RES;
adc_ptr->Exec(adc_result);
ADCA.CH1.MUXCTRL=adc_ptr->NextMux;
adc_ptr++;

// виртуальный канал 2 АЦП А
adc_result=ADCA.CH2.RES;
adc_ptr->Exec(adc_result);
ADCA.CH2.MUXCTRL=adc_ptr->NextMux;
adc_ptr++;

// виртуальный канал 3 АЦП А
adc_result=ADCA.CH3.RES;
adc_ptr->Exec(adc_result);
ADCA.CH3.MUXCTRL=adc_ptr->NextMux;
adc_ptr++;

struct TADC_BChannel *adcb_ptr=(active_block) ? (&AdcB[1][0]) : (&AdcB[0][0]);

// виртуальный канал 1 АЦП B
adc_result=ADCB.CH0.RES;
adcb_ptr->Exec(adc_result);
ADCB.CH0.MUXCTRL=adcb_ptr->NextMux;
adcb_ptr++;

// виртуальный канал 2 АЦП B
adc_result=ADCB.CH1.RES;
adcb_ptr->Exec(adc_result);
ADCB.CH1.MUXCTRL=adcb_ptr->NextMux;
adcb_ptr++;

// виртуальный канал 3 АЦП B
adc_result=ADCB.CH2.RES;
adcb_ptr->Exec(adc_result);
ADCB.CH2.MUXCTRL=adcb_ptr->NextMux;
adcb_ptr++;

// виртуальный канал 4 АЦП B
adc_result=ADCB.CH3.RES;
adcb_ptr->Exec(adc_result);
ADCB.CH3.MUXCTRL=adcb_ptr->NextMux;
adcb_ptr++;

// запуск преобразования
ADC_Conversions_Start(&ADCA, 0xF<<2);
ADC_Conversions_Start(&ADCB, 0xF<<2);

if (++CycleCnt>=16) {
// накоплено 16 отсчётов
CycleCnt=0;
adc_ptr= (active_block) ? (&AdcA[0][0]) : (&AdcA[1][0]);
TADC_AChannel *adc_ptr2= (active_block) ? (&AdcA[1][0]) : (&AdcA[0][0]);
for (char i=0; i<16; i++) {
adc_ptr->Cnt=0;
adc_ptr->Sum=0;
adc_ptr->State=adc_ptr2->State;
adc_ptr++;
adc_ptr2++;
}
adcb_ptr=(active_block) ? (&AdcB[0][0]) : (&AdcB[1][0]);
for (char i=0; i<16; i++) {
adcb_ptr->Sum=0;
}
SumReady=1;
}
}
};



extern TAdc Adc;
void InitADC();

#endif // adc_h__


Прерывание:

Код
TAdc Adc;
ISR(TCC0_OVF_vect)
{
    Adc.StartNextConvervion();
}


IAR выдал код с временем выполнения 450-550 циклов в зависимости от настроек оптимизации, что не есть гуд.
Из интереса создал проект для GCC, проверил в симуляторе ~320-350 тактов (не ожидал такого результата - удивлён).
Как получить от IAR похожий результат?

P.S. Проект сначала не компилился для GCC:
Код
In file included from ../../avr_compiler.h:132:0,
                 from ../task1.cpp:2:
c:\avr_toolchain\bin\../lib/gcc/avr/4.5.1/../../../../avr/include/util/delay.h: In function 'void _delay_ms(double)':
c:\avr_toolchain\bin\../lib/gcc/avr/4.5.1/../../../../avr/include/util/delay.h:149:42: error: 'fabs' was not declared in this scope
c:\avr_toolchain\bin\../lib/gcc/avr/4.5.1/../../../../avr/include/util/delay.h:149:43: error: 'ceil' was not declared in this scope
c:\avr_toolchain\bin\../lib/gcc/avr/4.5.1/../../../../avr/include/util/delay.h: In function 'void _delay_us(double)':
c:\avr_toolchain\bin\../lib/gcc/avr/4.5.1/../../../../avr/include/util/delay.h:226:42: error: 'fabs' was not declared in this scope
c:\avr_toolchain\bin\../lib/gcc/avr/4.5.1/../../../../avr/include/util/delay.h:226:43: error: 'ceil' was not declared in this scope
make: *** [task1.o] Ошибка 1

Что за ...?
Прект:Нажмите для просмотра прикрепленного файла
Закоментировал delay.h. Тогда откомпилировалось.
demiurg_spb
Цитата(_Артём_ @ Feb 1 2012, 04:02) *
P.S. Проект сначала не компилился для GCC:
Код
In file included from ../../avr_compiler.h:132:0,
                 from ../task1.cpp:2:
c:\avr_toolchain\bin\../lib/gcc/avr/4.5.1/../../../../avr/include/util/delay.h: In function 'void _delay_ms(double)':
c:\avr_toolchain\bin\../lib/gcc/avr/4.5.1/../../../../avr/include/util/delay.h:149:42: error: 'fabs' was not declared in this scope
c:\avr_toolchain\bin\../lib/gcc/avr/4.5.1/../../../../avr/include/util/delay.h:149:43: error: 'ceil' was not declared in this scope
c:\avr_toolchain\bin\../lib/gcc/avr/4.5.1/../../../../avr/include/util/delay.h: In function 'void _delay_us(double)':
c:\avr_toolchain\bin\../lib/gcc/avr/4.5.1/../../../../avr/include/util/delay.h:226:42: error: 'fabs' was not declared in this scope
c:\avr_toolchain\bin\../lib/gcc/avr/4.5.1/../../../../avr/include/util/delay.h:226:43: error: 'ceil' was not declared in this scope
make: *** [task1.o] Ошибка 1

Что за ...?
Прект:Нажмите для просмотра прикрепленного файла
Закоментировал delay.h. Тогда откомпилировалось.

подключите math.h перед delay.h
- это писатели avr-libc оплошали, ИМХО math.h стоило подключить внутри delay.h.
follow_me
похоже что GCC инлайнит
adc_ptr->Exec(adc_result);
а IAR нет

вы игрались с настройками оптимизации компилятора?

должен отметить что код чистенький и ухоженный - многим стоило бы поучиться писать так

единственная придирка - не внятные имена некоторых переменных, а так 5
_Артём_
Цитата(demiurg_spb @ Feb 1 2012, 06:57) *
подключите math.h перед delay.h
- это писатели avr-libc оплошали, ИМХО math.h стоило подключить внутри delay.h.


Да, понятно, оплошали.

Цитата(follow_me @ Feb 1 2012, 07:05) *
похоже что GCC инлайнит
adc_ptr->Exec(adc_result);
а IAR нет

Похоже на то
Забыл inline.
Поставил
Код
#pragma inline=forced
    inline void Exec(unsigned short new_value) {


Стало 360 циклов.
Цитата(follow_me @ Feb 1 2012, 07:05) *
единственная придирка - не внятные имена некоторых переменных, а так 5

Какие имена не очень?

Спасибо.
_Артём_
Не получается установить оптимизацию. Делаю так (по результату виу что эфекта нет)
Код
#pragma optimize=speed
    Adc.StartNextConvervion();
#pragma optimize=balanced

Как правильно?
Сергей Борщ
QUOTE (_Артём_ @ Feb 2 2012, 20:28) *
Не получается установить оптимизацию. Делаю так (по результату виу что эфекта нет)
В документации когда-то было упоминание, что эта прагма позволяет лишь понизить уровень оптимизации или вернуть после понижения к исходному.
Genadi Zawidowski
А что мешает установиь оптимизацию глобально - в установках проекта? Или работать перестаёт?
_Артём_
Цитата(Genadi Zawidowski @ Feb 3 2012, 12:22) *
А что мешает установиь оптимизацию глобально - в установках проекта? Или работать перестаёт?


Глобально установить можно, работает.
Но если я хочу часть проекта(часть файла в проекте) оптимизировать как balanced, а часть (Adc.StartNextConvervion) по скорости.
Вот и тут мне не ясно, возможно ли прагмами управлять этим процессом и как, если возможно.
_Артём_
Цитата(Сергей Борщ @ Feb 3 2012, 09:04) *
В документации когда-то было упоминание, что эта прагма позволяет лишь понизить уровень оптимизации или вернуть после понижения к исходному.

Тогда получается, что оптимизацию inline-функции можно задать только настройкой оптимизации проекта или файла в котором вызывается функция?
Или есть другие варианты?

sKWO
Цитата(_Артём_ @ Feb 5 2012, 17:28) *
Тогда получается, что оптимизацию inline-функции можно задать только настройкой оптимизации проекта или файла в котором вызывается функция?

Прагмами Вы можете оптимизировать критические участки кода в зоне действия прагмы.
А оптимизация для всего прожекта задаётся в его настройках и касается всех файлов подклёчённых к нему.
_Артём_
Цитата(sKWO @ Feb 14 2012, 21:01) *
А оптимизация для всего прожекта задаётся в его настройках и касается всех файлов подклёчённых к нему.

Это для GCC?
В IAR можно задать настройки оптимизации для каждого файла в проекте индивидуально.
Для GCC наверное тоже подобное возможно с помащью редактирования makefile.
sKWO
и как уже было сказано, повысить оптимизацию не получится чем в глобальных настройках.
если совсем печально ведёт себя компилятор, то асм ещё никто не отменял, на примеры подключения и написания на асме есть нормальная ссылка в ветке исходников программ и библиотек


Цитата(_Артём_ @ Feb 2 2012, 21:28) *
Как правильно?

цитата (IAR Compiler reference):
The #pragma directive is defined by the ISO/ANSI C standard and is a
mechanism for using vendor-specific extensions in a controlled way to make
sure that the source code is still portable.
The pragma directives control the behavior of the compiler, for example how
it allocates memory for variables and functions, whether it allows extended
keywords, and whether it outputs warning messages.
The pragma directives are always enabled in the compiler.

...

#pragma optimize=param[, param,...]

param:

s Optimizes for speed
z Optimizes for size
2|none|3|low|6|medium|9|high Specifies the level of optimization

и, ещё ИМХО прагмами играют когда ИАР некоторые функции "заоптимизирувает" как говорится, и когода не помогает волотайл для переменной, тогда играют с понижением оптимизации, потому и результата Вы и не увидели, опять же ИМХО.
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.