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

|
Собственно проблема такая - примеры для AT91SAM7A3 компилятся, линкуются и тп. но!, при попытке прогнать их во встроенном симуляторе Cstartup.s с первой точки (reset) улетает куда-то на адрес 6E7C0000, при попытке переписать стартап чтобы он с ресета уходил на lowlevel_init в симуляторе все ОК, однако в железе - мертвяк. все во Flash_DEBUG
|
|
|
|
|
 |
Ответов
|
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)
|
|
|
|
Сообщений в этой теме
Laurica IAR 5.11 May 16 2008, 15:28 sKWO Цитата(Laurica @ May 16 2008, 18:28) Собс... May 17 2008, 05:41 Laurica Цитата(sKWO @ May 17 2008, 09:41) Немного... May 17 2008, 06:16 zltigo Цитата(sKWO @ May 17 2008, 07:41) И ещё, ... May 17 2008, 06:31  Laurica Цитата(zltigo @ May 17 2008, 10:31) Борит... May 17 2008, 10:53   zltigo Цитата(Laurica @ May 17 2008, 12:53) с пр... May 17 2008, 14:27    Laurica Цитата(zltigo @ May 17 2008, 18:27) C кар... May 17 2008, 17:02     zltigo Цитата(Laurica @ May 17 2008, 19:02) Зря ... May 17 2008, 17:33      Laurica Обратился к первоисточнику:
Код ARM
__vector... May 17 2008, 18:55       alexander55 Цитата(Laurica @ May 17 2008, 22:55) Кодl... May 19 2008, 05:33        Laurica Цитата(alexander55 @ May 19 2008, 09:33) ... May 19 2008, 06:14       zltigo Цитата(Laurica @ May 17 2008, 20:55) если... May 19 2008, 06:23        Laurica За пример - большое спасибо, так и вправду понятне... May 19 2008, 06:46 Vitaliy_ARM Столкнулся с такой проблемой.
Не могу в этом IAR ... May 20 2008, 09:03 Сергей Борщ Цитата(Vitaliy_ARM @ May 20 2008, 12:03) ... May 20 2008, 09:44  Vitaliy_ARM Цитата(Сергей Борщ @ May 20 2008, 13:44) ... May 20 2008, 10:01      Vitaliy_ARM Цитата(Сергей Борщ @ May 23 2008, 15:27) ... May 26 2008, 07:01       Сергей Борщ Цитата(Vitaliy_ARM @ May 26 2008, 10:01) ... May 26 2008, 08:45        Vitaliy_ARM Цитата(Сергей Борщ @ May 26 2008, 12:45) ... May 26 2008, 09:20
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|