Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: Помогите переписать код для GCC под IAR
Форум разработчиков электроники ELECTRONIX.ru > Микроконтроллеры (MCs) > Cредства разработки для МК > IAR
smk
Суть такова: помещаем массив во flash и потом побайтно читаем.
В GCC:

Код
unsigned char brightness[256] PROGMEM = //табличка визуально равномерно наращивающая яркость
{0,0,0,1,1,2,2,3,3,4,4,4,5,5,6,6,6,7,7,8,8,8,9,9,10,10,10,11,11,12,12,
12,12,13,13,13,13,13,14,14,14,14,15,15,15,16,16,16,16,17,17,17,18,18,
18,19,19,19,19,20,20,20,21,21,21,22,22,22,22,23,23,23,24,24,24,25,25,
25,25,26,26,26,27,27,27,28,28,28,28,29,29,30,30,31,31,32,32,33,34,34,
35,35,36,37,38,38,39,40,41,41,42,43,44,44,45,46,47,48,48,49,50,51,52,
52,53,54,55,56,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,74,
75,76,77,78,79,80,82,83,84,86,87,88,89,91,92,94,95,97,99,101,102,104,
106,107,109,111,113,114,116,118,120,122,123,125,127,129,131,134,136,
138,140,142,145,147,149,151,153,156,158,160,162,164,167,169,171,173,
175,177,179,182,184,186,188,190,192,193,195,197,198,200,202,203,205,
206,208,210,211,213,215,217,218,220,222,223,225,226,228,229,231,232,
233,235,236,237,239,240,241,242,243,244,245,246,247,249,250,251,252,
253,254,255};

if((pwm>pgm_read_byte(&brightness[count_pwm]))|(pwm==0)){sig_off;}


А как такое делается в IAR? Спасибо.
shmur
Объявить как const и IAR сам поместит в ro секцию.

Или явно указать место, куда нужно поместить
Код
#pragma location="PROGMEM"
unsigned char brightness[256] =
//или так
unsigned char brightness[256] @ PROGMEM  =
_Артём_
Цитата(smk @ Feb 1 2012, 18:39) *
Суть такова: помещаем массив во flash и потом побайтно читаем.
В GCC:

Код
unsigned char brightness[256] PROGMEM = //табличка визуально равномерно наращивающая яркость
{0,0,0,1,1,2,2,3,3,4,4,4,5,5,6,6,6,7,7,8,8,8,9,9,10,10,10,11,11,12,12,
12,12,13,13,13,13,13,14,14,14,14,15,15,15,16,16,16,16,17,17,17,18,18,
18,19,19,19,19,20,20,20,21,21,21,22,22,22,22,23,23,23,24,24,24,25,25,
25,25,26,26,26,27,27,27,28,28,28,28,29,29,30,30,31,31,32,32,33,34,34,
35,35,36,37,38,38,39,40,41,41,42,43,44,44,45,46,47,48,48,49,50,51,52,
52,53,54,55,56,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,74,
75,76,77,78,79,80,82,83,84,86,87,88,89,91,92,94,95,97,99,101,102,104,
106,107,109,111,113,114,116,118,120,122,123,125,127,129,131,134,136,
138,140,142,145,147,149,151,153,156,158,160,162,164,167,169,171,173,
175,177,179,182,184,186,188,190,192,193,195,197,198,200,202,203,205,
206,208,210,211,213,215,217,218,220,222,223,225,226,228,229,231,232,
233,235,236,237,239,240,241,242,243,244,245,246,247,249,250,251,252,
253,254,255};

if((pwm>pgm_read_byte(&brightness[count_pwm]))|(pwm==0)){sig_off;}


А как такое делается в IAR? Спасибо.

Так например:
Код
__flash unsigned char brightness[256]={.....}
if (brightness[count_pwm]....) {...}
smk
Сделал #pragma location="PROGMEM". Теперь вот такую ошибку пишет.

Код
Error[Pe095]: array is too large D:\DATA\IAR_AVR\DatMSL\DatMSL_main.c 16
Error[Be010]: segment/section name not allowed (object must have static storage duration and be const or __no_init) D:\DATA\IAR_AVR\DatMSL\DatMSL_main.c 16


