реклама на сайте
подробности

 
 
> IAR 5.11, Объясните pls
Laurica
сообщение May 16 2008, 15:28
Сообщение #1





Группа: Новичок
Сообщений: 9
Регистрация: 17-04-08
Пользователь №: 36 836



Собственно проблема такая - примеры для AT91SAM7A3 компилятся, линкуются и тп. но!, при попытке прогнать их во встроенном симуляторе Cstartup.s с первой точки (reset) улетает куда-то на адрес 6E7C0000, при попытке переписать стартап чтобы он с ресета уходил на lowlevel_init в симуляторе все ОК, однако в железе - мертвяк. все во Flash_DEBUG
Go to the top of the page
 
+Quote Post
2 страниц V   1 2 >  
Start new topic
Ответов (1 - 24)
sKWO
сообщение May 17 2008, 05:41
Сообщение #2


Местный
***

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



Цитата(Laurica @ May 16 2008, 18:28) *
Собственно проблема такая - примеры для AT91SAM7A3 компилятся, линкуются и тп. но!, при попытке прогнать их во встроенном симуляторе Cstartup.s с первой точки (reset) улетает куда-то на адрес 6E7C0000, при попытке переписать стартап чтобы он с ресета уходил на lowlevel_init в симуляторе все ОК, однако в железе - мертвяк. все во Flash_DEBUG

Немного непонятно
А файл прошивки должен формироваться в режиме Реалис. Вы так его формировали?
И ещё, где-то было сообщение нащёт версии 5.11 толи В толи А что она вообще не рабочая.


--------------------
нельзя недооценивать предсказуемость глупости
Go to the top of the page
 
+Quote Post
Laurica
сообщение May 17 2008, 06:16
Сообщение #3





Группа: Новичок
Сообщений: 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, все-же хочется работать, а не бороться со средствами разработки... help.gif smile3046.gif
Go to the top of the page
 
+Quote Post
zltigo
сообщение May 17 2008, 06:31
Сообщение #4


Гуру
******

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



Цитата(sKWO @ May 17 2008, 07:41) *
И ещё, где-то было сообщение нащёт версии 5.11 толи В толи А что она вообще не рабочая.

- А это правда, что Сидоров выиграл машину в лотерею?
- Правда. Только не машину, а тысячу рублей. И не в лотерею, а в преферанс, и не выиграл, а проиграл...


Цитата(Laurica @ May 17 2008, 08:16) *
...все-же хочется работать, а не бороться со средствами разработки... help.gif smile3046.gif

Боритесь только сами с собой. Разработчики коммпилятров ошибаются несораизмеримо реже, нежели их пользователи smile.gif. тем более на переходе в main(). A EWARM 4.xx, Вы конечно взять можете на сайте iar.com, но незачем.


--------------------
Feci, quod potui, faciant meliora potentes
Go to the top of the page
 
+Quote Post
Laurica
сообщение May 17 2008, 10:53
Сообщение #5





Группа: Новичок
Сообщений: 9
Регистрация: 17-04-08
Пользователь №: 36 836



Цитата(zltigo @ May 17 2008, 10:31) *
Боритесь только сами с собой. Разработчики коммпилятров ошибаются несораизмеримо реже, нежели их пользователи smile.gif.

Да я не против бороться, я даже за twak.gif . Но чтобы бороться надо знатьхоть с чем конкретно. Кто нибудь знает где почитать как startup-ы пишуться в 5.11 с примерами/картинками smile.gif. На сайте IAR я посмотрю, но по-моему там уже везде ссылки на 5.10-5.11.
Go to the top of the page
 
+Quote Post
zltigo
сообщение May 17 2008, 14:27
Сообщение #6


Гуру
******

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



Цитата(Laurica @ May 17 2008, 12:53) *
с примерами/картинками smile.gif.

C картинками - это Вам тогда в детский сад надо пойти. А так - базовый вариант startup в комплекте поставки + документация на контроллер/ASM.


--------------------
Feci, quod potui, faciant meliora potentes
Go to the top of the page
 
+Quote Post
Laurica
сообщение May 17 2008, 17:02
Сообщение #7





Группа: Новичок
Сообщений: 9
Регистрация: 17-04-08
Пользователь №: 36 836



