Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: уникальный идентификатор
Форум разработчиков электроники ELECTRONIX.ru > Микроконтроллеры (MCs) > Cредства разработки для МК > GNU/OpenSource средства разработки
ARV
собственно, вместо многократного повторения __attribute__ ((naked, section(".init7"))) для разных функций типа void foo(void) в разных файлах хочу сделать какой-то макрос, который сам бы это дело дописал перед каким-то автоматически сгенерированным идентификатором. в общем, пишем:
Код
initialize{тут код начальной инициализации}
а получаем фактически что-то типа
Код
__attribute__ ((naked, section(".init7"))) void _name120097553(void){nen код начальной инициализации}


подскажите, как сделать? ничего путнего не получается... проблема в формировании уникального идентификатора....
_Pasha
Цитата(ARV @ Mar 27 2009, 15:50) *
подскажите, как сделать?


Если в файле по одному иниту, их можно обозвать одинаково. smile.gif
ARV
Цитата(_Pasha @ Mar 27 2009, 15:17) *
Если в файле по одному иниту, их можно обозвать одинаково. smile.gif

увы, низзя... если функцию не объявлять static - то компоновщик обнаруживает наличие одинаковых идентификаторов... а если объявить static - не действует __attribute__
solosh
Попробуйте для создания уникальных имен использовать макросы __LINE__ и __FILE__
ARV
Цитата(solosh @ Mar 27 2009, 16:07) *
Попробуйте для создания уникальных имен использовать макросы __LINE__ и __FILE__

так вот же ж sad.gif их и пробовал... проблема в том, что как __LINE__ сконкатировать с символом? если я пишу так:
Код
#define initialize void init ## __LINE__ (void)
то вместо ожидаемого
Код
void init_234(void)
я получаю
Код
void init___LINE__(void)
что неприемлемо...
solosh
Нужен еще один проход препроцессора.
Вот как раз Ваш случай:
http://electronix.ru/forum/index.php?s=&am...st&p=361393
Petka
Цитата(ARV @ Mar 27 2009, 16:24) *
так вот же ж sad.gif их и пробовал... проблема в том, что как __LINE__ сконкатировать с символом? если я пишу так:
Код
#define initialize void init ## __LINE__ (void)
то вместо ожидаемого
Код
void init_234(void)
я получаю
Код
void init___LINE__(void)
что неприемлемо...

поколдуйте с двойным переопределением.
например
Код
#define MY_LINE __LINE__
#define MY_LINE2 MY_LINE
ARV
Цитата(solosh @ Mar 27 2009, 17:16) *
Нужен еще один проход препроцессора.
Вот как раз Ваш случай:
http://electronix.ru/forum/index.php?s=&am...st&p=361393

