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

 
 
10 страниц V  « < 5 6 7 8 9 > »   
Reply to this topicStart new topic
> Перенос кода из под ИАРа на WinAVR, возникают некоторые вопросы...
sonycman
сообщение Nov 30 2008, 11:57
Сообщение #91


Любитель
*****

Группа: Свой
Сообщений: 1 864
Регистрация: 20-08-06
Из: Тольятти
Пользователь №: 19 695



Цитата(Rst7 @ Nov 30 2008, 15:09) *
218 bytes in segment CODE

Круто!
Чуть погодя попробую.
Изначально (в IAR) для флагов ошибок действительно использовались битовые поля, но после того, как я взглянул, что вытворяет с ними гнусь - убрал поскорее 07.gif
Чуть погодя обязательно попробую и отпишусь о результатах smile.gif
Go to the top of the page
 
+Quote Post
alx2
сообщение Nov 30 2008, 13:13
Сообщение #92


Местный
***

Группа: Участник
Сообщений: 340
Регистрация: 25-10-05
Из: Пермь, Россия
Пользователь №: 10 091



Привет, Rst7!
Цитата(Rst7 @ Nov 29 2008, 17:53) *
Да ну? Рассмотрим операцию сложения. Независимо от размера - char или int - половина возможных операндов (немного меньше, без 2n, где n - количество разрядов) приведет к переполнению. А значит - вероятность почти 50% и не зависит от размерности smile.gif
Честно говоря, я ничего не понял. smile.gif Я ведь говорю не о теоретической математике, а о сугубо прикладной. Математические величины, над которыми производятся вычисления в программе, как правило, отражают реальные сущности окружающего мира. Поэтому значения этих величин первичны по отношению к программе. Исходя из них программист выбирает, в частности, разрядность, необходимую для проведения вычислений. Я имел в виду, что для представления некой величины 8-ми бит может оказаться недостаточно с большей вероятностью, чем 16, и, тем более, 32-х. К примеру, количество людей, прошедших через турникет за час - оно вполне может измеряться несколькими сотнями. А вот превысить 65 тысяч, я думаю, не сможет. smile.gif


--------------------
Всего наилучшего,
Alex Mogilnikov
Go to the top of the page
 
+Quote Post
sonycman
сообщение Nov 30 2008, 13:22
Сообщение #93


Любитель
*****

Группа: Свой
Сообщений: 1 864
Регистрация: 20-08-06
Из: Тольятти
Пользователь №: 19 695



RST7
Не получается у меня научить гнуса правильно обращаться с битовым полем.
Даже с Вашей помощью... crying.gif
Вот что получилось:
Код
typedef struct
{
    byte    frame_err: 1, ovrun_err: 1, parity_err: 1, length_err: 1, lock_err: 1, chksum_err: 1, unknown_command: 1;
} USART_ERROR;

struct    usart_rx_status
{
    byte    counter;
    byte    mode;
    volatile bool data_available;
    USART_ERROR    error;
};

ISR(USART_RX_vect)
{
    static    byte    sign[] PROGMEM =    {'S','N'};
    static    byte    length;
    byte    data, state;
    USART_ERROR error;
    error    =    statusRx.error;

    do
    {
        state    =    UCSR0A;
        data    =    UDR0;
        if (statusRx.data_available)
            {
                error.lock_err    =    TRUE;
                continue;
            }
        if (state & ((1<<FE0)|(1<<DOR0)|(1<<UPE0)))
        {
            if (state & (1<<FE0)) error.frame_err    =    TRUE;
            if (state & (1<<DOR0)) error.ovrun_err    =    TRUE;
            if (state & (1<<UPE0)) error.parity_err    =    TRUE;
            statusRx.mode    =    RX_SEEK;
            statusRx.counter    =    0;
            continue;
        }
        else
        {
            error.frame_err    =    0;
            error.ovrun_err    =    0;
            error.parity_err    =    0;
            error.length_err    =    0;
            error.lock_err    =    0;
            error.chksum_err    =    0;
        }
        switch(statusRx.mode)
        {
        case    RX_SEEK:
            if (statusRx.counter < sizeof(sign))
            {
                if (data == pgm_read_byte(sign[statusRx.counter]))
                {
                    statusRx.counter++;
                }
                else
                {
                    statusRx.counter    =    0;
                }
            }
            else
            {
                statusRx.counter    =    0;
                if (data    >= sizeof(rx_buffer) || data == 0)
                {
                    error.length_err    =    TRUE;
                    break;
                }
                rx_buffer[statusRx.counter++]    =    data;
                length    =    ++data;
                statusRx.mode    =    RX_RUNNING;
            }
            break;
        case    RX_RUNNING:
            rx_buffer[statusRx.counter++]    =    data;
            length--;
            if (!length)
            {
                statusRx.data_available    =    TRUE;
                statusRx.mode    =    RX_SEEK;
                statusRx.counter    =    0;
            }
            break;
        }

    }while(UCSR0A & (1<<RXC0));
    statusRx.error    =    error;
}

