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

 
 
3 страниц V   1 2 3 >  
Reply to this topicStart new topic
> С++, обработчик прерывания как статическая ф-я класса.
AHTOXA
сообщение Dec 4 2008, 09:35
Сообщение #1


фанат дивана
******

Группа: Свой
Сообщений: 3 387
Регистрация: 9-08-07
Из: Уфа
Пользователь №: 29 684



Пытаюсь запихать. Запихал:
Код
class    TUart1 : public TCustomUart
{
    public:
        TUart1(uint32_t baudrate) {hw_init(baudrate);}
    protected:
        ...
        virtual void hw_init(uint32_t baudrate);
        virtual void write_tx_reg(char ch) { TXBUF0 = ch; }
        static interrupt(UART0RX_VECTOR) usart0_rx(void);
        static interrupt(UART0TX_VECTOR) usart0_tx(void);
};

...

interrupt(UART0TX_VECTOR) TUart1::usart0_tx(void)
{
    OS::TISRW ISR;
    char ch;
    if (Uart1.TxChannel.get_count())
    {
        Uart1.TxChannel.pop(ch);
        TXBUF0 = ch;
    }
    else
    {
        Uart1.tx_active = false;
    }
}


Делаю это для того, чтобы в прерывании обращаться к private-членам класса. Вроде всё получается. Единственное неудобство состоит в том, что пока я не напишу где-нибудь
Код
void TUart1::hw_init(uint32_t baudrate)
{
    typedef void (* Handler)(void);
    volatile Handler ptr;
    ...
    ptr = &usart0_rx;
    ptr = &usart0_tx;
}

, обработчики прерываний не линкуются. Может есть какой-то более цивильный способ?

Ну и вообще, хотелось бы не статическую функцию, а просто функцию классаsmile.gif

ЗЫ. msp-gcc.


--------------------
Если бы я знал, что такое электричество...
Go to the top of the page
 
+Quote Post
Legotron
сообщение Dec 4 2008, 09:45
Сообщение #2


инопланетянин
***

Группа: Свой
Сообщений: 236
Регистрация: 24-12-06
Из: Питер
Пользователь №: 23 832



Цитата(AHTOXA @ Dec 4 2008, 12:35) *
ptr = &usart0_rx;
ptr = &usart0_tx;

А разве здесь нужен знак "&"?
По-моему, название функции является указателем, как с массивами...

По-поводу проблемы: а будет линковаться, если описать тела функций обработчиков внутри класса, не проверяли?
Go to the top of the page
 
+Quote Post
xelax
сообщение Dec 4 2008, 09:56
Сообщение #3


Местный
***

Группа: Свой
Сообщений: 370
Регистрация: 7-11-06
Пользователь №: 22 035



Цитата(AHTOXA @ Dec 4 2008, 12:35) *
Ну и вообще, хотелось бы не статическую функцию, а просто функцию классаsmile.gif


В нестатичные членах класса всегда передаётся указатель на объект, который их вызвал.
Если сделать прерывания нестатичными, то как и куда им будет передаваться этот указатель??? 07.gif
Go to the top of the page
 
+Quote Post
AHTOXA
сообщение Dec 4 2008, 10:09
Сообщение #4


фанат дивана
******

Группа: Свой
Сообщений: 3 387
Регистрация: 9-08-07
Из: Уфа
Пользователь №: 29 684



Цитата(Legotron @ Dec 4 2008, 14:45) *
А разве здесь нужен знак "&"?
По-моему, название функции является указателем, как с массивами...

Да тут без разницы, нужно просто обращение...
Цитата
По-поводу проблемы: а будет линковаться, если описать тела функций обработчиков внутри класса, не проверяли?

Не, не помогает.


--------------------
Если бы я знал, что такое электричество...
Go to the top of the page
 
+Quote Post
Сергей Борщ
сообщение Dec 4 2008, 10:11
Сообщение #5


Гуру
******

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



Цитата(AHTOXA @ Dec 4 2008, 11:35) *
Единственное неудобство состоит в том, что пока я не напишу где-нибудь
Код
    ptr = &usart0_rx;
    ptr = &usart0_tx;
}
Фигня какая-то...
Код
class adc_t
{
public:
    typedef uint16_t sample_t;
    static sample_t const MAX_VALUE = 4096;

    template<adc_channel_t channel>
    INLINE inline static sample_t digital();   // adc raw value
    template<adc_channel_t channel>
    INLINE inline static float analog();        // adc result converted to analog
........
private:
    static OS_INTERRUPT void IntHandler();

    static OS::TMutex Locker;
    static OS::TEventFlag Ready;
};