да, случай как раз мой. но почему-то когда я вручную писал static для инициализирующей функции, она исключалась уборщиком мусора (-Wl,-gc-sections -ffunction-sections)... наверное потому, что не было атрибута used?
спасибо за помощь!
ReAl
Цитата(ARV @ Mar 27 2009, 21:31) *
она исключалась уборщиком мусора (-Wl,-gc-sections -ffunction-sections)... наверное потому, что не было атрибута used?
Да, именно поэтому.
demiurg_spb
А для чего, простите, весь сыр-бор. Чтобы лишь автоматизировать инициализацию какого-либо программного модуля?
Если так, то Вы ребята далеко ушли от программирования на С. Что неужели трудно явно вызывать процедуру инициализации? А как быть с расстановкой очерёдности инициализации разных модулей? С простотой портирования? С наглядностью наконец? На мой взгляд происходит подмена понятия программирования. Извините, но хочется понять глубинный смысл сего явления. Ответ типа: мне удобно т.к. я догадался до такого "извращения" - не то, что хочется услышатьsmile.gif Я сторонник глубинного понимания языка программирования, а не фишек линкера и прочего инструментария, входящего в комплект поставки компилятора. Да это знать и понимать тоже нужно, но использовать так... Уж если считаете, что Вам стал жать С используйте С++ с его конструкторами и деструкторами, шаблонами и всем-всем остальным что Вам будет нужно. Так будет честнее. ИМХО.
Сергей Борщ
Цитата(demiurg_spb @ Mar 28 2009, 01:38) *
А для чего, простите, весь сыр-бор. Чтобы лишь автоматизировать инициализацию какого-либо программного модуля?
Нет, периферии.
Цитата(demiurg_spb @ Mar 28 2009, 01:38) *
Если так, то Вы ребята далеко ушли от программирования на С. Что неужели трудно явно вызывать процедуру инициализации?
Трудно. На каждый вызов положить по ®call/ret и сохранение/восстановление контекста? Нафига? Если для этого есть специально разарботанный очень элегантный механизм.
demiurg_spb
Цитата(Сергей Борщ @ Mar 28 2009, 11:57) *
Нет, периферии. ... Нафига? Если для этого есть специально разарботанный очень элегантный механизм.
Я вас прекрасно понимаю с точки зрения экономии ПЗУ, слабо с точки зрения повышения быстродействия. И совсем никак с моей личной точки зрения. Поясню. У меня обычно пользователю доступны режимы работы устройства (пусть это будет пресловутый UART), так после изменения настроек нужно вызвать процедуру инициализации повторно. Так если эта процедура у меня уже физически есть, то зачем мне всё это? Да есть такая периферия которая не отдаётся на откуп юзеру, так с ней можно и через static inline или __attribute__((always_inline)) "бороться". Хотя тут уже не принципиально как. Спасибо за ответ. Для меня тема исчерпана. Ваш метод имеет право на жизньsmile.gif
2 ARV: гляньте, тут тоже происходит формирование уникальных идентификаторов:
Код
#ifdef __cplusplus
    template<bool> struct CompileTimeError;
    template<> struct CompileTimeError<true> {};
#    define STATIC_ASSERT(expr)    (CompileTimeError<(expr) != 0>())
#else
#    define MY_JOIN_3_H(A,B,C)     A##B##C
#    define MY_JOIN_3(A,B,C)       MY_JOIN_3_H(A,B,C)
#    define STATIC_ASSERT_H(expr)  typedef int MY_JOIN_3(static_assert_,__LINE__,_h) [(expr) ? 1 : -1]
#    define STATIC_ASSERT(expr)    STATIC_ASSERT_H(expr)
#endif
ARV
2 demiurg_spb: спасибо, уже не надо, тем более, что принцип тот же самый, что и ранее, и даже тот же, о котором я сам думал... я лишь не сразу понял, что надо неоднократно макросы вкладывать друг в друга smile.gif
demiurg_spb
Да тут есть свой прикол. Я даже использую это в таком случае:
Через makefile спускаю строку (имя файла) в зависимости от типа условной компиляции:
Код
ADD_COMPILE_FLAGS += -DLOW_LEVELX_H=low_level3.h
...
CFLAGS += $(ADD_COMPILE_FLAGS)

определяю макрос:
Код
// str macro
#define STR(S)                #S       // STR(blabla) = "blabla"
#define XSTR(S)                STR(S)   // STR(_version) = "v1.0" if _version = "v1.0"

А в программе просто подключаю инклюдом нужный файл без всяких там #if #elif #endif
Код
#include XSTR(LOW_LEVELX_H)
Мне нравится.
_Pasha
Цитата(demiurg_spb @ Mar 28 2009, 17:43) *
Мне нравится.

+1 И мне smile.gif
Автору большое спасибо за тему. Познавательно.
ReAl
Цитата(demiurg_spb @ Mar 28 2009, 01:38) *
А как быть с расстановкой очерёдности инициализации разных модулей?
...
Уж если считаете, что Вам стал жать С используйте С++ с его конструкторами и деструкторами,
А что, очерёдность вызовов конструкторов (т.е. инициализации) статических объектов из разных модулей в С++ будет определена?