и результат компиляции первой строчки:
Код
    error    =    statusRx.error;
     b38:    80 91 ae 01     lds    r24, 0x01AE
     b3c:    58 2f           mov    r21, r24
     b3e:    52 95           swap    r21
     b40:    51 70           andi    r21, 0x01; 1
     b42:    b8 2f           mov    r27, r24
     b44:    b1 70           andi    r27, 0x01; 1
     b46:    68 2f           mov    r22, r24
     b48:    66 95           lsr    r22
     b4a:    61 70           andi    r22, 0x01; 1
     b4c:    78 2f           mov    r23, r24
     b4e:    76 95           lsr    r23
     b50:    76 95           lsr    r23
     b52:    71 70           andi    r23, 0x01; 1
     b54:    f8 2f           mov    r31, r24
     b56:    f6 95           lsr    r31
     b58:    f6 95           lsr    r31
     b5a:    f6 95           lsr    r31
     b5c:    f1 70           andi    r31, 0x01; 1
     b5e:    e8 2f           mov    r30, r24
     b60:    e2 95           swap    r30
     b62:    e6 95           lsr    r30
     b64:    e1 70           andi    r30, 0x01; 1
     b66:    08 2f           mov    r16, r24
     b68:    02 95           swap    r16
     b6a:    06 95           lsr    r16
     b6c:    06 95           lsr    r16
     b6e:    01 70           andi    r16, 0x01; 1

дальше в коде в основном всё осталось по-прежнему...
laughing.gif
Go to the top of the page
 
+Quote Post
alx2
сообщение Nov 30 2008, 13:41
Сообщение #94


Местный
***

Группа: Участник
Сообщений: 340
Регистрация: 25-10-05
Из: Пермь, Россия
Пользователь №: 10 091



Цитата(sonycman @ Nov 30 2008, 02:02) *
Зачем часто писать явное приведение к int? Разумнее сразу иметь хотя-бы одну переменную размерности int, если обработка данных типа char приводит к образованию переполнения smile.gif
Это можно. Но тогда в памяти будут храниться незначащие байты.
Цитата(sonycman @ Nov 30 2008, 02:02) *
Ты говоришь про общий случай. Я - про строку кода конкретной функции lcdPrintText, в которой делимое всегда лежит в пределах 0 <= d < 96. Поэтому эти выражения совершенно эквивалентны.
Я говорил о правилах языка, а они пишутся именно для общего случая. Я вполне допускаю, что изменение правил дало бы для данной конкретной программы выигрыш в объеме. Вопрос в том, стоит ли этот выигрыш потери совместимости. В конце концов, если уж так хочется, можно ИМХО создать свой класс mychar, и определить для него такую математику, какую хочется. В том числе приведение к char каждого промежуточного результата. И другой язык для этого придумывать не обязательно. smile.gif


--------------------
Всего наилучшего,
Alex Mogilnikov
Go to the top of the page
 
+Quote Post
Rst7
сообщение Nov 30 2008, 13:46
Сообщение #95


Йа моск ;)
******

Группа: Модераторы
Сообщений: 4 345
Регистрация: 7-07-05
Из: Kharkiv-city
Пользователь №: 6 610



Цитата
и результат компиляции первой строчки:


