Перейти к содержанию
    

Перенос кода из под ИАРа на WinAVR

Сейчас пытаюсь подогнать ИАРовский проект на меге88 под ВинАВР 4.3.2.

Чувствую, помучаться придётся немало :smile3046:

 

Пока не могу разобраться, как красиво прочитать/записать 16-ти битный таймер, обеспечив атомарность операции.

Аналога иаровского __monitor не нашёл.

Существуют ли подобные макросы? Или надо писать самому?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Поможет WinAVR\avr\include\util\atomic.h

Уря, разобрался! :a14:

С меня :beer:

 

Я то пытался накропать код и заюзать что-то типа cli() и sei() своими корявенькими ручонками, а тут уже готовое решение, такое компактное и мощное одновременно!

Разрабы туда, наверное, тонну хитрости запихали! Учитывать все выходы из секции для восстановления прерываний... бла, как они это осуществили?

 

Всё, пошёл спать. С утра буду невыспавшийся - зато довольный :laughing:

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Насколько я помню, у WinAVR имеется отличная документация, включающая в том числе раздел "Porting Code From IAR"

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Насколько я помню, у WinAVR имеется отличная документация, включающая в том числе раздел "Porting Code From IAR"

Спасибо, теперь всё понятно и с прерываниями :biggrin:

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Насколько я помню, у WinAVR имеется отличная документация, включающая в том числе раздел "Porting Code From IAR"

А может кто подскажет, где поискать документацию по AVR GCC в виде PDF?

А то не очень удобно пользоваться html версией... :07:

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

А может кто подскажет, где поискать документацию по AVR GCC в виде PDF?

А то не очень удобно пользоваться html версией... :07:

как правило, она находится в папке WinAVR\doc\avr-libc - я ведь верно понял, что интересует документация на avr-libc?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Разрабы туда, наверное, тонну хитрости запихали! Учитывать все выходы из секции для восстановления прерываний... бла, как они это осуществили?
У gcc есть довольно мощная штука - атрибуты. Куча разных.

Например, атрибутом можно сказать, что результат, возвращаемый данной функцией, зависит только от передаваемых ей параметров и она сама вовне ничего не меняет, т.е. не имеет "побочных эффектов".

Вся математика типа sqrt() такая.

Тогда если её вызывать с одними и теми же неизменными аргументами (константами либо переменными, про которые компилятор знает, что они не менялись) несколько раз - компилятор вызовет одитн раз, запомнит значение и подставит где нужно сам.

 

Для переменных можно задать аттрибутами функции создания и очистки, при создании переменной будет вызвана одна функция, при уничтожении (при выходе из окружающего её блока { } ) - другая. Это что-то типа конструкторов-деструкторов в C++. Вот они и спрятали в макросах переменную, при создании которой в неё копируется SREG и прерывания запрещаются/разрешаются, в зависимости от типа блока, а при удалении она переписывается назад в SREG, таким образом состояние прерываний восстанавливается.

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

ATOMIC_BLOCK(ATOMIC_RESTORESTATE)
{
   ...
}

А не

{
    ATOMIC_BLOCK(ATOMIC_RESTORESTATE);
   ...
}

макросы оформили в виде заголовка цикла for(;;) - переменная, которая объявлена в заголовке (for( unsigned char u; ...; ... ) ) имеет время жизни в пределах цикла, создаётся до первого входа в тело и уничтожается после выхода из цикла.

 

Очень симпатично сделано... Учтено всё.

 

Вот тут ещё на эту тему было, только "наоборот" - нужно на время разрешить прерывания:

http://electronix.ru/forum/index.php?showt...mp;#entry487831

в примере макрос из atomic.h и С++ класс дали при компиляции тождественный код.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

как правило, она находится в папке WinAVR\doc\avr-libc - я ведь верно понял, что интересует документация на avr-libc?

Нет, на библиотеку как раз pdf есть. Мне бы на компилятор, со всеми его ключевыми словами, аттрибутами и т.д...

Она там только в формате html... в принципе, сойдёт, если нет лучшего :)

 

Очень симпатично сделано... Учтено всё.

Спасибо за разъяснение, стало понятнее!

Сам только недавно начал осваивать С++, и имею небольшое представление о классах.

Очень интересная штука ;)

 

У меня возникла очередная проблема в портировании проекта IAR на WinAVR.

