AHTOXA 18 4 декабря, 2008 Опубликовано 4 декабря, 2008 · Жалоба Пытаюсь запихать. Запихал: 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; } , обработчики прерываний не линкуются. Может есть какой-то более цивильный способ? Ну и вообще, хотелось бы не статическую функцию, а просто функцию класса:) ЗЫ. msp-gcc. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
legotron 0 4 декабря, 2008 Опубликовано 4 декабря, 2008 · Жалоба ptr = &usart0_rx; ptr = &usart0_tx; А разве здесь нужен знак "&"? По-моему, название функции является указателем, как с массивами... По-поводу проблемы: а будет линковаться, если описать тела функций обработчиков внутри класса, не проверяли? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
xelax 0 4 декабря, 2008 Опубликовано 4 декабря, 2008 · Жалоба Ну и вообще, хотелось бы не статическую функцию, а просто функцию класса:) В нестатичные членах класса всегда передаётся указатель на объект, который их вызвал. Если сделать прерывания нестатичными, то как и куда им будет передаваться этот указатель??? :07: Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
AHTOXA 18 4 декабря, 2008 Опубликовано 4 декабря, 2008 · Жалоба А разве здесь нужен знак "&"? По-моему, название функции является указателем, как с массивами... Да тут без разницы, нужно просто обращение... По-поводу проблемы: а будет линковаться, если описать тела функций обработчиков внутри класса, не проверяли? Не, не помогает. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Сергей Борщ 134 4 декабря, 2008 Опубликовано 4 декабря, 2008 · Жалоба Единственное неудобство состоит в том, что пока я не напишу где-нибудь 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; } Все линкуется... Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
AHTOXA 18 4 декабря, 2008 Опубликовано 4 декабря, 2008 · Жалоба Фигня какая-то... Не то слово:) Похоже мне попалась какая-то неудачная сборка mspgcc:) Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Сергей Борщ 134 4 декабря, 2008 Опубликовано 4 декабря, 2008 · Жалоба Не то слово:) Похоже мне попалась какая-то неудачная сборка 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(); } Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
AHTOXA 18 4 декабря, 2008 Опубликовано 4 декабря, 2008 · Жалоба Возможно. Могу выслать свою или собери из cvs. Вышлите пожалуйста, собирать пока не готов:) UARTов может быть несколько и вшивать конкретный вектор в класс неправильно. Я немного с другой стороны подхожу. У меня есть базовый TCustomUart, с pure virtual ф-ями доступа к аппаратуре. И от него наследники для каждого физического UARTа, с реализациями этих функций и со статическими обработчиками прерываний. Там должен быть inline обработчик, который вызывается из реального обработчика. А реальный обработчик будет знать, с каким объектом вызывать. Можно и так, надо будет обмозговать:) Вот кстати тестовый проектик: problem.rar Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
dxp 58 4 декабря, 2008 Опубликовано 4 декабря, 2008 · Жалоба Ну и вообще, хотелось бы не статическую функцию, а просто функцию класса:) Этого нельзя. Обработчик прерывания не может быть нестатической функцией-членом класса. При вызове нестатической функции-члена ей всегда неявно передается указатель this (понятно для чего :) ), что легко реализуется при обычном вызове, т.е. когда код выполняется "синхронно". А прерывание - это асинхронное событие, программа (компилятор, процессор) "не знает", когда оно произойдет (и не может знать), поэтому вызов функции с передачей this практически нереализуем - какой this передавать? Ведь нестатическая функция-член всегда вызвается для конкретного экземляра класса (объекта), его адрес четко известен в точке вызова. Чего нельзя сказать про случай с прерыванием - для какого объекта делается вызов? Поэтому обработчик прерывания - это обычная функция. Либо статическая функция-член класса, которая отличается от обычной только правами доступа к закрытым членам класса и областью видимости (scope). Все, других отличий нет. Именно поэтому чтобы из статической функции-члена класса добраться до представления (потрохов) конкретного объекта, обязательно надо явно сообщать адрес этого конкретного объекта. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
AHTOXA 18 4 декабря, 2008 Опубликовано 4 декабря, 2008 · Жалоба Этого нельзя. Да это понятно:) Я так, на всякий случай, вдруг наука что-то придумала, а я не в курсе Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
AHTOXA 18 4 декабря, 2008 Опубликовано 4 декабря, 2008 · Жалоба Короче, разобрался я, в чём причина. Всё дело в шаблонах:) Базовый класс у меня объявлен как шаблон: 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); }; - тоже шаблон. Убрав шаблоны, получил нормальную линковку обработчиков прерываний. Видимо, это так работает механизм шаблонирования - всё, что не вызывается, то не инстанцируется? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
vik0 0 4 декабря, 2008 Опубликовано 4 декабря, 2008 · Жалоба Видимо, это так работает механизм шаблонирования - всё, что не вызывается, то не инстанцируется? Именно. Можете попробовать явное инстанцирование (explicit instantiation): // в синтаксисе возможны ошибки - сейчас точный синтаксис не вспомню :( template void TUart1<конкретные значения параметров шаблона>::usart0_rx(void); Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
AHTOXA 18 4 декабря, 2008 Опубликовано 4 декабря, 2008 · Жалоба Можете попробовать явное инстанцирование (explicit instantiation): То, что нужно, спасибо! Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Vitaliy_ARM 0 6 декабря, 2008 Опубликовано 6 декабря, 2008 · Жалоба То, что нужно, спасибо! А можно конечный кусок кода увидеть Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Сергей Борщ 134 6 декабря, 2008 Опубликовано 6 декабря, 2008 · Жалоба А можно конечный кусок кода увидеть template void TUart1<размер1, размер2>::usart0_rx(); template void TUart1<размер1, размер2>::usart0_tx(); Страуструп, конец прилдожения B, явное инстанцирование. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться