|
IAR 5.11, Объясните pls |
|
|
|
May 16 2008, 15:28
|
Группа: Новичок
Сообщений: 9
Регистрация: 17-04-08
Пользователь №: 36 836

|
Собственно проблема такая - примеры для AT91SAM7A3 компилятся, линкуются и тп. но!, при попытке прогнать их во встроенном симуляторе Cstartup.s с первой точки (reset) улетает куда-то на адрес 6E7C0000, при попытке переписать стартап чтобы он с ресета уходил на lowlevel_init в симуляторе все ОК, однако в железе - мертвяк. все во Flash_DEBUG
|
|
|
|
2 страниц
1 2 >
|
 |
Ответов
(1 - 24)
|
May 17 2008, 05:41
|

Местный
  
Группа: Участник
Сообщений: 355
Регистрация: 27-03-07
Из: Україна, Чуднів
Пользователь №: 26 530

|
Цитата(Laurica @ May 16 2008, 18:28)  Собственно проблема такая - примеры для AT91SAM7A3 компилятся, линкуются и тп. но!, при попытке прогнать их во встроенном симуляторе Cstartup.s с первой точки (reset) улетает куда-то на адрес 6E7C0000, при попытке переписать стартап чтобы он с ресета уходил на lowlevel_init в симуляторе все ОК, однако в железе - мертвяк. все во Flash_DEBUG Немного непонятно А файл прошивки должен формироваться в режиме Реалис. Вы так его формировали? И ещё, где-то было сообщение нащёт версии 5.11 толи В толи А что она вообще не рабочая.
--------------------
нельзя недооценивать предсказуемость глупости
|
|
|
|
|
May 17 2008, 06:16
|
Группа: Новичок
Сообщений: 9
Регистрация: 17-04-08
Пользователь №: 36 836

|
Цитата(sKWO @ May 17 2008, 09:41)  Немного непонятно А файл прошивки должен формироваться в режиме Реалис. Вы так его формировали? И ещё, где-то было сообщение нащёт версии 5.11 толи В толи А что она вообще не рабочая. Теперь мне не понятно...Что значит в режиме Реалис? Дело в том, что моя собственная программа, отлично собиравшаяся в 4.3Х-KS напрочь отказывается компилироваться в 5.11-EV. При попытке переписать startup вроде как адресация после рестарта нормальная - я попадаю в lowlevel init, затем в main - но это все только в симуляторе, а в железе ... ЛЮДИ, ежели не в падлу, скиньте ссылку на EWARM 4.XX EVALUATION, все-же хочется работать, а не бороться со средствами разработки...
|
|
|
|
|
May 17 2008, 06:31
|

Гуру
     
Группа: Свой
Сообщений: 13 372
Регистрация: 27-11-04
Из: Riga, Latvia
Пользователь №: 1 244

|
Цитата(sKWO @ May 17 2008, 07:41)  И ещё, где-то было сообщение нащёт версии 5.11 толи В толи А что она вообще не рабочая. - А это правда, что Сидоров выиграл машину в лотерею? - Правда. Только не машину, а тысячу рублей. И не в лотерею, а в преферанс, и не выиграл, а проиграл... Цитата(Laurica @ May 17 2008, 08:16)  ...все-же хочется работать, а не бороться со средствами разработки...  Боритесь только сами с собой. Разработчики коммпилятров ошибаются несораизмеримо реже, нежели их пользователи  . тем более на переходе в main(). A EWARM 4.xx, Вы конечно взять можете на сайте iar.com, но незачем.
--------------------
Feci, quod potui, faciant meliora potentes
|
|
|
|
|
May 17 2008, 10:53
|
Группа: Новичок
Сообщений: 9
Регистрация: 17-04-08
Пользователь №: 36 836

