|
Перенос кода из под ИАРа на WinAVR, возникают некоторые вопросы... |
|
|
|
Nov 23 2008, 17:23
|

Профессионал
    
Группа: Свой
Сообщений: 1 143
Регистрация: 30-09-08
Из: Новочеркасск
Пользователь №: 40 581

|
Цитата(sonycman @ Nov 23 2008, 20:09)  А может кто подскажет, где поискать документацию по AVR GCC в виде PDF? А то не очень удобно пользоваться html версией...  как правило, она находится в папке WinAVR\doc\avr-libc - я ведь верно понял, что интересует документация на avr-libc?
--------------------
Я бы взял частями... но мне надо сразу.
|
|
|
|
|
Nov 23 2008, 18:03
|

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

|
Цитата(sonycman @ Nov 22 2008, 23:17)  Разрабы туда, наверное, тонну хитрости запихали! Учитывать все выходы из секции для восстановления прерываний... бла, как они это осуществили? У 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 и С++ класс дали при компиляции тождественный код.
--------------------
Ну, я пошёл… Если что – звоните…
|
|
|
|
|
Nov 23 2008, 19:09
|

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

|
Цитата(ARV @ Nov 23 2008, 21:23)  как правило, она находится в папке WinAVR\doc\avr-libc - я ведь верно понял, что интересует документация на avr-libc? Нет, на библиотеку как раз pdf есть. Мне бы на компилятор, со всеми его ключевыми словами, аттрибутами и т.д... Она там только в формате html... в принципе, сойдёт, если нет лучшего Цитата(ReAl @ Nov 23 2008, 22:03)  Очень симпатично сделано... Учтено всё. Спасибо за разъяснение, стало понятнее! Сам только недавно начал осваивать С++, и имею небольшое представление о классах. Очень интересная штука У меня возникла очередная проблема в портировании проекта 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' Что-то я пока что в тупике. Описания такой функции нет в исходниках компилятора. Что делать? Почему так получилось?
|
|
|
|
|
Nov 23 2008, 20:38
|
Профессионал
    
Группа: Свой
Сообщений: 1 453
Регистрация: 23-08-05
Пользователь №: 7 886

|
Цитата(ReAl @ Nov 23 2008, 21:03)  У 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) И переносимо, и без хитрых атрибутов? Может я чего-то не понял. Или есть какой-то потаёный от меня смысл?
|
|
|
|
|
Nov 23 2008, 21:37
|

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

|
Цитата(sonycman @ Nov 23 2008, 21:09)  то есть при создании объекта класса выдаётся ошибка: undefined reference to `__cxa_guard_release' Что-то я пока что в тупике. Описания такой функции нет в исходниках компилятора. Что делать? Почему так получилось?  Странно. К тому коду было добавлено Код 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 можно найти объяснения.
--------------------
Ну, я пошёл… Если что – звоните…
|
|
|
|
|
Nov 23 2008, 21:37
|

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

|
Цитата(Petka @ Nov 24 2008, 00:38)  В принципе понятно как они сделали. но во зачем - непонятно. зачем такой хитрый выверт с непереносимыми атрибутами, когда аналогичную штуку можно проделать без них? например: Код #define ATOMIC_BLOCK() for(U8 __temp=get_SREG_and_CLI(),iter=0;iter<1;i++,SREG=__temp) И переносимо, и без хитрых атрибутов? Может я чего-то не понял. Или есть какой-то потаёный от меня смысл? А если внутри блока будет break или return? Выполнится ли тогда SREG=__temp? Цитата(ReAl @ Nov 24 2008, 01:37)  Странно. К тому коду было добавлено Код static CTimer tmrSpinup;
int main() { tmrSpinup.Set(10); while( !tmrSpinup ); for(;;); } и всё собралось-слинковалось несколькими версиями от 3.4.6 (WinAVR-20060421) до 4.4.0 (Klen-20080530), более свежих нет на компе. Есть информация, что некоторые статические объекты вызывают такую ошибку в новых версиях компилятора, так как отсутствует какая-то библиотека... Решилось добавлением ключа -fno-threadsafe-statics
|
|
|
|
|
Nov 23 2008, 21:43
|

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

|
Цитата(Petka @ Nov 23 2008, 22:38)  В принципе понятно как они сделали. но во зачем - непонятно. зачем такой хитрый выверт с непереносимыми атрибутами, когда аналогичную штуку можно проделать без них? например: Код #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
--------------------
Ну, я пошёл… Если что – звоните…
|
|
|
|
|
Nov 23 2008, 21:45
|

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

|
Цитата(sonycman @ Nov 23 2008, 21:09)  то есть при создании объекта класса выдаётся ошибка: undefined reference to `__cxa_guard_release' Полный ответ здесь. Но я на это не нарывался, видимо потому, что использую --ffunction-section и --gc-sections. Я и узнал-то об этих функциях только из статьи по ссылке.
--------------------
На любой вопрос даю любой ответ"Write code that is guaranteed to work, not code that doesn’t seem to break" ( C++ FAQ)
|
|
|
|
|
Nov 23 2008, 21:51
|

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

|
Цитата(sonycman @ Nov 23 2008, 23:37)  А если объявить tmrSpinup как static? Есть информация, что некоторые статические объекты вызывают такую ошибку в новых версиях компилятора, так как отсутствует какая-то библиотека... Решилось добавлением ключа -fno-threadsafe-statics Так у меня она static и объявлена, вероятно, у меня достаточно старые версии :-) За ключик спасибо, добавлю как упреждающий манёвр. Цитата(Сергей Борщ @ Nov 23 2008, 23:45)  У меня из дому какие-то проблемы именно с этим сайтом :-( По прямому линку заходит, но страшно медленно, а вот на вторую страницу какой-то темы зайти уже нереально. Поэтому я его практически не смотрю, на работе как правило не до интернета. При этом всё остальное дома "летает", как и положено adsl2+, многое быстрее, чем на работе. Так что гляну уже после "типоотпуска".
--------------------
Ну, я пошёл… Если что – звоните…
|
|
|
|
2 чел. читают эту тему (гостей: 2, скрытых пользователей: 0)
Пользователей: 0
|
|
|