Жесть. Все биты превратил в char'ы и разложил в регистрах. В конце функции, кстати, должен был собрать вместе smile.gif

Выбросьте Вы, наверное, нафиг эту опенсорсную какашку.

Потому как на данном этапе получить из него более лучший чем у IAR'а код не получается. И врядли когда-либо в обозримом будущем получится. Даже с учетом того, что у IAR'а иногда наблюдаются психозы с указателями.

А в общем, я бы рекомнедовал купить IAR и клевать мозг его разработчикам. Потому как тогда будут заплачены денежки и есть за что бороться. Сам я в ближайшее время собираюсь по этому пути пойти.

А с гнусем - Вы же сами видите, любая просьба (даже о рассмотрении серьезного бага в оптимизаторе) посылается куда подальше - ведь "никто никому не должен". Аргумент о том, что багов и пожеланий больше чем времени, не принимается - нет времени пилить напильником гнуся - не надо за него вообще браться. Как там, в StarWars - "не надо пытаться, делай - или не делай" smile.gif

Пардон, если зацепил кого. Ничего личного, просто констатация факта.


--------------------
"Практика выше (теоретического) познания, ибо она имеет не только достоинство всеобщности, но и непосредственной действительности." - В.И. Ленин
Go to the top of the page
 
+Quote Post
alx2
сообщение Nov 30 2008, 13:57
Сообщение #96


Местный
***

Группа: Участник
Сообщений: 340
Регистрация: 25-10-05
Из: Пермь, Россия
Пользователь №: 10 091



Цитата(sonycman @ Nov 30 2008, 02:56) *
Имеем текст:
Код
typedef    unsigned char    byte;
byte percent;
byte    maxRPM;
byte    minRPM;

percent = (maxRPM - minRPM) / 2;

и результат:
Код
            percent = (maxRPM - minRPM) / 2;
     6c0:    80 85           ldd    r24, Z+8; 0x08
     6c2:    90 e0           ldi    r25, 0x00; 0
     6c4:    21 85           ldd    r18, Z+9; 0x09
     6c6:    82 1b           sub    r24, r18
     6c8:    91 09           sbc    r25, r1
     6ca:    62 e0           ldi    r22, 0x02; 2
     6cc:    70 e0           ldi    r23, 0x00; 0
     6ce:    ee d8           rcall    .-3620; 0xfffff8ac <__eeprom_end+0xff7ef884>

Здесь вроде нет знаковых переменных, и нет сложения. Почему не сработала оптимизация?
Что именно тут можно было сделать более оптимально?

Цитата(sonycman @ Nov 30 2008, 02:56) *
Также есть проблемы с утилитой создания листинга avr-objdump - как видно, неправильно вычисляется адрес подпрограммы деления...

А зачем вообще в данном случае использовать дизассемблирование? Почему не смотреть сразу вывод компилятора? Там хотя бы все имена символов на своих местах:
Код
        lds r24,maxRPM
        ldi r25,lo8(0)
        lds r18,minRPM
        sub r24,r18
        sbc r25,__zero_reg__
        ldi r22,lo8(2)
        ldi r23,hi8(2)
        rcall __divmodhi4
        sts percent,r22
        ret
А узнать адрес функции удобнее из map-файла...
Цитата(sonycman @ Nov 30 2008, 02:56) *
Так это как раз не компилятор, это просто библиотечные макросы. Аналогичные макросы можно сделать для любого минимально вменяемого компилятора.

Но разве есть подобные макросы для IAR? Там ведь приходится пользоваться громоздкой конструкцией с pragma и примитивными __disable_interrupt() и __enable_interrupt()...
Не знаю, я IAR'ом никогда не пользовался. Даже если нет, что мешает написать? Вот в GCC тоже нет таких макросов - так сделали же...

Сообщение отредактировал alx2 - Nov 30 2008, 14:50


--------------------
Всего наилучшего,
Alex Mogilnikov
Go to the top of the page
 
+Quote Post
sonycman
сообщение Nov 30 2008, 14:19
Сообщение #97


Любитель
*****

Группа: Свой
Сообщений: 1 864
Регистрация: 20-08-06
Из: Тольятти
Пользователь №: 19 695