|
Цитата(zltigo @ May 17 2008, 10:31)  Боритесь только сами с собой. Разработчики коммпилятров ошибаются несораизмеримо реже, нежели их пользователи  . Да я не против бороться, я даже за  . Но чтобы бороться надо знатьхоть с чем конкретно. Кто нибудь знает где почитать как startup-ы пишуться в 5.11 с примерами/картинками  . На сайте IAR я посмотрю, но по-моему там уже везде ссылки на 5.10-5.11.
|
|
|
|
|
May 17 2008, 17:02
|
Группа: Новичок
Сообщений: 9
Регистрация: 17-04-08
Пользователь №: 36 836

|
Цитата(zltigo @ May 17 2008, 18:27)  C картинками - это Вам тогда в детский сад надо пойти. Да староват вроде как для сада уже... Зря вы так, наглядный пример лучше трех талмудов.
|
|
|
|
|
May 17 2008, 17:33
|

Гуру
     
Группа: Свой
Сообщений: 13 372
Регистрация: 27-11-04
Из: Riga, Latvia
Пользователь №: 1 244

|
Цитата(Laurica @ May 17 2008, 19:02)  Зря вы так, наглядный пример лучше трех талмудов. Повторяю: Код ..базовый вариант startup в комплекте поставки.. Более, чем нагляден и достаточно универсален. Разве только без картинок  .
--------------------
Feci, quod potui, faciant meliora potentes
|
|
|
|
|
May 17 2008, 18:55
|
Группа: Новичок
Сообщений: 9
Регистрация: 17-04-08
Пользователь №: 36 836