И неужели Вы думаете, что при наличии функции init_XXX(), которая может вызываться по ходу программы в разных местах кто-то будет дублировать её тело в init-блоке? Хотя можно её вызов вставить в
Код
INIT(8) { init_XXX(); }
:-)
Cам подход "подключили модуль - он автоматически проинициализируется по умолчанию" имеет право на жизнь, у того же борланда это делалось через #pragma startup/#pragma exit.
И дело не только в экономии нескольких байт и тактов, но и в автоматизации того, что можно и нужно автоматизировать, а не нагружать себя самого созданием нагромождения вызовов init_XXX() в начале функции main() (заодно явно видно, какие инициализации терпят перестановку местами, а уж то, что осталось в виде init_XXX() - обкомментировать как и почему оставлено и в каком порядке должно вызываться, если это важно).

Ну и кроме того случаи бывают разные, например, может захотеться у той же меги64 или 162 внешнюю память сделать продолжением внутренней и "без дырок" - стек разместить в конце внешней памяти (да, будет работать несколько медленнее, "ну и что"). Тогда включить внешнюю шину надо до первого вызова, даже в С++ с его конструкторами. Вот тогда фрагмент комментария из темы по ссылке выше как раз и поможет.
Код
*  INIT_CODE(1)
*  {
*    MCUCR = (1 << SRE);
*    XMCRA = (4 << SRL0) | (0 << SRW00);
*    XMCRB = (1 << XMBK);
*  }
static inline тут не поможет.

Я таким образом настраиваю всякие таймерные и не только прерывания - рядом с обработчиком ISR() и (если они есть) функциями доступа к разделяемым с прерываниям данными торчит INIT(8), который это всё хозяйство инициализирует. Пусть он себе "вызывается" автоматичекски.
Рассматривайте этот метод как расширение возможностей start-up-модуля, но без модификации его текста (чем этот метод и является) и станет понятно, когда его удобно и "правильно" применять.
start-up-модуль занимается подготовкй окружения для функции main() (можно було бы ведь в начале функции main() вызывать библиотечные функции clear_bss(); init_initialized_data(); - Вы же не боретесь за право это делать? ) для общго случая, а код в отданных программисту секциях .init1/3/5/7/8 уточняет это для данной конкретной программы.
demiurg_spb
ReAl, искреннее Вам спасибо! Всё разложили по полочкам!
Так действительно может оказаться нагляднее и удобнее, нежели править startup.S, чем я обычно и занимался по мере необходимости.
ReAl
Цитата(demiurg_spb @ Mar 28 2009, 20:54) *
Так действительно может оказаться нагляднее и удобнее, нежели править startup.S
И отдельное спасибо авторам за раскладку секций:
Код
*  .init0  Start here after reset.
*  .init1
*  .init2  Clear __zero_reg__, set up stack pointer.
*  .init3
*  .init4  Initialize data and BSS.
*  .init5
*  .init6  C++ constructors.
*  .init7
*  .init8
*  .init9  Call main()
Имеем достаточно мелкую "нарезку" для того, чтобы подсунуть своё именно на нужном этапе.
Да, с init1 надо осторожно, если встречается что-то в духе
MCUSR = 0;
то это надо делать в init3, так как оно будет скомпилировано отправкой в SFR регистра r1, а он обнуляется в init2.
ARV
Цитата(ReAl @ Mar 29 2009, 00:56) *
И отдельное спасибо авторам за раскладку секций:

дык в документации к avr-libc все это подробно рассказано smile.gif
_Pasha
Цитата(ReAl @ Mar 28 2009, 23:56) *
Да, с init1 надо осторожно

Я вот тоже не правлю стартап, но в секциях init* пишу асмовый код. На всякий случай, вдруг концепция измениццо smile.gif
ReAl
Цитата(ARV @ Mar 30 2009, 08:02) *
дык в документации к avr-libc все это подробно рассказано smile.gif
Ну да, там и почитано, им и спасибо.
KRS
Цитата(demiurg_spb @ Mar 28 2009, 17:43) *
А в программе просто подключаю инклюдом нужный файл без всяких там #if #elif #endif
Код
#include XSTR(LOW_LEVELX_H)
Мне нравится.


C инклюдами можно проще гораздо.
Например:
Код
-DTEST_CFG="\"test1/test_cfg.h\""

#include TEST_CFG // "test1/test_cfg.h"
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.