Цитата(_Артём_ @ Feb 1 2012, 19:09) *
Так например:
Код
__flash unsigned char brightness[256]={.....}
if (brightness[count_pwm]....) {...}

Пробовал. выдает ошибку.

В нелпе как-то через указатель делается. Кто-то так делал?
_Артём_
Цитата(shmur @ Feb 1 2012, 18:54) *
Объявить как const и IAR сам поместит в ro секцию.

Нет не поместит (в общем случае)
Код
__root const unsigned char StartStr[]="1234";

StartStr помещена в SRAM по адресу 0x214E. Нужно явно указывать в настройках (почему-то нельзя выбрать
Нажмите для просмотра прикрепленного файла)
smk
Цитата(_Артём_ @ Feb 1 2012, 19:18) *
Нет не поместит (в общем случае)
Код
__root const unsigned char StartStr[]="1234";

StartStr помещена в SRAM по адресу 0x214E. Нужно явно указывать в настройках (почему-то нельзя выбрать
Нажмите для просмотра прикрепленного файла)

Галка там есть и была раньше.
_Артём_
Цитата(smk @ Feb 1 2012, 19:15) *
Сделал #pragma location="PROGMEM". Теперь вот такую ошибку пишет.

Код
Error[Pe095]: array is too large D:\DATA\IAR_AVR\DatMSL\DatMSL_main.c 16
Error[Be010]: segment/section name not allowed (object must have static storage duration and be const or __no_init) D:\DATA\IAR_AVR\DatMSL\DatMSL_main.c 16



Пробовал. выдает ошибку.

В нелпе как-то через указатель делается. Кто-то так делал?

У меня работает.
Код
__root __farflash unsigned char brightness[256]={....}
void SystemTimer() {
    PORTB.OUT=brightness[int_cnt++];
}

Может места нет?
Цитата
Галка там есть и была раньше.

Странно что её выбрать/отменить нельзя - неразрешена.
shmur
Цитата(smk @ Feb 1 2012, 20:15) *
Сделал #pragma location="PROGMEM". Теперь вот такую ошибку пишет.

Код
Error[Pe095]: array is too large D:\DATA\IAR_AVR\DatMSL\DatMSL_main.c 16
Error[Be010]: segment/section name not allowed (object must have static storage duration and be const or __no_init) D:\DATA\IAR_AVR\DatMSL\DatMSL_main.c 16


Нужно с const
Код
#pragma location="PROGMEM"
[b]const[/b] unsigned char brightness[256] = {...}

PROGMEM должен быть определен в конфиг файле линкера, примерно так:
place in ROM_region { readonly section PROGMEM };

Если что курите иаровский DevelopmentGuide, там обо всем этом неплохо написано.
_Артём_
Кстати, а что за проц?
Я про АВР писал, у других архитектур может быть иначе.
SSerge
способов куча, смотря что нужно.

1. через #pragma location=
только там писать не "PROGMEM", а имя сегмента памяти. Можно завести свой, можно посмотреть в документации как называются те, что компилятор сам использует.

2. через extended keywords, а конкретно __flash или __farflash
Удобно тем, что не нужно руками заводить сегментов как в (1) и потом объяснять линкеру что с этими сегментами делать.

3. Объявлять переменную с модификатором const, но по умолчанию он поместит такую переменную в RAM и проинициализирует, нужно это где-то в настройках указывать.

Функции типа pgm_read_byte() для доступа не нужны, компилятор сам знает как прочитать из флэши.

В папке /doc есть подробная дока, где описаны все особенности реализации, расширения языка и прочее.
smk
Цитата(_Артём_ @ Feb 1 2012, 20:06) *
Кстати, а что за проц?
Я про АВР писал, у других архитектур может быть иначе.

Tiny13a

Сделал вот так
Код
__flash const unsigned char brightness[256] =


Пишет ошибку
Код
Error[e16]: Segment CODE (size: 0x30e align: 0x1) is too long for segment definition. At least 0x26 more bytes needed. The problem occurred while processing the segment placement command  
"-Z(CODE)CODE=_..X_FLASH_BASE-_..X_FLASH_END", where at the moment of placement the available memory ranges were "CODE:118-3ff"
   Reserved ranges relevant to this placement:
   CODE:14-113          NEAR_F
   CODE:114-117         INITTAB
   CODE:118-3ff         CODE


