Микроконтролери и електроника
http://mcu-bg.com/mcu_site/

GCC & overlay sections
http://mcu-bg.com/mcu_site/viewtopic.php?f=3&t=9720
Страница 1 от 1

Автор:  [ Пет Яну 13, 2012 8:01 pm ]
Заглавие:  GCC & overlay sections

Компилатор GCC, 3 source файла, група от глобални static променливи с различни имена в тези 3 файла, трябва да се разположат на общ адрес в RAM, т.е. да се получи overlay.

Примерно трите файла изглеждат така:

Код:
source1.c
....
static J1939 __attribute__((section("userdata"),address(0x800))) j1939_xxx;
....


Код:
source2.c
....
static J1939 __attribute__((section("userdata"),address(0x800))) j1939_yyy;
....


Код:
source2.c
....
static J1939 __attribute__((section("userdata"),address(0x800))) j1939_zzz;
....


userdata секцията съм я създал в линкерския скрипт, задавам и адрес 0x800 на който искам
да ми разположи j1939 променливите ( секцията в скрипта също е зададена да бъда на 0x800).
Компилатора обаче си слага първата променлива на 0x800, втората на 0x854, третата на 0x8A4.

Някой да знае как се дефинират overlay променливи в GCC ?


Откак постнах въпроса се сетих да изпробвам да дефинирам 3 секции в линкер, примерно с имена
overlay1, overlay2 и overlay3, да им задам един и същ стартов адрес, след което в "C" файловете
да задам __attribute__((section("overlay.."),address(0x800))) , след което GCC компилира, но линкера
се разплака:
Код:
Link Error: section overlay2 [000800   -> 000801  ] overlaps section overlay1 [000800   -> 000801  ]
Link Error: section overlay3 [000800   -> 000801  ] overlaps section overlay1 [000800   -> 000801  ]


но като му се зададе опцията no-check-sections и работата стана. GCC сега ги разполага на един и същи
адрес .

Някой да знае по-елегантно решение ?

Автор:  miro_atc [ Пет Яну 13, 2012 8:57 pm ]
Заглавие:  Re: GCC & overlay sections

Това за какъв таргет е ?

Щото по принцип стандартно GCC (компилатора) няма думата при разполагане на променливите. Само линкера (LD) борави с адреси.

Така че нормално в сорса се указва само секцията (без адреси). А в линкерския скрипт задаваш адрес на секцията и евентуално някакъв ред/сортиране по който да се разполагат обектите в тая секция.

Освен това ти си задал "static" което влиза леко в конфликт, защото по стандарт всяка статик променлива трябва да се нулира, т.е. трябва да е в bss секцията, а пък ти след това слагаш друга секция. Не знам защо го правиш така, може за да ограничиш скопа... ама е подвеждащо ;-)

Автор:  [ Пет Яну 13, 2012 9:49 pm ]
Заглавие:  Re: GCC & overlay sections

Target-а няма значение. Правя го поради следната причина: имам у-во което ще има 3 различни режима на работа. В кой режим ще работи се избира по време на производството с джъмпер, а може и да се сложи ключе, за да може и потребителя да избира ( още не е решено дали потребителя ще има тази възможност, ако я има ще плаща в повече, т.е. това е четвърти, универсален вариант на устройството ). Трите режима използват общ код, но използват и такъв, който в другите режими няма да го има. Затова искам уникалните за даден режим променливи да са на общи адреси, за да могат тези адреси да се използват от линкера за уникалните променливи и на другите режими. Общите променливи са си общи, те се споделят и от трите режима. Уникалните променливи ги дефинирам като глобални static в рамките на файла за дадения режим на работа, за да нямат останалите режими достъп до тях ( по-точно за да не се изкушавам да ги използвам ), същевременно линкера има достъп до тях и ги използва. Един вид споделена памет.

При мен в сорс кода освен името на секцията мога да укажа и директно на кой адрес искам да е променливата, може би това е разширение на GCC-то за конкретния target ( 4.0.x ). Примерно, имаш 2 идентични UART канала, правиш си за тях един общ struct, след което когато дефинираш променливата за дадения канал задаваш с __attribute__ адреса й в паметта. Кода за приемане/изпращане може да е общ за двата канала, но като подаваш различна структура ще оперира с два различни UART-а. Това е същото като с хендъли, само дето при хендъла се харчи повече време да се определи кой е точно UART-a и да се заредят указателите с правилните адреси.

bss секцията е разделена на две: nbss ( near ) и bss. Near ми сa първите 2кб, достъпа до нея е по-бърз от bss.

Автор:  palavrov [ Пет Яну 13, 2012 10:31 pm ]
Заглавие:  Re: GCC & overlay sections

Я виж това дали ще свърши работа - http://sourceware.org/binutils/docs/ld/ ... ption.html
Би трябвало да стане - вместо да правиш овърлей на код секциите му пиши тези с данни.
А да те питам нещо - преди време се отрепах да търся нещо от рода на __attribute__(address(...)) и не намерих нищо - ти с коя версия/буилд на GCC го ползваш това?

Автор:  [ Пет Яну 13, 2012 11:05 pm ]
Заглавие:  Re: GCC & overlay sections

Цитат:
Я виж това дали ще свърши работа - http://sourceware.org/binutils/docs/ld/ ... ption.html
Би трябвало да стане - вместо да правиш овърлей на код секциите му пиши тези с данни.

Ще го изпробвам да видя дали ще стане.