Цитата(Rst7 @ Nov 30 2008, 17:46) *
Жесть. Все биты превратил в char'ы и разложил в регистрах. В конце функции, кстати, должен был собрать вместе smile.gif
Выбросьте Вы, наверное, нафиг эту опенсорсную какашку.

Наверное, так и придётся поступить в конце концов. Но почему-то жаль... crying.gif

Цитата(alx2 @ Nov 30 2008, 17:41) *
В конце концов, если уж так хочется, можно ИМХО создать свой класс mychar, и определить для него такую математику, какую хочется.

А вот это очень интересно! Надо будет попробовать на досуге! smile.gif

Цитата(alx2 @ Nov 30 2008, 17:57) *
А зачем вообще в данном случае использовать дизассемблирование? Почему не смотреть сразу вывод компилятора? Там хотя бы все имена символов на своих местах:

А как помотреть? Я в эклипсе не вижу больше никаких файлов после компиляции, кроме .lss 07.gif

Цитата
Даже если нет, что мешает написать?

Мне самому просто знаний не хватит написать "извращение", подобное ATOMIC_BLOCK().
По крайней мере, на данных порах.
Go to the top of the page
 
+Quote Post
alx2
сообщение Nov 30 2008, 14:21
Сообщение #98


Местный
***

Группа: Участник
Сообщений: 340
Регистрация: 25-10-05
Из: Пермь, Россия
Пользователь №: 10 091



Цитата(sonycman @ Nov 30 2008, 04:14) *
В ИАРе очень удобно сделана работа с указателями на память программ и eeprom. Она совершенно не отличается от указателей на оперативку a14.gif
Хотелось бы видеть такое когда-нибудь и в GCC.
Можно в двух словах, как это сделано в IAR? Предполагаю, что там сделаны "универсальные указатели", которые включают не только адрес, но и идентификатор адресного пространства (код/данные). Кстати, опять же, IMHO ничто не мешает определить какой-нибудь класс u_pointer, хранящий такой указатель, и все необходимые для него операции. И не надо ждать, когда авторы компилятора что-то там сделают...


--------------------
Всего наилучшего,
Alex Mogilnikov
Go to the top of the page
 
+Quote Post
sonycman
сообщение Nov 30 2008, 14:34
Сообщение #99


Любитель
*****

Группа: Свой
Сообщений: 1 864
Регистрация: 20-08-06
Из: Тольятти
Пользователь №: 19 695



Цитата(alx2 @ Nov 30 2008, 18:21) *
Можно в двух словах, как это сделано в IAR? Предполагаю, что там сделаны "универсальные указатели", которые включают не только адрес, но и идентификатор адресного пространства (код/данные). Кстати, опять же, IMHO ничто не мешает определить какой-нибудь класс u_pointer, хранящий такой указатель, и все необходимые для него операции. И не надо ждать, когда авторы компилятора что-то там сделают...

Я без понятия, как там это сделано. Но выглядит вот так:
Код
__no_init __eeprom byte    ds1820romcodes[4][10]    @ 0x0;
static     unsigned char    ds18rom[4][10];

void    ds18Init(void)
{
    for(byte    a=0;a<40;a++)
    {
        ds18rom[0][a]    =    ds1820romcodes[0][a];
    }
}

Также и с обращением на чтение памяти программ:
Код
lcdPrintText("CPU");

void  lcdPrintText(char const __flash __flash *text)
{
  while(*text) lcdPutChar(*text++);
}

laughing.gif
Go to the top of the page
 
+Quote Post
alx2
сообщение Nov 30 2008, 14:40
Сообщение #100


Местный
***

Группа: Участник
Сообщений: 340
Регистрация: 25-10-05
Из: Пермь, Россия
Пользователь №: 10 091



Цитата(sonycman @ Nov 30 2008, 03:24) *
А вот доводить до ума оптимизацию, думаю, нужно. В частности, по обработке switch?
Можно немного подсказать gcc, поместив промежуточный результат во временную переменную:
Код
void do_something();
void do_something_else();
void fff(char flags)
{
    char tmp = flags & 0xe0;
    switch(tmp)
    {
        case 0x40:
            do_something();
            break;
        case 0x80:
            do_something_else();
    }
}