И еще это почему-то не нравится

Код
unsigned int read_adc (void)
{
unsigned int adc_res=0;
ADCSRA |= (1<<6);
while (!(ADCSRA & (1<<4)));
adc_res = ((ADCH<<8)+ADCL);
return adc_res;
}


Код
Warning[Pa082]: undefined behavior: the order of volatile accesses is undefined in this statement D:\DATA\IAR_AVR\DatMSL\DatMSL_main.c 54



_Артём_
Цитата(smk @ Feb 1 2012, 20:23) *
Tiny13a

Сделал вот так
Код
__flash const unsigned char brightness[256] =


Пишет ошибку
Код
Error[e16]: Segment CODE (size: 0x30e align: 0x1) is too long for segment definition. At least 0x26 more bytes needed. The problem occurred while processing the segment placement command  
"-Z(CODE)CODE=_..X_FLASH_BASE-_..X_FLASH_END", where at the moment of placement the available memory ranges were "CODE:118-3ff"
   Reserved ranges relevant to this placement:
   CODE:14-113          NEAR_F
   CODE:114-117         INITTAB
   CODE:118-3ff         CODE


Цитата
At least 0x26 more bytes needed.

Что-то памяти ему мало. Попробуйте уменьшить массив на 0x26 байт или упростите программу (только чтобы посмотреть откомпилируется ли и куда положит)

Цитата(smk @ Feb 1 2012, 20:23) *
Код
Warning[Pa082]: undefined behavior: the order of volatile accesses is undefined in this statement D:\DATA\IAR_AVR\DatMSL\DatMSL_main.c 54

Ему не нравится такое выражение:
Цитата
adc_res = ((ADCH<<8)+ADCL);

Можно так:
Код
adc_res = ADC;





smk
Цитата(_Артём_ @ Feb 1 2012, 20:31) *
Что-то памяти ему мало. Попробуйте уменьшить массив на 0x26 байт или упростите программу (только чтобы посмотреть откомпилируется ли и куда положит)


Ему не нравится такое выражение:

Можно так:
Код
adc_res = ADC;

Попробовал, получилось. Спасибо.

По части памяти я очень удивлен. GCC откомпилировал в 936 байт, а на ИАР как раз перетягиваю т.к. нужно кое-чего добавить, а у ИАР говорят код компактней. Может привести код целиком?
_Артём_
Цитата(smk @ Feb 1 2012, 20:45) *
Попробовал, получилось. Спасибо.

По части памяти я очень удивлен. GCC откомпилировал в 936 байт, а на ИАР как раз перетягиваю т.к. нужно кое-чего добавить, а у ИАР говорят код компактней. Может привести код целиком?


Может и привести...

Цитата(smk @ Feb 1 2012, 20:45) *
По части памяти я очень удивлен. GCC откомпилировал в 936 байт, а на ИАР как раз перетягиваю т.к. нужно кое-чего добавить, а у ИАР говорят код компактней. Может привести код целиком?


Какая оптимизация установлена?
smk
Оптимизация максимальная по размеру.

Код
#include <ioavr.h>
#include <intrinsics.h>


#include <stdio.h>

#define sig_off PORTB &= ~(1<<2)//âêë êîíòðîëüíûé ñâåòîäèîä
#define sig_on PORTB |= (1<<2)  //âûêë êîíòðîëüíûé ñâåòîäèîä
#define sensibility  120//50            //÷óâñòâèòåëüíîñòü
//#define div_on_off 200//200 ñêîðîñòü ïëàâíîãî çàæèãàíèÿ/ãàøåíèÿ
//#define set_time 2 //ïàóçà ïåðåä ãàøåíèåì â ñåêóíäàõ