Цитата(zltigo @ May 17 2008, 18:27) *
C картинками - это Вам тогда в детский сад надо пойти.


Да староват вроде как для сада уже... Зря вы так, наглядный пример лучше трех талмудов.
Go to the top of the page
 
+Quote Post
zltigo
сообщение May 17 2008, 17:33
Сообщение #8


Гуру
******

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



Цитата(Laurica @ May 17 2008, 19:02) *
Зря вы так, наглядный пример лучше трех талмудов.

Повторяю:
Код
..базовый вариант startup в комплекте поставки..

Более, чем нагляден и достаточно универсален. Разве только без картинок smile.gif.


--------------------
Feci, quod potui, faciant meliora potentes
Go to the top of the page
 
+Quote Post
Laurica
сообщение May 17 2008, 18:55
Сообщение #9





Группа: Новичок
Сообщений: 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) то есть если выполнится первая такая команда, то мы окажемся там, где стрелочка в коде. Так?
Понимаю, что звучит по-дурацки, но... wacko.gif
Go to the top of the page
 
+Quote Post
alexander55
сообщение May 19 2008, 05:33
Сообщение #10


Бывалый
*****

Группа: Свой
Сообщений: 1 584
Регистрация: 7-08-07
Пользователь №: 29 615



Цитата(Laurica @ May 17 2008, 22:55) *
Код
ldr  pc,[pc,#+24]

происходит добавление к текущему адресу числа 24, (смещение на 6 dword) то есть если выполнится первая такая команда, то мы окажемся там, где стрелочка в коде. Так?
Понимаю, что звучит по-дурацки, но... wacko.gif

В счетчик команд заносится соответствующий хандлер, т.е. осуществляется переход на соответствующую метку .
Go to the top of the page
 
+Quote Post
Laurica
сообщение May 19 2008, 06:14
Сообщение #11





Группа: Новичок
Сообщений: 9
Регистрация: 17-04-08
Пользователь №: 36 836



Цитата(alexander55 @ May 19 2008, 09:33) *
В счетчик команд заносится соответствующий хандлер, т.е. осуществляется переход на соответствующую метку .

Это понятно, что обработчик заносится..., но меня интересует вопрос правильно ли я понимаю КАКОЙ обработчик туда заносится. Адресация-то относительная.
Go to the top of the page
 
+Quote Post
zltigo
сообщение May 19 2008, 06:23
Сообщение #12


Гуру
******

Группа: Свой
Сообщений: 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
Go to the top of the page
 
+Quote Post
Laurica
сообщение May 19 2008, 06:46
Сообщение #13





Группа: Новичок
Сообщений: 9
Регистрация: 17-04-08
Пользователь №: 36 836



За пример - большое спасибо, так и вправду понятнее. Однако, касаемо моей изначальной проблеммы - а именно не_запускания программы в железе - наткнулся на то, что если workspace поставить flash_flash (а не flash_debug), то все несколько меняется. При компиляции во flash_debug при переходе с "0" адреса происходит улет в 0x6E7C (а там вакуум...и не работает не в железе ни в симуляторе), в RAM_debug 0x7B50, а в flash_flash туда же в 0x6E7C, при этом все работает в симуляторе, но в железе глухо как в танке... При этом код не меняелся никак.
Доктор, где у меня ошибка..? crying.gif

Сообщение отредактировал Laurica - May 19 2008, 06:58
Go to the top of the page
 
+Quote Post
Vitaliy_ARM
сообщение May 20 2008, 09:03
Сообщение #14


Знающий
****

Группа: Свой
Сообщений: 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. Может чего упустил?


--------------------
Умные речи подобны строкам, напечатанным курсивом. К. Прутков
Go to the top of the page
 
+Quote Post
Сергей Борщ
сообщение May 20 2008, 09:44
Сообщение #15


Гуру
******

Группа: Модераторы
Сообщений: 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)
Go to the top of the page
 
+Quote Post
Vitaliy_ARM
сообщение May 20 2008, 10:01
Сообщение #16


Знающий
****

Группа: Свой
Сообщений: 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


Спасибо!!! Второй вариант заработал.
a14.gif


--------------------
Умные речи подобны строкам, напечатанным курсивом. К. Прутков
Go to the top of the page
 
+Quote Post
Vitaliy_ARM
сообщение May 22 2008, 08:07
Сообщение #17


