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

 
 
> 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
 
Start new topic
Ответов
Vitaliy_ARM
сообщение May 22 2008, 08:07
Сообщение #2


Знающий
****

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


Гуру
******

Группа: Модераторы
Сообщений: 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
Сообщение #4


Знающий
****

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


Гуру
******

Группа: Модераторы
Сообщений: 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
Сообщение #6


Знающий
****

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


Гуру
******

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

Сообщений в этой теме
- 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


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

 


RSS Текстовая версия Сейчас: 21st July 2025 - 11:15
Рейтинг@Mail.ru


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