__flash const unsigned char brightness[256] = //òàáëè÷êà âèçóàëüíî ðàâíîìåðíî íàðàùèâàþùàÿ ÿðêîñòü
{0,0,0,1,1,2,2,3,3,4,4,4,5,5,6,6,6,7,7,8,8,8,9,9,10,10,10,11,11,12,12,
12,12,13,13,13,13,13,14,14,14,14,15,15,15,16,16,16,16,17,17,17,18,18,
18,19,19,19,19,20,20,20,21,21,21,22,22,22,22,23,23,23,24,24,24,25,25,
25,25,26,26,26,27,27,27,28,28,28,28,29,29,30,30,31,31,32,32,33,34,34,
35,35,36,37,38,38,39,40,41,41,42,43,44,44,45,46,47,48,48,49,50,51,52,
52,53,54,55,56,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,74,
75,76,77,78,79,80,82,83,84,86,87,88,89,91,92,94,95,97,99,101,102,104,
106,107,109,111,113,114,116,118,120,122,123,125,127,129,131,134,136,
138,140,142,145,147,149,151,153,156,158,160,162,164,167,169,171,173,
175,177,179,182,184,186,188,190,192,193,195,197,198,200,202,203,205,
206,208,210,211,213,215,217,218,220,222,223,225,226,228,229,231,232,
233,235,236,237,239,240,241,242,243,244,245,246,247,249,250,251,252,
253,254,255};

volatile unsigned int adc_data;//íàïðÿæåíèå íà âûõîäå ÈÊ äàò÷èêà òåêóùåå
volatile unsigned int _adc_data;//íàïðÿæåíèå íà âûõîäå ÈÊ äàò÷èêà ïðåäèäóùåå
volatile unsigned int tick_count,dev_pwm;//äåëèòåëü ÷àñòîòû ØÈÌ
volatile unsigned char status_flag,delta,pwm,my_time,count_pwm,detect;//ñêîðîñòü èçìåíåíèÿ (îòñ÷åòîâ ÀÖÌ / 50 ìñ)
volatile unsigned char div_on_on, div_on_off, set_time;

unsigned int read_adc (void)
{
ADCSRA |= (1<<6);
while (!(ADCSRA & (1<<4)));
return ADC;
}


#pragma vector=TIM0_OVF_vect
__interrupt static void timer0_ovf_isr( void )//26087 hz
    {
    TCNT0 = 0xD2; //set count
    if(dev_pwm==700)//700
        {
            dev_pwm=0;
            TCCR0B = 0x00; //stop timer
            adc_data=read_adc();
            if(adc_data>=_adc_data) delta=adc_data - _adc_data;//âû÷èñëÿåì èçìåíåíèå çà âðåìÿ îò ïðåäèäóùåãî ïðåðûâàíèÿ îò òàéìåðà
            else delta=_adc_data - adc_data;
            _adc_data = adc_data;//çàïîìèíàåì òåêóùåå çíà÷åíèå ñèãíàëà îò ÈÊ äàò÷èêà
            if(delta>sensibility)
                {
                    detect=255;
                    status_flag=1;
                }
            else {detect=0;}
            TCCR0B = 0x02; //start timer
        }
    if((pwm>(brightness[count_pwm]))|(pwm==0)){sig_off;}
    else {sig_on;}
    ++dev_pwm;
    ++pwm;
    ++tick_count;
    }


void main(void)
{
ADMUX=0x43; //0b01000011;
ADCSRA=0x86; //0b10000110;
PORTB=0x10; //0b00010000;
DDRB=0x04; //0b00000100;
TCNT0 = 0xD2; //set count
TCCR0A = 0x00;
TCCR0B = 0x02; //start timer
TIMSK0 = 0x02; //timer interrupt sources
if(PINB & (1<<4)) //PB4==1?
    {//ðåçèñòîð îòïàÿí
    div_on_on=10;
    div_on_off=10;
    set_time=1;
    }
else
    {//ðåçèñòîð ïðèïàÿí
    div_on_on=200;
    div_on_off=200;
    set_time=60;    
    }
__enable_interrupt();

while(1)
    {
    if(status_flag==0)
    {
        tick_count=0;
    }
    if(status_flag==1)
        {
            for(;;)    
            {
            if(tick_count==div_on_on)
                {
                if(count_pwm==255)
                    {
                        count_pwm=255;
                        status_flag=2;
                        tick_count=0;
                        break;
                    }
                    tick_count=0;
                    ++count_pwm;
                }    
            }    
        }
    if(status_flag==2)
        {
            for(;;)
            {
            if(tick_count==26087)
                {
                if(my_time==set_time)
                    {
                        tick_count=0;
                        my_time=0;
                        status_flag=3;
                        break;
                    }
                    tick_count=0;
                    ++my_time;
                }
            if(detect==255)
                {
                    my_time=0;
                }    
            }
        }
    if(status_flag==3)    
        {
            for(;;)
            {
            if(tick_count==div_on_off)
                {
                if(count_pwm==0)
                    {
                        tick_count=0;
                        count_pwm=0;
                        status_flag=0;
                        break;
                    }
                tick_count=0;
                --count_pwm;
                }
            if(detect==255)
                {
                    status_flag=1;
                    break;
                }
            }
        }

    }
//return 0;
}
Сергей Борщ
QUOTE (smk @ Feb 1 2012, 21:22) *
Оптимизация максимальная по размеру.
Попробуйте максимальную по скорости. Когда то она давала и меньший код, чем оптимизация по размеру. Ну и там есть еще несколько дополнительных галочек, с которыми стоит поиграться. А вообще вам надо радикально пересмотреть использование volatile-переменных, оставив квалификатор лишь у тех переменных, к которым есть обращения И в прерываниях И в основном цикле. А с оставшимися volatile работать по принципу "считал во временную локальную переменную, поработал с локальной, выгрузил результат в volatile". Уверен, что таким нехитрым способом можно выиграть больше, чем от смены компилятора.
_Артём_
Цитата(smk @ Feb 1 2012, 21:22) *
Оптимизация максимальная по размеру.