Знающий
****

Группа: Свой
Сообщений: 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*")

Это вообще возможно или я в трех соснах блуждаю?


--------------------
Умные речи подобны строкам, напечатанным курсивом. К. Прутков
Go to the top of the page
 
+Quote Post
Сергей Борщ
сообщение May 22 2008, 08:40
Сообщение #18


Гуру
******

Группа: Модераторы
Сообщений: 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)
Go to the top of the page
 
+Quote Post
Vitaliy_ARM
сообщение May 22 2008, 14:29
Сообщение #19


Знающий
****

Группа: Свой
Сообщений: 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


--------------------
Умные речи подобны строкам, напечатанным курсивом. К. Прутков
Go to the top of the page
 
+Quote Post
Сергей Борщ
сообщение May 22 2008, 18:18
Сообщение #20


Гуру
******

Группа: Модераторы
Сообщений: 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;
}
Хм, а интересная мысль. Надо взять ее на заметку для небольших неторопливых безОСевых приложений типа загрузчиков. smile.gif


--------------------
На любой вопрос даю любой ответ
"Write code that is guaranteed to work, not code that doesn’t seem to break" (C++ FAQ)
Go to the top of the page
 
+Quote Post
Vitaliy_ARM
сообщение May 23 2008, 09:26
Сообщение #21


Знающий
****

Группа: Свой
Сообщений: 509
Регистрация: 19-07-07
Из: г. Таганрог
Пользователь №: 29 246



Цитата(Сергей Борщ @ May 22 2008, 22:18) *
Хм, а интересная мысль. Надо взять ее на заметку для небольших неторопливых безОСевых приложений типа загрузчиков. smile.gif

Сложно. Получается, что с оберткой по-проще. Уже делал что-то подобное (прикрепил один из вариантов оберток).

Еще пока не использовал наследование, пользовался подобными конструкциями:
Код
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
 


--------------------
Умные речи подобны строкам, напечатанным курсивом. К. Прутков
Go to the top of the page
 
+Quote Post
Сергей Борщ
сообщение May 23 2008, 11:27
Сообщение #22


Гуру
******

Группа: Модераторы
Сообщений: 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)
Go to the top of the page
 
+Quote Post
Vitaliy_ARM
сообщение May 26 2008, 07:01
Сообщение #23


Знающий
****

Группа: Свой
Сообщений: 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 порта могут находиться в любом месте области памяти?


--------------------
Умные речи подобны строкам, напечатанным курсивом. К. Прутков
Go to the top of the page
 
+Quote Post
Сергей Борщ
сообщение May 26 2008, 08:45
Сообщение #24


Гуру
******

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



Цитата(Vitaliy_ARM @ May 26 2008, 10:01) *
Вариант два: сделать в классе поле номера порта, так же инициализировать его в конструкторе. Потом в каждой функции ставить siwtch() и выбирать соответствующие регистры. Достоинсва: меньше памяти расходуется на поля, недостатки: меньше быстродействие.
Насколько я помню, там все порты примерно одинаоквы. Все их регистры можно описать одной структурой. Так почему бы указатель на эту структуру и не передавать конструктору?


--------------------
На любой вопрос даю любой ответ
"Write code that is guaranteed to work, not code that doesn’t seem to break" (C++ FAQ)
Go to the top of the page
 
+Quote Post
Vitaliy_ARM
сообщение May 26 2008, 09:20
Сообщение #25


Знающий
****

Группа: Свой
Сообщений: 509
Регистрация: 19-07-07
Из: г. Таганрог
Пользователь №: 29 246



Цитата(Сергей Борщ @ May 26 2008, 12:45) *
Насколько я помню, там все порты примерно одинаоквы. Все их регистры можно описать одной структурой. Так почему бы указатель на эту структуру и не передавать конструктору?


a14.gif Точно! Как я сразу не догадался. Спасибо за ответы


--------------------
Умные речи подобны строкам, напечатанным курсивом. К. Прутков
Go to the top of the page
 
+Quote Post

2 страниц V   1 2 >
Reply to this topicStart new topic
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 


RSS Текстовая версия Сейчас: 27th July 2025 - 23:59
Рейтинг@Mail.ru


Страница сгенерированна за 0.01656 секунд с 7
ELECTRONIX ©2004-2016