Результат компиляции:
Код
_Z3fffc:
        andi r24,lo8(-32)
        cpi r24,lo8(64)
        breq .L3
        cpi r24,lo8(-128)
        brne .L5
        rjmp .L6
.L3:
        rcall _Z12do_somethingv
        ret
.L6:
        rcall _Z17do_something_elsev
.L5:
        ret


--------------------
Всего наилучшего,
Alex Mogilnikov
Go to the top of the page
 
+Quote Post
Rst7
сообщение Nov 30 2008, 14:47
Сообщение #101


Йа моск ;)
******

Группа: Модераторы
Сообщений: 4 345
Регистрация: 7-07-05
Из: Kharkiv-city
Пользователь №: 6 610



Цитата
Наверное, так и придётся поступить в конце концов. Но почему-то жаль...


Я где-то с регулярностью в полгода посматриваю, что происходит на гнусевом фронте. Пробую собирать какие-то куски своего кода и каждый раз убеждаюсь, что качество кодогенерации прилично уступает IAR'у. Ну уступает и уступает. Хрен с ним.

Однако последние версии гнуся просто убили (что WinAVR последний, что сборка klen'а) - это я про полный бред, который он делает из do{*src++=*dst++;}while(--l); если l имеет тип unsigned char. Вот на исследовании этого бага я и настаиваю.


--------------------
"Практика выше (теоретического) познания, ибо она имеет не только достоинство всеобщности, но и непосредственной действительности." - В.И. Ленин
Go to the top of the page
 
+Quote Post
AHTOXA
сообщение Nov 30 2008, 14:58
Сообщение #102


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

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



Насчёт битовых полей. Можно опять же помочь компилятору.
CODE
typedef unsigned char byte;
typedef union
{
byte error;
struct
{
byte frame_err: 1,
ovrun_err: 1,
parity_err: 1,
length_err: 1,
lock_err: 1,
chksum_err: 1,
unknown_command: 1;
}flags;
} USART_ERROR;

struct usart_rx_status
{
byte counter;
byte mode;
volatile unsigned char data_available;
USART_ERROR error;
};

struct usart_rx_status statusRx;
byte rx_buffer[22];

#define RX_SEEK 1
#define RX_RUNNING 2

SIGNAL(SIG_USART0_RECV)
{
static byte sign[] PROGMEM = {'S','N'};
static byte length;
byte data, state;
USART_ERROR error;
error.error = statusRx.error.error;

do
{
state = UCSR0A;
data = UDR0;
if (statusRx.data_available)
{
error.flags.lock_err = TRUE;
continue;
}
if (state & ((1<<FE0)|(1<<DOR0)|(1<<UPE0)))
{
if (state & (1<<FE0)) error.flags.frame_err = TRUE;
if (state & (1<<DOR0)) error.flags.ovrun_err = TRUE;
if (state & (1<<UPE0)) error.flags.parity_err = TRUE;
statusRx.mode = RX_SEEK;
statusRx.counter = 0;
continue;
}
else
{
error.error = 0;
}
switch(statusRx.mode)
{
case RX_SEEK:
if (statusRx.counter < sizeof(sign))
{
if (data == pgm_read_byte(sign[statusRx.counter]))
{
statusRx.counter++;
}
else
{
statusRx.counter = 0;
}
}
else
{
statusRx.counter = 0;
if (data >= sizeof(rx_buffer) || data == 0)
{
error.flags.length_err = TRUE;
break;
}
rx_buffer[statusRx.counter++] = data;
length = ++data;
statusRx.mode = RX_RUNNING;
}
break;
case RX_RUNNING:
rx_buffer[statusRx.counter++] = data;
length--;
if (!length)
{
statusRx.data_available = TRUE;
statusRx.mode = RX_SEEK;
statusRx.counter = 0;
}
break;
}

}while(UCSR0A & (1<<RXC0));
statusRx.error = error;
}


И получается:
Код
function __vector_18 size 125 (93)

Это для winavr 20071221


--------------------
Если бы я знал, что такое электричество...
Go to the top of the page
 
+Quote Post
alx2
сообщение Nov 30 2008, 15:26
Сообщение #103


Местный
***

Группа: Участник
Сообщений: 340
Регистрация: 25-10-05
Из: Пермь, Россия
Пользователь №: 10 091



Цитата(sonycman @ Nov 30 2008, 19:19) *
А как помотреть? Я в эклипсе не вижу больше никаких файлов после компиляции, кроме .lss 07.gif
gcc -S предписывает не выполнять ассемблирование. Результат компиляции будет записан в файл с расширением s (если явно не указано иное).
Цитата(sonycman @ Nov 30 2008, 19:19) *
Мне самому просто знаний не хватит написать "извращение", подобное ATOMIC_BLOCK().
По крайней мере, на данных порах.
Тем интереснее будет посмотреть, как это сделано например в avrlibc (именно там я эти макросы нашел). В простейшем случае это дает инструкцию cli при входе в блок и sei при выходе.

Кстати, я бы не рекомендовал использовать for() для обрамления критических блоков. Дело в том, что если внутри такого блока встретится return или будет выброшено исключение, третье выражение for() выполнено не будет, и прерывания так и останутся запрещены. Лучше сделать специальный класс, в конструкторе и деструкторе которого запрещать и разрешать прерывания соответственно. В этом случае будет гарантия, что деструктор выполнится при любом выходе из блока...

Цитата(Rst7 @ Nov 30 2008, 19:47) *
...полный бред, который он делает из do{*src++=*dst++;}while(--l); если l имеет тип unsigned char.
В последних - это в каких? Имеющийся у меня gcc-4.3.1 сгенерил вот это:
Код
.L2:
        ld r24,Z+
        st X+,r24
        subi r20,lo8(-(-1))
        brne .L2
Я этот код бредовым не нахожу...


--------------------
Всего наилучшего,
Alex Mogilnikov
Go to the top of the page
 
+Quote Post
Rst7
сообщение Nov 30 2008, 15:37
Сообщение #104


Йа моск ;)
******