Цитат:
А да те питам нещо - преди време се отрепах да търся нещо от рода на __attribute__(address(...)) и не намерих нищо - ти с коя версия/буилд на GCC го ползваш това?

4.0.3 , dsPIC30F/33F/33E . Може и да е уникално за Microchip компилацията.

Цитат:
address (addr)
The address attribute specifies an absolute address for the variable. This attribute can be used in conjunction with a section attribute. This can be used to start a group of variables at a specific address:

int foo __attribute__((section("mysection"),address(0x900)));
int bar __attribute__((section("mysection")));
int baz __attribute__((section("mysection")));

Автор:  miro_atc [ Пет Яну 13, 2012 11:09 pm ]
Заглавие:  Re: GCC & overlay sections

Пирев, не мога да те разбера от къв зор си усложняваш живота... Искаш да ти е трудно като смениш компилатор/таргет/адреси ли що ли? ;-)

Направи си като бял човек, примерно

header1.h:

Код:
struct module1_data
{
      J1939   J1939_xxx;
      // и т.н всички променливи дето ползва модула
}

void module1(module1_data* data);


source1.c:

Код:
//нямаш никакви глобални променливи

void module1(module1_data* data)
{
    //ползваш само *data

   data->J1939_xxx = 234;

}



и т.н за всички модули.

и накрая да кажем main.c

Код:
#include header1.h
#include header2.h
...
union data_storage
{
    module1_data  as_module1;
    module2_data  as_module2;
    ....
}

data_storage data;

int main(void)
{
    switch(jumers)
    {
        case 1: 
                 module1(&data.as_module1);
                 break;
        case 2: 
                 module2(&data.as_module2);
                 break;
        ....
    }

}

Автор:  [ Съб Яну 14, 2012 12:13 am ]
Заглавие:  Re: GCC & overlay sections

Че защо да си усложнявам живота ? В момента смених процесора, и стана много културно и бързо. На стария процесор по същия начин го бях направил, само че там си имаше директно overlay атрибут за променливите :D А този не мисля, че ще го сменям. В един и същ корпус имам избор на 30, 40 или 60 MIPS. В момента съм на 10 MIPS и натоварвам процесора на към 45%.

Мислех и по начина, по който предлагаш с union, но се отказах, поради твърде тромавия достъп през указатели.
Сега всеки режим си има собствен файл, в главната програма правя switch( jumper ) и викам главната функция на съответния режим. Всеки файл си стана самостоятелен програмен модул независим от останалата част, само се наложи малко гимнастика с линкера, ама аз докато писах поста с въпроса взе, че стана :-) Общите части на кода ги направих в библиотека, която лесно може да се адаптира според използваната платка.

Код:
int main(void)   {

    InitMCU();
 
#if defined ( USE_J1939 )

    // Set ECAN module in loopback mode, for development only
    //SetECANMode( ECAN_LOOPBACK_MODE );

   // Wait for address contention to time out
    while( J1939_Flags.WaitingForAddressClaimContention ) {
      Delay1ms();
      J1939_Poll( 1 );
   }
#endif

    // Main program loop
    while( 1 )   {
      ClearWatchDog();
      switch( DeviceMode )   {
          // Switch at position 2
          case Mode1:   Mode1Main(); break;
          // Switch at position 3
          case Mode2:   Mode2Main(); break;
          // Switch at position 4
          case Mode3:   Mode3Main(); break;
          // Switch at position 1
          case Mode4:   Mode4Main(); break;
          default:      break;
      }
    }
    return 0;
}

Автор:  palavrov [ Съб Яну 14, 2012 12:50 am ]
Заглавие:  Re: GCC & overlay sections

¶ написа:
Мислех и по начина, по който предлагаш с union, но се отказах, поради твърде тромавия достъп през указатели.

Това не винаги е вярно - примерно на АРМ не е, за х86 е все тая. Проблема е че повечето риск процесори за да заредят някоя променлива от паметта в регистър, трябва първо с отделна инструкция да и заредят адреса, но пък имат инструкция с относително адресиране спрямо регистър (в който е указателя) така че това което Миро предлага може да работи по бързо. GCC се изхитрява и зарежда в един регистър адрес някъде по средата на променливите от дата сегмента, и после ги чете и пише спрямо него, но това работи само при условие че всички променливи са дефинирани в същия файл, ако са външни нищо не помага, зарежда си им адреса всеки път с отделна инструкция.

Автор:  [ Съб Яну 14, 2012 6:06 am ]
Заглавие:  Re: GCC & overlay sections

palavrov написа:
Това не винаги е вярно - примерно на АРМ не е, за х86 е все тая. Проблема е че повечето риск процесори за да заредят някоя променлива от паметта в регистър, трябва първо с отделна инструкция да и заредят адреса, но пък имат инструкция с относително адресиране спрямо регистър (в който е указателя) така че това което Миро предлага може да работи по бързо. GCC се изхитрява и зарежда в един регистър адрес някъде по средата на променливите от дата сегмента, и после ги чете и пише спрямо него, но това работи само при условие че всички променливи са дефинирани в същия файл, ако са външни нищо не помага, зарежда си им адреса всеки път с отделна инструкция.


Е в случая не е RISC ами DSP core, от време на време преглеждам листинга и горе-долу знам кое как се генерира. Като цяло съм доволен от кода, пъргаво ядро, адресацията е читава, но има моменти в които ме досърбяват ръцете да го направя на асемблер :D

Страница 1 от 1 Часовете са според зоната UTC + 2 часа [ DST ]
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group
http://www.phpbb.com/