WinAVR, c++ и прерывания
- apwork
- Первый раз сказал Мяу!
- Сообщения: 21
- Зарегистрирован: Ср май 11, 2011 12:24:54
- Откуда: Лисичанск
WinAVR, c++ и прерывания
Подскажите как прикрутить обработчик прерывания к классу c++.
Компилятор - avr-gcc из WinAVR.
Компилятор - avr-gcc из WinAVR.
- avreal
- Опытный кот
- Сообщения: 842
- Зарегистрирован: Чт дек 31, 2009 19:27:45
- Откуда: Бровари, Україна
- Контактная информация:
Re: WinAVR, c++ и прерывания
Обработчик прерывания в любом случае должен быть статической функцией (если это функция класса), так как некому ему передать this.
У avr-gcc проблема в декораци имён функций классов в С++ и в способе задания обработчиков с фиксироанными именами __vector_NUMBER. Что-то пробовали сделать, чтобы можно было обработчик в классе делать, но, вроде бы, в релизах это так и не работает.
Надёжно -- только как дружественную фцнкцию. Тогда она и будет статическая и с нужными атрибутами и именем, а «классовый» обработчик может уже быть каким нужно.
У avr-gcc проблема в декораци имён функций классов в С++ и в способе задания обработчиков с фиксироанными именами __vector_NUMBER. Что-то пробовали сделать, чтобы можно было обработчик в классе делать, но, вроде бы, в релизах это так и не работает.
Надёжно -- только как дружественную фцнкцию. Тогда она и будет статическая и с нужными атрибутами и именем, а «классовый» обработчик может уже быть каким нужно.
Код: Выделить всё
#include <avr/interrupt.h>
ISR(TIMER0_OVF_vect);
class Foo {
...
private:
friend void TIMER0_OVF_vect();
inline void Isr();
uint8_t cnt;
};
Foo foo;
void Foo::Isr() { ++cnt; }
void TIMER0_OVF_vect()
{
foo.Isr();
}Лень в виде мании величия: «ты гений, зачем стараться?». В виде комплекса: «всё равно не выйдет, зачем упираться?». Как логика: «если достаточно, зачем знать и уметь больше?». Цель одна: остановить. Не любит тепло работающих мышц и шум работающего мозга.
- apwork
- Первый раз сказал Мяу!
- Сообщения: 21
- Зарегистрирован: Ср май 11, 2011 12:24:54
- Откуда: Лисичанск
Re: WinAVR, c++ и прерывания
Спасибо за информацию. Буду пробовать. Хотя со статичной функцией класса было бы интереснее.
-
Мастер Ломастер
- Поставщик валерьянки для Кота
- Сообщения: 1995
- Зарегистрирован: Ср май 11, 2011 21:37:45
- Откуда: Цветочный город
- Контактная информация:
Re: WinAVR, c++ и прерывания
а в чем смысл впихивания обработчика в класс?
битва с дураками проиграна, победители торжествуют. слава победителям!
- avreal
- Опытный кот
- Сообщения: 842
- Зарегистрирован: Чт дек 31, 2009 19:27:45
- Откуда: Бровари, Україна
- Контактная информация:
Re: WinAVR, c++ и прерывания
На avrfreaks поищите C++ interrupt, там несколько тем было год-два назад.apwork писал(а):Спасибо за информацию. Буду пробовать. Хотя со статичной функцией класса было бы интереснее.
Что-то я пробовал, но у меня толи не пошло, толи выглядело не ровнее дружественных функций.
Если нароете что-то свежее-рабочее, отпишитесь тут
Последний раз редактировалось avreal Чт май 12, 2011 10:33:03, всего редактировалось 1 раз.
Лень в виде мании величия: «ты гений, зачем стараться?». В виде комплекса: «всё равно не выйдет, зачем упираться?». Как логика: «если достаточно, зачем знать и уметь больше?». Цель одна: остановить. Не любит тепло работающих мышц и шум работающего мозга.
- avreal
- Опытный кот
- Сообщения: 842
- Зарегистрирован: Чт дек 31, 2009 19:27:45
- Откуда: Бровари, Україна
- Контактная информация:
Re: WinAVR, c++ и прерывания
В том же в чём и впихивание всего остального -- «приватизация» того, что не должно быть видно снаружи при сохранении быстрого доступа, некоторое разделение интерфейса и реализации, ...Мастер Ломастер писал(а):а в чем смысл впихивания обработчика в класс?
Лень в виде мании величия: «ты гений, зачем стараться?». В виде комплекса: «всё равно не выйдет, зачем упираться?». Как логика: «если достаточно, зачем знать и уметь больше?». Цель одна: остановить. Не любит тепло работающих мышц и шум работающего мозга.
-
Мастер Ломастер
- Поставщик валерьянки для Кота
- Сообщения: 1995
- Зарегистрирован: Ср май 11, 2011 21:37:45
- Откуда: Цветочный город
- Контактная информация:
Re: WinAVR, c++ и прерывания
разделение - самоцель? всегда считал, что ООП имеет цель упрощение построения сложных проектов, в которых одновременное существование нескольких экземпляров одного и того же класса является непременным условием... или проект состоит из хитрой иерархии классов для обеспечения некоей "стройности" кода...
существование двух экземпляров класса со встроенными обработчиками одного и того же прерывания в AVR я не представляю... выглядит это, как костыли... стройности программе тоже вряд ли прибавляет...
получается, смысл только в загонянии части переменных под private ? оно того на самом деле стоит?
существование двух экземпляров класса со встроенными обработчиками одного и того же прерывания в AVR я не представляю... выглядит это, как костыли... стройности программе тоже вряд ли прибавляет...
получается, смысл только в загонянии части переменных под private ? оно того на самом деле стоит?
битва с дураками проиграна, победители торжествуют. слава победителям!
- avreal
- Опытный кот
- Сообщения: 842
- Зарегистрирован: Чт дек 31, 2009 19:27:45
- Откуда: Бровари, Україна
- Контактная информация:
Re: WinAVR, c++ и прерывания
А в С -- если какой-то модуль выделяется в отдельный файл со спрятанными там (через static) переменными и функциями внутреннего употребления -- тоже «непременным условием» будет применение в программе двух экземпляров этого модуля? Иначе программа «нестройная», выделение модуля было «самоцелью» ?
На мой взгляд, класс, от которого в программе существует в принципе единственный экземпляр -- вполне нормальное явление.
Кроме того, эти классы могут быть потомками одного родителя и каждый из них имеет свой обработчик прерывания. В программе есть по единственному объекту каждого из них, но с точки зрения остальной части программы это несколько одинаковых объектов базового для них всех типа.
У меня сейчас в меге64 подобным образом работает 5-канальный приёмник пакетов (односторонняя передача, эта штука только принимает, анализирует и в UART на комп). Впрочем, там вместе с float-статистикой, fprintf, кучей текстовых строк -- килов 7 кода. Было бы у меги168 нужное количество COMPARE, в ней бы и было сделано. Да и платки с мегой64 завалялись.
Каждый канал - единственный экземпляр «себя» с двумя собственными обработчиками прерываний (внешнее прерывание и таймерное COMPARE). Но все одни -- потомки общего PaсketReceiver и уровнем выше все думают, что вот в этом массиве -- указатели именно на задействованные PacketReceiver, а не на те, нарушающие «непременное условие», единственные экземпляры производных классов.
На мой взгляд, класс, от которого в программе существует в принципе единственный экземпляр -- вполне нормальное явление.
Кроме того, эти классы могут быть потомками одного родителя и каждый из них имеет свой обработчик прерывания. В программе есть по единственному объекту каждого из них, но с точки зрения остальной части программы это несколько одинаковых объектов базового для них всех типа.
У меня сейчас в меге64 подобным образом работает 5-канальный приёмник пакетов (односторонняя передача, эта штука только принимает, анализирует и в UART на комп). Впрочем, там вместе с float-статистикой, fprintf, кучей текстовых строк -- килов 7 кода. Было бы у меги168 нужное количество COMPARE, в ней бы и было сделано. Да и платки с мегой64 завалялись.
Каждый канал - единственный экземпляр «себя» с двумя собственными обработчиками прерываний (внешнее прерывание и таймерное COMPARE). Но все одни -- потомки общего PaсketReceiver и уровнем выше все думают, что вот в этом массиве -- указатели именно на задействованные PacketReceiver, а не на те, нарушающие «непременное условие», единственные экземпляры производных классов.
Лень в виде мании величия: «ты гений, зачем стараться?». В виде комплекса: «всё равно не выйдет, зачем упираться?». Как логика: «если достаточно, зачем знать и уметь больше?». Цель одна: остановить. Не любит тепло работающих мышц и шум работающего мозга.
-
Мастер Ломастер
- Поставщик валерьянки для Кота
- Сообщения: 1995
- Зарегистрирован: Ср май 11, 2011 21:37:45
- Откуда: Цветочный город
- Контактная информация:
Re: WinAVR, c++ и прерывания
возможно, пока я корректировал свое сообщение - вы как раз отвечалиavreal писал(а):Каждый канал - единственный экземпляр «себя» с двумя собственными обработчиками прерываний (внешнее прерывание и таймерное COMPARE). Но все одни -- потомки общего PaсketReceiver и уровнем выше все думают, что вот в этом массиве -- указатели именно на задействованные PacketReceiver, а не на те, нарушающие «непременное условие», единственные экземпляры производных классов.
меня смутил единственный экземпляр единственного класса с обработчиком прерываний - по сравнению с отдельным модулем никаких преимуществ не имееющий, как мне кажется, но требующий перехода на заведомо более сложный инструмент С++. т.е. налицо возрастание сложности решения без заметной выгоды...
битва с дураками проиграна, победители торжествуют. слава победителям!
- avreal
- Опытный кот
- Сообщения: 842
- Зарегистрирован: Чт дек 31, 2009 19:27:45
- Откуда: Бровари, Україна
- Контактная информация:
Re: WinAVR, c++ и прерывания
Но каждый «листовой» класс при этом имеет единственный экземпляр, а топикстартер не упоминал, его классы самостоятельные, или чьи-то потомкиМастер Ломастер писал(а):упоминание об улучшении стройности программы за счет иерархии классов - это как раз ваш случай. это я понимаю и могу с этим согласиться без возражений.
Если остальная программа и так на плюсах (а это отдельный разговор, который шире обсуждения одного какого-то модуля-класса), то никакого специального перехода не будет.Мастер Ломастер писал(а):меня смутил единственный экземпляр единственного класса с обработчиком прерываний - по сравнению с отдельным модулем никаких преимуществ не имееющий, как мне кажется, но требующий перехода на заведомо более сложный инструмент С++. т.е. налицо возрастание сложности решения без заметной выгоды...
Пусть нужен UART (в упомянутом выше приёмнике-анализаторе пакетов) или там I2C -- если не в микроконтроллере, то в программе вполне может быть в единственном экземпляре.
В программе, использующей scmRTOS, оформление «драйвера I2C» в виде модуля С-стиля только сделает программу «неоднородной», проще она точно от этого не станет.
А класс один без иерархии (ОП, а не ООП, если я правильно терминологию понимаю) и с единственным экземпляром -- вполне ляжет в стиль. Всякие там mutex-ы с event-ами будут не отдельно стоящими статическими объектами в отдельном файле, а полями (возможно, тоже статическими) класса «драйвера», конструкторы вызовутся, то-сё. Где тут усложнение -- уже не видно. Да и вообще не видно, после того, как инструмент освоен. А применять удобно.
Код: Выделить всё
fprintf_P( uart, ...... );Он имеет operator FILE* () специально для этого случая, а внутри и экземпляр класса очереди, и разные сервисы scmRTOS использует. Поток просто уснёт (а не будет в цикле поллить флаги UART), если в очереди места нет, будет разбужен, когда появится.
Выписать тот же функционал в чисто С-шном стиле через
Код: Выделить всё
FILE uart_file = FDEV_SETUP_STREAM(uart_putchar, ...);
#define uart (&uart_file)Зато inline-доступ к приватным полям будет быстр, а для использования такого же доступа к «приватным» переменным С-шного модуля придётся таки делать их глобальными, а не в файловой области видимости прятать.
Просто в h-файле не описывать на верхнем уровне, а прятать внутрь функций, чтобы скрыть их существование и не дать туда что-то записать минуя опубликованный интерфейс модуля:
Код: Выделить всё
static inline unsigned GetSystemTimer()
{
extern volatile unsigned sys_timer;
return sys_timer;
}Лень в виде мании величия: «ты гений, зачем стараться?». В виде комплекса: «всё равно не выйдет, зачем упираться?». Как логика: «если достаточно, зачем знать и уметь больше?». Цель одна: остановить. Не любит тепло работающих мышц и шум работающего мозга.
- apwork
- Первый раз сказал Мяу!
- Сообщения: 21
- Зарегистрирован: Ср май 11, 2011 12:24:54
- Откуда: Лисичанск
Re: WinAVR, c++ и прерывания
На avrfreaks и подобных сайтах все рекомендации сводятся к применению friend функций-прерываний. Объясняют это ограничениями и недостатками avr-gcc. Все надеются, что в будущем будет что-то придумано.
Попробую поискать еще, иначе буду лепить friend'a
Попробую поискать еще, иначе буду лепить friend'a
- apwork
- Первый раз сказал Мяу!
- Сообщения: 21
- Зарегистрирован: Ср май 11, 2011 12:24:54
- Откуда: Лисичанск
Re: WinAVR, c++ и прерывания
Такое еще нарыл ( пост от Ron Kreymborg на [avr-chat] ) :
Он предлагает с помощью директивы asm сделать так:
1. Объявить макрос
2. Объявить класс прерывания
Макрос объявляет обработчик прерывания статическим.
Далее приводится текст файла с имплементацией класса прерывания:
А вот и класс устройства ( в данном случае это таймер )
От себя скажу, что это решение весьма заинтересовало. На практике еще не пробовал, но в ближайшее время попробую.
Он предлагает с помощью директивы asm сделать так:
1. Объявить макрос
Код: Выделить всё
#define CLASS_IRQ(name, vector) \
static void name(void) asm(__STRINGIFY(vector)) \
__attribute__ ((signal, __INTR_ATTRS))2. Объявить класс прерывания
Код: Выделить всё
class CTimer0Interrupt
{
public:
CTimer0Interrupt();
~CTimer0Interrupt();
private:
CLASS_IRQ(OverflowInterrupt, TIMER0_OVF_vect);
};Макрос объявляет обработчик прерывания статическим.
Далее приводится текст файла с имплементацией класса прерывания:
Код: Выделить всё
//***************************************************************
// Timer0Interrupt.cpp
//
#include "Timer0.h"
#include "Timer0Interrupt.h"
extern CTimer0 Timer0;
//----------
CTimer0Interrupt::CTimer0Interrupt()
{
TCNT0 = TIMER0_TIMEOUT;
TCCR0 = 0x04;
TIMSK |= (1<<TOIE0); // enable overflow interrupts
}
//----------
CTimer0Interrupt::~CTimer0Interrupt()
{
TIMSK &= ~(1<<TOIE0); // disable Timer0 timeout interrupt
}
//----------
void CTimer0Interrupt::OverflowInterrupt(void)
{
TCNT0 = TIMER0_TIMEOUT; // restart the timeout
Timer0.SetOverflowFlag(); // tell our friend of the event
}А вот и класс устройства ( в данном случае это таймер )
Код: Выделить всё
class CTimer0
{
friend class CTimer0Interrupt;
public:
CTimer0();
~CTimer0();
int GetTimer0Flags(void);
private:
void SetOverflowFlag(void);
private:
volatile int mTimer0Flags;
CTimer0Interrupt mTimer0Interrupt;
};
void CTimer0Interrupt::OverflowInterrupt(void)
{
TCNT0 = TIMER0_TIMEOUT; // restart the timeout
Timer0.mTimer0Flags |= TIMER0_OVERFLOW;
}От себя скажу, что это решение весьма заинтересовало. На практике еще не пробовал, но в ближайшее время попробую.
Re: WinAVR, c++ и прерывания
а в чем смысл впихивания обработчика в класс?
Даже шире: в чем смысл применения ООП при создании firmware?
На мой взгляд, класс, от которого в программе существует в принципе единственный экземпляр -- вполне нормальное явление.
Ну, не все так однозначно. Например, мне это кажется жутким извращением.
Разница между теорией и практикой на практике гораздо больше, чем в теории.
- apwork
- Первый раз сказал Мяу!
- Сообщения: 21
- Зарегистрирован: Ср май 11, 2011 12:24:54
- Откуда: Лисичанск
Re: WinAVR, c++ и прерывания
Э-э-э... товарищи, давайте не устраивать холивар. Личные предубеждения оставляем при себе и оперируем фактами. Есть проблема - ищем решение! Не надо говорить, что проблема плохая - находим себе "хорошую" проблему и решаем в свое удовольствие!
Re: WinAVR, c++ и прерывания
Я предпочитаю обработчики прерываний делать обычными статическими функциями-членами. Причем встраиваемыми для эффективности. И вызывать их из обычным образом написанного обработчика.
Это более гибкий и переносимый подход. Подробнее можно почитать тут:
http://we.easyelectronics.ru/Soft/kolcevoy-bufer-na-s-dlya-mk.html
Код: Выделить всё
class Usart
{
...
static void RxHandler()
{
char byte = UDR;
...
}
...
};
...
ISR(USART_RXC_vect)
{
Usart::RxHandler();
}
Это более гибкий и переносимый подход. Подробнее можно почитать тут:
http://we.easyelectronics.ru/Soft/kolcevoy-bufer-na-s-dlya-mk.html
- BCluster
- Собутыльник Кота
- Сообщения: 2512
- Зарегистрирован: Пн апр 06, 2009 19:33:29
- Откуда: Молдова, Кишинев
- Контактная информация:
Re: WinAVR, c++ и прерывания
Не люблю плюсы. Да и необходимость использования ООП на авр весьма сомнительна. Программы не настолько сложны. Ну эт ИМХО все канечно 