Группа: Модераторы
Сообщений: 4 345
Регистрация: 7-07-05
Из: Kharkiv-city
Пользователь №: 6 610



Цитата
Насчёт битовых полей. Можно опять же помочь компилятору.


Это не помощь. А объезд кривого оптимизатора. По науке сам должен был структуру скопировать, а не по полям разносить.

ЗЫ Приведите, чтоли, получившийся код, глянем...

Цитата
В последних - это в каких?


Я же написал в каких. Вот собственно тут можно почитать - http://electronix.ru/forum/index.php?s=&am...st&p=499837

Тут меня постарались убедить, что все хорошо - http://electronix.ru/forum/index.php?s=&am...st&p=501677

Однако тоже оказалось не очень хорошо, если почитать дальше.


--------------------
"Практика выше (теоретического) познания, ибо она имеет не только достоинство всеобщности, но и непосредственной действительности." - В.И. Ленин
Go to the top of the page
 
+Quote Post
sonycman
сообщение Nov 30 2008, 15:38
Сообщение #105


Любитель
*****

Группа: Свой
Сообщений: 1 864
Регистрация: 20-08-06
Из: Тольятти
Пользователь №: 19 695



Цитата(alx2 @ Nov 30 2008, 19:26) *
gcc -S предписывает не выполнять ассемблирование. Результат компиляции будет записан в файл с расширением s (если явно не указано иное).

Спасибо smile.gif
Цитата
Кстати, я бы не рекомендовал использовать for() для обрамления критических блоков. Дело в том, что если внутри такого блока встретится return или будет выброшено исключение, третье выражение for() выполнено не будет, и прерывания так и останутся запрещены. Лучше сделать специальный класс, в конструкторе и деструкторе которого запрещать и разрешать прерывания соответственно.

Но ведь ATOMIC_BLOCK() именно так и сделан?
Go to the top of the page
 
+Quote Post

10 страниц V  « < 5 6 7 8 9 > » 
Reply to this topicStart new topic
5 чел. читают эту тему (гостей: 5, скрытых пользователей: 0)
Пользователей: 0

 


RSS Текстовая версия Сейчас: 21st July 2025 - 06:57
Рейтинг@Mail.ru


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