OS_INTERRUPT interrupt(ADC12_VECTOR) adc_t::IntHandler()
{
    OS::TISRW ISRWrapper;
    ADC12IV;
    Ready.SignalISR();
    Locker.UnlockISR();
    ADC12IE = 0;
}
Все линкуется...


--------------------
На любой вопрос даю любой ответ
"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
AHTOXA
сообщение Dec 4 2008, 10:29
Сообщение #6


фанат дивана
******

Группа: Свой
Сообщений: 3 387
Регистрация: 9-08-07
Из: Уфа
Пользователь №: 29 684



Цитата(Сергей Борщ @ Dec 4 2008, 15:11) *
Фигня какая-то...


Не то словоsmile.gif Похоже мне попалась какая-то неудачная сборка mspgcc:)


--------------------
Если бы я знал, что такое электричество...
Go to the top of the page
 
+Quote Post
Сергей Борщ
сообщение Dec 4 2008, 12:09
Сообщение #7


Гуру
******

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



Цитата(AHTOXA @ Dec 4 2008, 12:29) *
Не то словоsmile.gif Похоже мне попалась какая-то неудачная сборка mspgcc:)
Возможно. Могу выслать свою или собери из cvs.
Я тут немного подумал, и пришел к выводу, что в исходном коде есть концептуальная ошибка: UARTов может быть несколько и вшивать конкретный вектор в класс неправильно. Там должен быть inline обработчик, который вызывается из реального обработчика. А реальный обработчик будет знать, с каким объектом вызывать. Примерно так:

Код
class uart_t
{
public:
    inline INLINE void init(uint32_t const divider);
    inline INLINE bool hasinput() { return Rx.Buffer.has_data(); }
    bool get(uint8_t &data, timeout_t timeout = 0);
    void put(uint8_t data);
private:
....
    friend void UART0_RxHandler();
    friend void UART0_TxHandler();
    friend void UART1_RxHandler();
    friend void UART1_TxHandler();

    inline INLINE void RxHandler();
    inline INLINE void TxHandler();
};

OS_INTERRUPT interrupt(USCIAB0RX_VECTOR) UART0_RxHandler()
{
    OS::TISRW ISRW;
    UART0.RxHandler();
}

OS_INTERRUPT interrupt(USCIAB0TX_VECTOR) UART0_TxHandler()
{
    OS::TISRW ISRW;
    UART0.TxHandler();
}

OS_INTERRUPT interrupt(USCIAB1RX_VECTOR) UART1_RxHandler()
{
    OS::TISRW ISRW;
    UART1.RxHandler();
}

OS_INTERRUPT interrupt(USCIAB1TX_VECTOR) UART1_TxHandler()
{
    OS::TISRW ISRW;
    UART1.TxHandler();
}


--------------------
На любой вопрос даю любой ответ
"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
AHTOXA
сообщение Dec 4 2008, 12:19
Сообщение #8


фанат дивана
******

Группа: Свой
Сообщений: 3 387
Регистрация: 9-08-07
Из: Уфа
Пользователь №: 29 684



Цитата(Сергей Борщ @ Dec 4 2008, 17:09) *
Возможно. Могу выслать свою или собери из cvs.

Вышлите пожалуйста, собирать пока не готовsmile.gif
Цитата
UARTов может быть несколько и вшивать конкретный вектор в класс неправильно.

Я немного с другой стороны подхожу. У меня есть базовый TCustomUart, с pure virtual ф-ями доступа к аппаратуре. И от него наследники для каждого физического UARTа, с реализациями этих функций и со статическими обработчиками прерываний.
Цитата
Там должен быть inline обработчик, который вызывается из реального обработчика. А реальный обработчик будет знать, с каким объектом вызывать.

Можно и так, надо будет обмозговатьsmile.gif

Вот кстати тестовый проектик:
Прикрепленный файл  problem.rar ( 50.53 килобайт ) Кол-во скачиваний: 151


--------------------
Если бы я знал, что такое электричество...
Go to the top of the page
 
+Quote Post
dxp
сообщение Dec 4 2008, 12:49
Сообщение #9


Adept
******

Группа: Свой
Сообщений: 3 469
Регистрация: 6-12-04
Из: Novosibirsk
Пользователь №: 1 343



Цитата(AHTOXA @ Dec 4 2008, 15:35) *
Ну и вообще, хотелось бы не статическую функцию, а просто функцию классаsmile.gif

Этого нельзя. Обработчик прерывания не может быть нестатической функцией-членом класса. При вызове нестатической функции-члена ей всегда неявно передается указатель this (понятно для чего smile.gif ), что легко реализуется при обычном вызове, т.е. когда код выполняется "синхронно". А прерывание - это асинхронное событие, программа (компилятор, процессор) "не знает", когда оно произойдет (и не может знать), поэтому вызов функции с передачей this практически нереализуем - какой this передавать? Ведь нестатическая функция-член всегда вызвается для конкретного экземляра класса (объекта), его адрес четко известен в точке вызова. Чего нельзя сказать про случай с прерыванием - для какого объекта делается вызов?