Есть класс таймеров:

#include    <util/atomic.h>

typedef    unsigned long    dword;
typedef    unsigned short    word;
typedef    unsigned char    byte;

extern volatile    word    tcounter;       //hardware timer

class    CTimer    {
private:
    word    interval;
    word    counter;

public:
    CTimer (word timeout    =    0) {    Set(timeout);    }
    void    operator =    (word    timeout);
    void    Set (word timeout);
    bool    operator ! ();
    operator    bool ();
};

        CTimer::operator    bool()
{
    if (!interval) return TRUE;
    if ((tcounter - counter) >= interval)
    {
        interval    =    0;
        return    TRUE;
    }
    return    FALSE;
}

bool    CTimer::operator !    ()
{
    return    !operator bool();
}

void    CTimer::operator =    (word    timeout)
{
    Set(timeout);
}

void    CTimer::Set(word timeout)
{
    if (timeout)
    {
        interval    =    timeout    /    10;            //interrupts timer resolution is 10ms
        counter    =    tcounter;
    }
    else
    {
        interval    =    0;
    }
}

Этот файл компилируется нормально.

Но при компиляции таких строк:

static CTimer tmrSpinup;

то есть при создании объекта класса выдаётся ошибка: undefined reference to `__cxa_guard_release'

 

Что-то я пока что в тупике.

Описания такой функции нет в исходниках компилятора.

Что делать? Почему так получилось? :wacko:

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

У gcc есть довольно мощная штука - атрибуты. Куча разных.

....

Для переменных можно задать аттрибутами функции создания и очистки, при создании переменной будет вызвана одна функция, при уничтожении (при выходе из окружающего её блока { } ) - другая. Это что-то типа конструкторов-деструкторов в C++. Вот они и спрятали в макросах переменную, при создании которой в неё копируется SREG и прерывания запрещаются/разрешаются, в зависимости от типа блока, а при удалении она переписывается назад в SREG, таким образом состояние прерываний восстанавливается.

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

ATOMIC_BLOCK(ATOMIC_RESTORESTATE)
{
   ...
}

А не

{
    ATOMIC_BLOCK(ATOMIC_RESTORESTATE);
   ...
}

макросы оформили в виде заголовка цикла for(;;) - переменная, которая объявлена в заголовке (for( unsigned char u; ...; ... ) ) имеет время жизни в пределах цикла, создаётся до первого входа в тело и уничтожается после выхода из цикла.

 

Очень симпатично сделано... Учтено всё.

....

В принципе понятно как они сделали. но во зачем - непонятно. зачем такой хитрый выверт с непереносимыми атрибутами, когда аналогичную штуку можно проделать без них? например:

#define ATOMIC_BLOCK()   for(U8 __temp=get_SREG_and_CLI(),iter=0;iter<1;i++,SREG=__temp)

И переносимо, и без хитрых атрибутов? Может я чего-то не понял. Или есть какой-то потаёный от меня смысл?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

то есть при создании объекта класса выдаётся ошибка: undefined reference to `__cxa_guard_release'

 

Что-то я пока что в тупике.

Описания такой функции нет в исходниках компилятора.

Что делать? Почему так получилось? :wacko:

Странно. К тому коду было добавлено

static CTimer tmrSpinup;

int main()
{
    tmrSpinup.Set(10);
    while( !tmrSpinup );
    for(;;);
}

и всё собралось-слинковалось несколькими версиями от 3.4.6 (WinAVR-20060421) до 4.4.0 (Klen-20080530), более свежих нет на компе.

Это функция, похоже, должна была бы быть в libstdc++, если бы она для AVR была. Там же __cxa_pure_virtual и т.д., т.е. поддержка для более "взрослого" применения С++ с исключениями и т.д.

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

    CFLAGS += -ffunction-sections #-fdata-sections
    LDFLAGS += -Wl,--gc-sections

Это предназначено для итеративного выбрасывания кода и данных, которые никогда не вызывается/не используются.

За компанию стоит добавить

    LDFLAGS += -Wl,--relax

поиском по разделу AVR можно найти объяснения.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

В принципе понятно как они сделали. но во зачем - непонятно. зачем такой хитрый выверт с непереносимыми атрибутами, когда аналогичную штуку можно проделать без них? например:

#define ATOMIC_BLOCK()   for(U8 __temp=get_SREG_and_CLI(),iter=0;iter<1;i++,SREG=__temp)

И переносимо, и без хитрых атрибутов? Может я чего-то не понял. Или есть какой-то потаёный от меня смысл?

А если внутри блока будет break или return? Выполнится ли тогда SREG=__temp?

 

Странно. К тому коду было добавлено

static CTimer tmrSpinup;

int main()
{
    tmrSpinup.Set(10);
    while( !tmrSpinup );
    for(;;);
}

и всё собралось-слинковалось несколькими версиями от 3.4.6 (WinAVR-20060421) до 4.4.0 (Klen-20080530), более свежих нет на компе.

Есть информация, что некоторые статические объекты вызывают такую ошибку в новых версиях компилятора, так как отсутствует какая-то библиотека...

Решилось добавлением ключа -fno-threadsafe-statics

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

В принципе понятно как они сделали. но во зачем - непонятно. зачем такой хитрый выверт с непереносимыми атрибутами, когда аналогичную штуку можно проделать без них? например:
#define ATOMIC_BLOCK()   for(U8 __temp=get_SREG_and_CLI(),iter=0;iter<1;i++,SREG=__temp)

И переносимо, и без хитрых атрибутов? Может я чего-то не понял. Или есть какой-то потаёный от меня смысл?

Это НЕ аналогичная штука. По ссылке, там где я пример с классом приводил, достаточно полный пример зачем это надо (конструкторы-деструкторы, пусть даже в виде прицепленных атрибутами функций).

Может быть выход из середины блока, простой "переносимый" вариант при этом не отработает освобождение (у вcякой задачи есть два решения - простое и правильное ;-) )

#include <avr/interrupt.h>
#include <util/atomic.h>

uint8_t get_SREG_and_CLI() { uint8_t s = SREG; cli(); return s; }

#define ATOM()   for(uint8_t __temp=get_SREG_and_CLI(),iter=0; iter<1; iter++,SREG=__temp)


volatile uint8_t v;

void foo(uint8_t z)
{
    ATOM() {
        ++v;
        if(z) return;
        ++v;
    }    
}


void moo(uint8_t z)
{
    ATOMIC_BLOCK(ATOMIC_RESTORESTATE) {
        ++v;
        if(z) return;
        ++v;
    }    
}

.global    foo
    .type    foo, @function
foo:
    in r18,95-0x20
/* #APP */
    cli
/* #NOAPP */
    lds r25,v
    subi r25,lo8(-(1))
    sts v,r25
    tst r24
    brne .L10
    lds r24,v
    subi r24,lo8(-(1))
    sts v,r24
    out 95-0x20,r18
.L10:                           ; <--- а кто прерывания взад вернёт???
    ret

.global    moo
    .type    moo, @function
moo:
    in r18,95-0x20
/* #APP */
    cli
/* #NOAPP */
    lds r25,v
    subi r25,lo8(-(1))
    sts v,r25
    tst r24
    brne .L4
    lds r24,v
    subi r24,lo8(-(1))
    sts v,r24
.L4:                            ; <--- вот это другое дело!
    out 95-0x20,r18
    ret

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

то есть при создании объекта класса выдаётся ошибка: undefined reference to `__cxa_guard_release'
Полный ответ здесь. Но я на это не нарывался, видимо потому, что использую --ffunction-section и --gc-sections. Я и узнал-то об этих функциях только из статьи по ссылке.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

А если объявить tmrSpinup как static?

Есть информация, что некоторые статические объекты вызывают такую ошибку в новых версиях компилятора, так как отсутствует какая-то библиотека...

Решилось добавлением ключа -fno-threadsafe-statics

Так у меня она static и объявлена, вероятно, у меня достаточно старые версии :-)

За ключик спасибо, добавлю как упреждающий манёвр.

 

 

 

Полный ответ здесь.

У меня из дому какие-то проблемы именно с этим сайтом :-(

По прямому линку заходит, но страшно медленно, а вот на вторую страницу какой-то темы зайти уже нереально.

Поэтому я его практически не смотрю, на работе как правило не до интернета.

При этом всё остальное дома "летает", как и положено adsl2+, многое быстрее, чем на работе.

Так что гляну уже после "типоотпуска".

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.

Гость
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...