Попробовал откомпилировать с максимальной оптимизацией: 790 байт code/ 63 RAM.
IAR сначала жаловался на нехватку ОЗУ, уменьшил стеки - собралось.

P.S. У вас зачем все глобальные переменные volatile? Некоторые из них (dev_pwm, delta, my_time и может ещё какие-нибудь) используются исключительно в единственном прерываниии: volatile не нужен. Может аналогичная ситуция с основной программой, не смотрел.
P.S.2 Просьба: если скомпилится и заработает выложите полученные размеры для IAR и GCC. Интересно кто кого.
smk
Уменьшил CSTACK до 0x0f и тоже собралось. Получилось 844/64. Есть еще пара вопросов перед тем как делать все остальное. ИАР выдает несколько предупреждений и хочется от них избавиться. Все предупреждения вида:
Код
Warning[Pa082]: undefined behavior: the order of volatile accesses is undefined in this statement D:\DATA\IAR_AVR\DatMSL\DatMSL_main.c 46

В строчках

Код
if(adc_data>=_adc_data) delta=adc_data - _adc_data;

else delta=_adc_data - adc_data;

if((pwm>(brightness[count_pwm]))|(pwm==0)){sig_off;}

if(tick_count==div_on_on)

if(my_time==set_time)

if(tick_count==div_on_off)


Пока наилучший результат 770/64.
Сергей Борщ
QUOTE (smk @ Feb 2 2012, 09:42) *
ИАР выдает несколько предупреждений
Правильно выдает. Чтение volatile может приводить к изменению ее содержимого (вспомните регистр UDR или подобные) и содержимого других volatile-переменых (при чтении ADCH обновляется ADCL). В вычислении результата ваших выражений используются минимум две volatile-переменные. Компилятор предупреждает, что поскольку порядок вычисления выражений не определен, то и результат вычислений может быть не таким, как вы ожидаете. У вас есть два варианта решения:
1) Избавиться от лишних volatile и тогда большинство выражений будет содержать максимум одну volatile-переменную.
2) В оставшихся выражениях вместо "лишних" volatile-переменных использовать временные локальные переменные, в которые заранее считано значение из volatile:
CODE
uint16_t ADC_result;
{
    uint8_t Tmp = ADCL;
    ADC_result = (ADCH << 8) | Tmp;
}

Ну или не делать п.1 а везде применять п.2, но это тупиковое решение и сокращения кода вы так не получите.

Исправил - попутаны были ADCH и ADCL
smk
Сделал везде по 1 варианту. Это пока дало наилучший результат. Посмотрим что будет в железе.
Сергей Борщ
QUOTE (smk @ Feb 2 2012, 11:52) *
Сделал везде по 1 варианту.
Не забудьте сообщить, какой в итоге получится размер кода и какой размер того же исходника даст gcc.
smk
По последним данным GCC 936 байт, а IAR 770 байт, но hex от IAR в железо еще не лил и не тестировал что вышло с потребительской стороны.
smk
Самый лучший результат составил 750 байт. В железе все заработало правильно.
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.