Поэтому обработчик прерывания - это обычная функция. Либо статическая функция-член класса, которая отличается от обычной только правами доступа к закрытым членам класса и областью видимости (scope). Все, других отличий нет. Именно поэтому чтобы из статической функции-члена класса добраться до представления (потрохов) конкретного объекта, обязательно надо явно сообщать адрес этого конкретного объекта.


--------------------
«Отыщи всему начало, и ты многое поймёшь» К. Прутков
Go to the top of the page
 
+Quote Post
AHTOXA
сообщение Dec 4 2008, 14:22
Сообщение #10


фанат дивана
******

Группа: Свой
Сообщений: 3 387
Регистрация: 9-08-07
Из: Уфа
Пользователь №: 29 684



Цитата(dxp @ Dec 4 2008, 17:49) *
Этого нельзя.


Да это понятноsmile.gif Я так, на всякий случай, вдруг наука что-то придумала, а я не в курсе biggrin.gif


--------------------
Если бы я знал, что такое электричество...
Go to the top of the page
 
+Quote Post
AHTOXA
сообщение Dec 4 2008, 15:35
Сообщение #11


фанат дивана
******

Группа: Свой
Сообщений: 3 387
Регистрация: 9-08-07
Из: Уфа
Пользователь №: 29 684



Короче, разобрался я, в чём причина. Всё дело в шаблонахsmile.gif
Базовый класс у меня объявлен как шаблон:
Код
template<uint16_t rx_buf_size, uint16_t tx_buf_size>
class    TCustomUart
{
    public:
        TCustomUart() : RxChannel(), TxChannel(), tx_active(false) { }

        void    putchar(char ch);
        void    puts(char * ch);
        char    getchar(void);
        ...
    protected:
        OS::channel<char, rx_buf_size> RxChannel;
        OS::channel<char, tx_buf_size> TxChannel;

        virtual void disable_tx_interrupt(void) = 0;
        virtual void enable_tx_interrupt(void) = 0;
        virtual void write_tx_reg(char ch) = 0;
        ...
};


соответственно, класс uart1:
Код
template<uint16_t rx_buf_size, uint16_t tx_buf_size>
class    TUart1 : public TCustomUart<rx_buf_size, tx_buf_size>
{
        ...
        static OS_INTERRUPT void usart0_rx(void);
        static OS_INTERRUPT void usart0_tx(void);
};

- тоже шаблон.
Убрав шаблоны, получил нормальную линковку обработчиков прерываний.
Видимо, это так работает механизм шаблонирования - всё, что не вызывается, то не инстанцируется?


--------------------
Если бы я знал, что такое электричество...
Go to the top of the page
 
+Quote Post
vik0
сообщение Dec 4 2008, 19:25
Сообщение #12


Местный
***

Группа: Свой
Сообщений: 381
Регистрация: 27-07-08
Из: теплые края
Пользователь №: 39 233



Цитата(AHTOXA @ Dec 4 2008, 17:35) *
Видимо, это так работает механизм шаблонирования - всё, что не вызывается, то не инстанцируется?

Именно.
Можете попробовать явное инстанцирование (explicit instantiation):
Код
// в синтаксисе возможны ошибки - сейчас точный синтаксис не вспомню  :(
template void TUart1<конкретные значения параметров шаблона>::usart0_rx(void);
Go to the top of the page
 
+Quote Post
AHTOXA
сообщение Dec 4 2008, 21:20
Сообщение #13


фанат дивана
******

Группа: Свой
Сообщений: 3 387
Регистрация: 9-08-07
Из: Уфа
Пользователь №: 29 684



Цитата(vik0 @ Dec 5 2008, 00:25) *
Можете попробовать явное инстанцирование (explicit instantiation):


То, что нужно, спасибо!


--------------------
Если бы я знал, что такое электричество...
Go to the top of the page
 
+Quote Post
Vitaliy_ARM
сообщение Dec 6 2008, 12:00
Сообщение #14


Знающий
****

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



Цитата(AHTOXA @ Dec 5 2008, 00:20) *
То, что нужно, спасибо!


А можно конечный кусок кода увидеть


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


Гуру
******

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



Цитата(Vitaliy_ARM @ Dec 6 2008, 14:00) *
А можно конечный кусок кода увидеть
Код
template  void TUart1<размер1, размер2>::usart0_rx();
template  void TUart1<размер1, размер2>::usart0_tx();
Страуструп, конец прилдожения 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

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

 


RSS Текстовая версия Сейчас: 22nd July 2025 - 00:05
Рейтинг@Mail.ru


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