|
Обратился к первоисточнику: Код ARM __vector: ldr pc,[pc,#+24] ;; Reset ---------------------------------- __und_handler: | ldr pc,[pc,#+24] ;; Undefined instructions | __swi_handler: | ldr pc,[pc,#+24] ;; Software interrupt (SWI/SVC) | __prefetch_handler: | ldr pc,[pc,#+24] ;; Prefetch abort | __data_handler: | ldr pc,[pc,#+24] ;; Data abort | DC32 0xFFFFFFFF ;; RESERVED | __irq_handler: | ldr pc,[pc,#+24] ;; IRQ<----------------------------------- __fiq_handler: ldr pc,[pc,#+24] ;; FIQ DC32 __iar_program_start DC32 __und_handler DC32 __swi_handler DC32 __prefetch_handler DC32 __data_handler<-------------------------------------- а из IRQ сдесь B . DC32 IRQ_Handler_Entry DC32 FIQ_Handler_Entry если я правильно понимаю, то вот сдесь Код ldr pc,[pc,#+24] происходит добавление к текущему адресу числа 24, (смещение на 6 dword) то есть если выполнится первая такая команда, то мы окажемся там, где стрелочка в коде. Так? Понимаю, что звучит по-дурацки, но...
|
|
|
|
|
May 19 2008, 05:33
|
Бывалый
    
Группа: Свой
Сообщений: 1 584
Регистрация: 7-08-07
Пользователь №: 29 615

|
Цитата(Laurica @ May 17 2008, 22:55)  Код ldr pc,[pc,#+24] происходит добавление к текущему адресу числа 24, (смещение на 6 dword) то есть если выполнится первая такая команда, то мы окажемся там, где стрелочка в коде. Так? Понимаю, что звучит по-дурацки, но...  В счетчик команд заносится соответствующий хандлер, т.е. осуществляется переход на соответствующую метку .
|
|
|
|
|
May 19 2008, 06:14
|
Группа: Новичок
Сообщений: 9
Регистрация: 17-04-08
Пользователь №: 36 836

|
Цитата(alexander55 @ May 19 2008, 09:33)  В счетчик команд заносится соответствующий хандлер, т.е. осуществляется переход на соответствующую метку . Это понятно, что обработчик заносится..., но меня интересует вопрос правильно ли я понимаю КАКОЙ обработчик туда заносится. Адресация-то относительная.
|
|
|
|
|
May 19 2008, 06:23
|

Гуру
     
Группа: Свой
Сообщений: 13 372
Регистрация: 27-11-04
Из: Riga, Latvia
Пользователь №: 1 244

|
Цитата(Laurica @ May 17 2008, 20:55)  если я правильно понимаю, то вот сдесь Код ldr pc,[pc,#+24] происходит добавление к текущему адресу числа 24, (смещение на 6 dword) то есть если выполнится первая такая команда, то мы окажемся там, где стрелочка в коде. Так? Нет. "Для разобраться" надо просто слегка посмотреть на архитектуру процессора и на то, что значат в ASM скобочки []. Хотя написано, конечно от балды. Я так не пишу, дабы не заморачивать голову ненужными магическими числами. Так читабельнее: Код ldr pc, (?vect_entry + 4*0); 00 ldr pc, (?vect_entry + 4*1); 04 ldr pc, (?vect_entry + 4*2); 08 ldr pc, (?vect_entry + 4*3); 0C ldr pc, (?vect_entry + 4*4); 10 dc32 0 ; 14 Summ of other vectors instructions ldr pc, [pc,#-0xFF0]; 18 Jump directly to the address given by the AIC ; from [0xFFFFF030] Curent 18h +conveyer ldr pc, (?vect_entry + 4*7); 1C ;---------------------------------------------------------------------------- ORG 0x20 ; Constant table entries (for ldr pc) will be placed at 0x20 ?vect_entry: dc32 ?cstartup ; Reset dc32 ?undf_abort ; UND dc32 vPortYieldProcessor; SWI dc32 ?pref_abort ; P_ABT dc32 ?data_abort ; D_ABT dc32 0 ; ARM-reserved vector dc32 0 ; IRQ (Jump directly!) dc32 FIQ_ISR_handler; FRQ
--------------------
Feci, quod potui, faciant meliora potentes
|
|
|
|
|
May 19 2008, 06:46
|
Группа: Новичок
Сообщений: 9
Регистрация: 17-04-08
Пользователь №: 36 836

|
За пример - большое спасибо, так и вправду понятнее. Однако, касаемо моей изначальной проблеммы - а именно не_запускания программы в железе - наткнулся на то, что если workspace поставить flash_flash (а не flash_debug), то все несколько меняется. При компиляции во flash_debug при переходе с "0" адреса происходит улет в 0x6E7C (а там вакуум...и не работает не в железе ни в симуляторе), в RAM_debug 0x7B50, а в flash_flash туда же в 0x6E7C, при этом все работает в симуляторе, но в железе глухо как в танке... При этом код не меняелся никак. Доктор, где у меня ошибка..?
Сообщение отредактировал Laurica - May 19 2008, 06:58
|
|
|
|
|
May 20 2008, 09:03
|
Знающий
   
Группа: Свой
Сообщений: 509
Регистрация: 19-07-07
Из: г. Таганрог
Пользователь №: 29 246

|
Столкнулся с такой проблемой. Не могу в этом IAR експортировать функции (в данном случае __start_firmware()) из startup.s Прописал: Код SECTION .intvec:CODE:NOROOT(2) PUBLIC __vector PUBLIC __iar_program_start PUBLIC __vector_0x14 PUBLIC __start_firmware Тело функции: Код __start_firmware: ldr r0,=0x0 ldr r1,=0x0 ldr r2,=0x0 ldr r3,=0x0 ldr r4,=0x0 ldr r5,=0x0 ldr r6,=0x0 ldr r7,=0x0 ldr r8,=0x0 ldr r9,=0x0 ldr r10,=0x0 ldr r11,=0x0 ldr r12,=0x0 ldr r13,=0x0 ldr r14,=0x0 ldr pc, =(0x0008000) пытался вызвать: Код extern void __start_firmware();
main() { TargetInit(); __start_firmware(); } При компиляции выдается ошибка, что __start_firmware неопределена. В мануале написано, что для экспорта достаточно прописать PUBLIC __start_firmware. Может чего упустил?
--------------------
Умные речи подобны строкам, напечатанным курсивом. К. Прутков
|
|
|
|
|
May 20 2008, 09:44
|

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

|
Цитата(Vitaliy_ARM @ May 20 2008, 12:03)  При компиляции выдается ошибка, что __start_firmware неопределена. В мануале написано, что для экспорта достаточно прописать PUBLIC __start_firmware. Может чего упустил? Самое простое - может забыли подключить startup.s к проекту? Более сложное - если ваш файл компилится в режиме С++, то надо писать extern "C" void __start_firmware(); Если файл может компилиться как в С так и в С++ варианте, то Код #include <yvals.h> _EXTERN_C void __start_firmware(); _END_EXTERN_C
--------------------
На любой вопрос даю любой ответ"Write code that is guaranteed to work, not code that doesn’t seem to break" ( C++ FAQ)
|
|
|
|
|
May 20 2008, 10:01
|
Знающий
   
Группа: Свой
Сообщений: 509
Регистрация: 19-07-07
Из: г. Таганрог
Пользователь №: 29 246

|
Цитата(Сергей Борщ @ May 20 2008, 13:44)  Более сложное - если ваш файл компилится в режиме С++, то надо писать extern "C" void __start_firmware(); Если файл может компилиться как в С так и в С++ варианте, то Код #include <yvals.h> _EXTERN_C void __start_firmware(); _END_EXTERN_C Спасибо!!! Второй вариант заработал.
--------------------
Умные речи подобны строкам, напечатанным курсивом. К. Прутков
|
|
|
|
|
May 22 2008, 08:07
|
Знающий
   
Группа: Свой
Сообщений: 509
Регистрация: 19-07-07
Из: г. Таганрог
Пользователь №: 29 246

|
Потихоньку разбираюсь с C++. Не пойму один момент. Как известно, в ARM надо прописать адрес обработчика прерывания в VIC; Некоторый класс: Код typedef class _TIMER { public: void Init(); __arm void Isr();
}TIMER,*pTIMER;
void _TIMER::Init() { ------------------- OpenIsr(TIMER1,(DWORD*)Isr,HIGH_PR); // определяем обработчик прерывания }
__arm void _TIMER::Isr() { ---------------------- } Компилятор ругается, что нельзя сконвертировать тип. Пробовал и так конвертировать: Код OpenIsr(TIMER1,static_cast<DWORD*>(Isr),HIGH_PR); // определяем обработчик прерывания Ошибка таже: Error[Pa073]: invalid type conversion (from "__code __interwork void ()" to "DWORD*") Это вообще возможно или я в трех соснах блуждаю?
--------------------
Умные речи подобны строкам, напечатанным курсивом. К. Прутков
|
|
|
|
|
May 22 2008, 08:40
|

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

|
Цитата(Vitaliy_ARM @ May 22 2008, 11:07)  Ошибка таже: Error[Pa073]: invalid type conversion (from "__code __interwork void ()" to "DWORD*") Странная ошибка. он должен был ругаться на конвертацию адреса функции-члена в указатель, а он ругается на нее как на обычную функцию. Дело в том, что при вызове функции-члена первым параметром неявно передается указатель на объект. Прерывание не может передать этот указатель. Поэтому, или обработчик должен быть статической функцией-членом (которой не нужен this) или надо написать обычную функцию как обертку: Код __arm void TIMER1_Isr_wrapper() { TIMER1.Isr(); // Тут мы явно указываем передать адрес TIMER1 как this }
OpenIsr(TIMER1,(DWORD*)TIMER1_Isr_wrapper,HIGH_PR); // определяем обработчик прерывания при этом функцию-член-обработчик лучше сделать встраиваимой. Чтобы было легче понять: Вы объявили 5 экземпляров этого класса (TIMER1, TIMER2, ... TIMER5). Попав в ваш _TIMER::Isr(), откуда он будет знать, какой конкретно из этих 5 таймеров надо обрабатывать? И при инициализации ваш _TIMER:Init() настраивает только первый таймер, а как настраивать остальные? Если вы пишете этот класс под один конкретный таймер, то можно все функции-члены и данные-члены сделать статическими, но тогда появится неудобство - придется явно заводить каждый статический член-данное. Ой... Вы же передаете TIMER1 в OpenIsr. Видимо где-то дальше оно у вас используется для вызова обработчика. Тогда про статическое не читайте, почитайте это: указатель на функцию-член. И покажите объявление (а лучше и текст) OpenIsr()
--------------------
На любой вопрос даю любой ответ"Write code that is guaranteed to work, not code that doesn’t seem to break" ( C++ FAQ)
|
|
|
|
|
May 22 2008, 14:29
|
Знающий
   
Группа: Свой
Сообщений: 509
Регистрация: 19-07-07
Из: г. Таганрог
Пользователь №: 29 246

|
Цитата(Сергей Борщ @ May 22 2008, 12:40)  Ой... Вы же передаете TIMER1 в OpenIsr. Видимо где-то дальше оно у вас используется для вызова обработчика. Тогда про статическое не читайте, почитайте это: указатель на функцию-член. И покажите объявление (а лучше и текст) OpenIsr() Хорошая ссылка. Привожу код для OpenIsr(): Код void OpenIsr(DWORD IntNum,DWORD Handler, DWORD Priority) { DWORD *vect_addr; DWORD *vect_cntl; VICIntEnClr = 1 << IntNum; if (IntNum < VIC_SIZE ) { vect_addr = (DWORD *)(VIC_BASE_ADDR + VECT_ADDR_INDEX + IntNum*4); vect_cntl = (DWORD *)(VIC_BASE_ADDR + VECT_CNTL_INDEX + IntNum*4); *vect_addr = Handler; *vect_cntl = Priority; VICIntEnable = 1 << IntNum; } } Немного конкретизирую идею Думал сделать отдельный класс TARGET, в котором будут находиться функции , а потом все классы сделать наследниками его. Класс, который написал - это просто пример. Наверное удобнее номер таймера передавать в конструкторе, а потом от этого прописывать прерывания в OpenIsr: Код typedef class _TIMER { public: _TIMER(DWORD TimerNum); void Init(); void Isr(); } Собственно на пути всего этого стоит то, что не могу передать функции OpenIsr адрес обработчика превывания (метод этого же класса), который она должна записать в регистр микроконтроллера (LPC2468). По ссылке, указанной вами, попытался создать в классе такой указатель: void (_TIMER::*pFunction) (); Потом в конструкторе попытался сделать так: Код _TIMER::_TIMER(void) { DWORD *p; pFunction = &_TIMER::Isr; p = static_cast<DWORD*>(pFunction); } На третью строчку в фигурных скобках таже ошибка, не может сконвертировать тип. Обертку C функции делать не очень хочется, каждый раз при создании класса ее придется тоже создавать.
Сообщение отредактировал Vitaliy_ARM - May 22 2008, 14:35
--------------------
Умные речи подобны строкам, напечатанным курсивом. К. Прутков
|
|
|
|
|
May 22 2008, 18:18
|

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

|
Ах вот оно как! Я чего-то подумал, что TIMER1 это у вас объект класса _TIMER, а это вы так VIC_TIMER1 переобозвали... Маленькое замечание - не рекомендуется использовать подчеркивание в качестве первого символа в именах, такие имена зарезервированы за компилятором, можете напороться на интересные ошибки. И имена из одних заглавных обычно используются для мароопределений (#define). Цитата(Vitaliy_ARM @ May 22 2008, 17:29)  На третью строчку в фигурных скобках таже ошибка, не может сконвертировать тип. Функция, вызываемая по этому указателю, требует this в качестве неявного параметра. По этому указателю определяется, с каким именно из объектов данного класса идет работа. Как ваш обработчик передаст в функцию этот this? Если бы компилятор разрешил вам это преобразование, то у вас для нескольких прерваний VICVectAddr указывал бы на одну и ту же функцию. И как бы эта функция разгребала, какой из таймеров надо обрабатывать? VIC на каждый источник прерывания хочет вызвать отдельную функцию. И никак вы это не обойдете. Или вам придется сделать на N таймеров N функций-"оберток", или в классе объявить N статических обработчиков, которые отличаются от "оберток" только областью видимости. Посмотрите дизассемблированный текст обращения к любой функции-члену. В R1 находится указатель на объект Если бы компилятор разрешил вам это преобразование, то, поскольку в момент прерывания у вас R1 может иметь произвольное значение, эта функция-член начала бы править данные не в конкретном объекте, а в произвольном месте памяти. Нет, есть конечно финт ушами - сделать все классы, имеющие обработчики прерывания, полиморфными наследниками абстрактного базового класса, в VICVectAddr заносить указатели на объекты этих классов, а единый обработчик на векторе IRQ считывает VICVectAddr, преобразовывает его к типу "указатель на этот абстракный базовый класс" и вызывает по нему метод обработчика. Но это будет громоздкое (по сохранению регистров на стеке) и совершенно непереносимое на другие архитектуры решение. Что-то вроде вот такого: Код class interrupt_t { friend __irq void IRQ_Handler(); protected: interrupt_t(uint_fast8_t const vector_num, uint32_t const irq_ID); private: virtual void Handler() = 0; };
class timer_t : private interrupt_t { public: timer_t(uint_fast8_t const vector_num, uint32_t const irq_ID); private: virtual void Handler(); uint32_t Time; };
inline interrupt_t::interrupt_t(uint_fast8_t const vector_num, uint32_t const irq_ID) { uint32_t *Vector = &VICVectAddr0; Vector[vector_num] = (uint32_t)this; uint32_t *Control = &VICVectCtnl0; Control[vector_num] = (1 << 5) | irq_ID; VICVectEnable = (1 << irq_ID); }
inline timer_t::timer_t(uint32_t const vector_num, uint32_t const irq_ID) : interrupt_t(vector_num, irq_ID) { // настройка таймера ......... }
timer_t::Handler() { ++Time; }
timer_t Timer1 (15, VIC_TIMER1);
#pragma vector = 0x18 __irq void IRQ_Handler() { interrupt_t * pSource = (interrupt_t *)VICVectAddr; pSource->Handler(); VICVectAddr = 0; } Хм, а интересная мысль. Надо взять ее на заметку для небольших неторопливых безОСевых приложений типа загрузчиков.
--------------------
На любой вопрос даю любой ответ"Write code that is guaranteed to work, not code that doesn’t seem to break" ( C++ FAQ)
|
|
|
|
|
May 23 2008, 09:26
|
Знающий
   
Группа: Свой
Сообщений: 509
Регистрация: 19-07-07
Из: г. Таганрог
Пользователь №: 29 246

|
Цитата(Сергей Борщ @ May 22 2008, 22:18)  Хм, а интересная мысль. Надо взять ее на заметку для небольших неторопливых безОСевых приложений типа загрузчиков.  Сложно. Получается, что с оберткой по-проще. Уже делал что-то подобное (прикрепил один из вариантов оберток). Еще пока не использовал наследование, пользовался подобными конструкциями: Код while(1) { if(Emac.CheckRx()) { // определяем указатель на приемный пакет Emac.RxData(&Buf,&Len); // обрабатываем ответ StUdp.EthDataProcess(&Buf,&Len); // отправляем ответ Emac.TxData(Buf,Len); } } Хотя, если использовать наследование, то можно это все превратить в одну функцию. Занялся формированием концепции программирования. Вы сказали для неторопливых, оценивали ли вы размер кода, когда несколько объектов наследуют один и тот же базовый класс? Непонятен момент, как компилируются функции этого базового класса. Для каждого наследника они дублируются или компилятор это как-то оптимизирует?
Сообщение отредактировал Vitaliy_ARM - May 23 2008, 09:34
Прикрепленные файлы
isr.rar ( 919 байт )
Кол-во скачиваний: 28
--------------------
Умные речи подобны строкам, напечатанным курсивом. К. Прутков
|
|
|
|
|
May 23 2008, 11:27
|

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

|
Цитата(Vitaliy_ARM @ May 23 2008, 12:26)  Вы сказали для неторопливых, оценивали ли вы размер кода, когда несколько объектов наследуют один и тот же базовый класс? Непонятен момент, как компилируются функции этого базового класса. Для каждого наследника они дублируются или компилятор это как-то оптимизирует? Объект состоит только из данных. Когда вы обращаетесть к функции-члену, то компилятор по имени объекта определяет, какую именно из функций надо вызвать. Поэтому каждая (невстраиваимая) функция-член встречается в коде ровно один раз. Если это унаследованная функция для данного класса, то будет вызвана функция базового класса. Поэтому накладных расходов по коду при наследовании нет никаких. пример: Код class a_t: { public: void func_1() { data_a ++; } void func_2() { data_a --; } int data_a;
};
class b_t { public: void func_2() { data_b += 2; } int data_b; };
a_t a; /* в памяти имеем: a = struct a_t { int data_a; }; */
b_t b; /* в памяти имеем: b = struct { struct a_t { int data_a; }; int data_b; }; */
void test() { a.func_1();// вызывается a_t::func_1(this = &a), происходит a.data_a++; a.func_2();// вызывается a_t::func_2(this = &a), происходит a.data_a--; b.func_1();// вызывается a_t::func_1(this = &b), происходит b.data_a++; b.func_2();// вызывается b_t::func_2(this = &b), происходит b.data_b+=2; } Единственные накладные расходы, которые могут возникнуть - по памяти данных на архитектурах с выравниванием. Размер struct a_t будет округлен в бОльую сторону до параметра выравнивания (чтобы если из них сделать массив, следующий элемент оказался выровненным), и это округление может оставить пустое место между data_a и data_b в b.
--------------------
На любой вопрос даю любой ответ"Write code that is guaranteed to work, not code that doesn’t seem to break" ( C++ FAQ)
|
|
|
|
|
May 26 2008, 07:01
|
Знающий
   
Группа: Свой
Сообщений: 509
Регистрация: 19-07-07
Из: г. Таганрог
Пользователь №: 29 246

|
Цитата(Сергей Борщ @ May 23 2008, 15:27)  Объект состоит только из данных. Когда вы обращаетесть к функции-члену, то компилятор по имени объекта определяет, какую именно из функций надо вызвать. Поэтому каждая (невстраиваимая) функция-член встречается в коде ровно один раз. Если это унаследованная функция для данного класса, то будет вызвана функция базового класса. Поэтому накладных расходов по коду при наследовании нет никаких.
Единственные накладные расходы, которые могут возникнуть - по памяти данных на архитектурах с выравниванием. Размер struct a_t будет округлен в бОльую сторону до параметра выравнивания (чтобы если из них сделать массив, следующий элемент оказался выровненным), и это округление может оставить пустое место между data_a и data_b в b. Отлично. Получается можно использовать преимущества ОПП и при этом размер кода практически не увеличивается. Задам последний вопрос на отвлеченную тему: Если делать класс например для всех COM портов на контроллере LPC2468. При создании в конструкторе прописывать номер порта. При этом есть проблема, у каждого порта свои регистры. Думал как вариант: создать поля указателей на эти регистры. В конструкторе поставить switch и присваивать здесь этим указателям адреса соответствующих регистров, а в остальных функциях обращаться непосредственно к указателям. Достоинсва: быстродействие, недостатки: лишняя память на поля указателей. Вариант два: сделать в классе поле номера порта, так же инициализировать его в конструкторе. Потом в каждой функции ставить siwtch() и выбирать соответствующие регистры. Достоинсва: меньше памяти расходуется на поля, недостатки: меньше быстродействие. Можно ли обойтись (а нужно ли?) без операторов switch() при обращении к регистрам ввода/вывода, которые для каждого COM порта могут находиться в любом месте области памяти?
--------------------
Умные речи подобны строкам, напечатанным курсивом. К. Прутков
|
|
|
|
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|