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

 
 
 
Reply to this topicStart new topic
> с++ и прерывания
Sirko
сообщение Jan 23 2012, 12:16
Сообщение #1


Местный
***

Группа: Участник
Сообщений: 245
Регистрация: 15-08-07
Пользователь №: 29 795



Есть желание написать класс USART для XMega, благо строение ядра способствует. Но вот как быть с прерываниями?
Не хочется для каждого объекта прописывать обработчики в ручную, а как реализовать шаблонно или с макросами, не представляю.

Есть идеи?
Go to the top of the page
 
+Quote Post
_Артём_
сообщение Jan 23 2012, 12:51
Сообщение #2


Гуру
******

Группа: Свой
Сообщений: 2 128
Регистрация: 21-05-06
Пользователь №: 17 322



Цитата(Sirko @ Jan 23 2012, 14:16) *
Есть желание написать класс USART для XMega, благо строение ядра способствует. Но вот как быть с прерываниями?
Не хочется для каждого объекта прописывать обработчики в ручную, а как реализовать шаблонно или с макросами, не представляю.

Есть идеи?


Код
template<int INT_VECTOR>class Tuart_class {
public:
    #pragma vector=INT_VECTOR
    __interrupt static void UsartHandler()
    {

    }
    
};

Tuart_class<USARTC0_RXC_vect> usartc0;

Go to the top of the page
 
+Quote Post
prottoss
сообщение Jan 23 2012, 13:37
Сообщение #3


Гуру
******

Группа: Свой
Сообщений: 2 720
Регистрация: 24-03-05
Пользователь №: 3 659



Может так?

Код
class clUSART
    {
   public:    
        usart_t *c;
        
        void Init(usart_t *p){ c = p;};
        ...
        static void isr(usart_t *p);
   }
  
   clUSART u0, u1, u2;
  
    static void clUSART::isr(clUSART *p)
   {
        ...
   }
  
   __interrupt void u0_isr()
   {
        clUSART::isr(u0.c);
   }
   __interrupt void u1_isr()
    {
         clUSART::isr(u1.c);
    }
   __interrupt void u2_isr()
    {
         clUSART::isr(u2.c);
    }
   ...
   main()
   {
       u1.Init(p_usart1);
       u2.Init(p_usart2);
       u3.Init(p_usart3);
       ...
   }
   }


sm.gif Чет туплю после работ... редактирую 5-ый раз. Ну, надеюсь смысл понятен.

Сообщение отредактировал prottoss - Jan 23 2012, 13:53


--------------------
Go to the top of the page
 
+Quote Post
_Артём_
сообщение Jan 23 2012, 14:14
Сообщение #4


Гуру
******

Группа: Свой
Сообщений: 2 128
Регистрация: 21-05-06
Пользователь №: 17 322



Цитата(prottoss @ Jan 23 2012, 15:37) *
Может так?

Так конечно можно, но есть недостатки:
Код
class clUSART
    {
   public:    
        usart_t *c;

Обращение будет по указателю, а хотелось бы через STD/LDD (не путаю команды?)



Код
   __interrupt void u0_isr()
   {
        clUSART::isr(u0.c);
   }
   __interrupt void u1_isr()
    {
         clUSART::isr(u1.c);
    }
   __interrupt void u2_isr()
    {
         clUSART::isr(u2.c);
    }
   ...
   }

Каждый вектор отдельно прописывать?
И ещё вызов функции делать?
P.S. Не понял где вектор указывается.


Go to the top of the page
 
+Quote Post
Sirko
сообщение Jan 23 2012, 14:37
Сообщение #5


Местный
***

Группа: Участник
Сообщений: 245
Регистрация: 15-08-07
Пользователь №: 29 795



Откровенно говоря не хочется во "внутренностях" руками лазить.
Мысль - объявить некий енумерейт и подставлять его при инициализации.

Код
template <USART_ENUM E>
class Tuart_class {
    typedef enum{
        usartC0 = 25,
        usartC1 = 28
    }USART_ENUM;
};

ISR(E){}    // USARTE0_RXC_vect
ISR(E+1){}    // USARTE0_DRE_vect
ISR(E+2){}    // USARTE0_TXC_vect

void main(){

     Tuart_class<Tuart_class::USART_ENUM::usartC0> usartc0;

}


К сожалению, мой уровень знаний не велик для таких фокусов
Go to the top of the page
 
+Quote Post
demitar
сообщение Jan 23 2012, 14:55
Сообщение #6


Участник
*

Группа: Участник
Сообщений: 17
Регистрация: 3-09-09
Пользователь №: 52 170



омг
На днях за неимением достойного занятия тоже пытался нашаблонить такое для авр под иар
использовать предполагаю примерно так:

typedef usart<USART0, MyProtocol, 57600L> ext_us;

все нормально компилируется, в железе не проверял.
правда, все-время мучают два вопроса:
что за говнокод получается и нафига мне это надо wacko.gif
Прикрепленные файлы
Прикрепленный файл  avr_usart.hpp.zip ( 2.56 килобайт ) Кол-во скачиваний: 27
 
Go to the top of the page
 
+Quote Post
prottoss
сообщение Jan 23 2012, 14:59
Сообщение #7


Гуру
******

Группа: Свой
Сообщений: 2 720
Регистрация: 24-03-05
Пользователь №: 3 659



Цитата(_Артём_ @ Jan 23 2012, 20:14) *
P.S. Не понял где вектор указывается.

Ну так
__interrupt void u0_isr();
__interrupt void u1_isr();
__interrupt void u2_isr();

и есть обработчики (векторы), которые подставляют указатель конкретного USART в общий для объектов обработчик clUSART::isr

Я просто не знаю, какие в xmega имена обработчиков определены в IAR.


--------------------
Go to the top of the page
 
+Quote Post
_Артём_
сообщение Jan 23 2012, 15:00
Сообщение #8


Гуру
******

Группа: Свой
Сообщений: 2 128
Регистрация: 21-05-06
Пользователь №: 17 322



Цитата(demitar @ Jan 23 2012, 16:55) *
омг
На днях за неимением достойного занятия тоже пытался нашаблонить такое для авр под иар
использовать предполагаю примерно так:

typedef usart<USART0, MyProtocol, 57600L> ext_us;

все нормально компилируется, в железе не проверял.
правда, все-время мучают два вопроса:
что за говнокод получается и нафига мне это надо wacko.gif

Да, выглядит страшно... но для xmeg должно быть гораздо проще (порты все одинаковые).
А что без enum и проч. никак нельзя?
И адрес порта не получается подсунуть.
Go to the top of the page
 
+Quote Post
demitar
сообщение Jan 23 2012, 15:04
Сообщение #9


Участник
*

Группа: Участник
Сообщений: 17
Регистрация: 3-09-09
Пользователь №: 52 170



Ну дык я букварь по цпп только в декабре приобрел rolleyes.gif
а адрес порта по первому параметру шаблона выбирается
типа для 128 меги:
usart<USART0,....> - нулевой порт
usart<USART1,....> - первый
Go to the top of the page
 
+Quote Post
_Артём_
сообщение Jan 23 2012, 22:21
Сообщение #10


Гуру
******

Группа: Свой
Сообщений: 2 128
Регистрация: 21-05-06
Пользователь №: 17 322



Цитата(prottoss @ Jan 23 2012, 16:59) *
Ну так
__interrupt void u0_isr();
__interrupt void u1_isr();
__interrupt void u2_isr();

и есть обработчики (векторы), которые подставляют указатель конкретного USART в общий для объектов обработчик clUSART::isr

Я просто не знаю, какие в xmega имена обработчиков определены в IAR.

pragma не хватает.
Тогда так?
Код
  #pragma vector=USARTC0_RXC_vect
  __interrupt void u0_rxc_isr()
   {
        clUSART::isr(u0.c);
   }
  #pragma vector=USARTC1_RXC_vect
   __interrupt void u1__rxc_isr()
    {
         clUSART::isr(u1.c);
    }
   ..........

Go to the top of the page
 
+Quote Post
demitar
сообщение Jan 24 2012, 06:06
Сообщение #11


Участник
*

Группа: Участник
Сообщений: 17
Регистрация: 3-09-09
Пользователь №: 52 170



а правильно ли я понял, что IO регистры у атхмеги в одном адресном пространстве с памятью данных?
Go to the top of the page
 
+Quote Post
V_G
сообщение Jan 24 2012, 07:11
Сообщение #12


Профессионал
*****

Группа: Свой
Сообщений: 1 818
Регистрация: 15-10-09
Из: Владивосток
Пользователь №: 52 955



Вообще-то для UARTов в хmege есть очень эффективный механизм DMA, но ни одна из представленных сишных реализаций его не использует.
Во всяком случае, при передаче, когда длина буфера заранее известна, применять DMA очень эффективно и красиво, и не нужно никаких прерываний. При приеме посложнее. Но если протокол предусматривает передачу длины посылки, я по прерыванию RxC побайтно беру начало, пока не доберусь до длины, а потом настраиваю DMA на прием указанного числа байтов и реагирую только на прерывание окончания DMA.
Но это на ассемблере

По IO - да. Плюс к тому есть виртуальные порты, которые можно присвоить к любым портам, подключенным к внешним ногам, и обращаться к ним традиционно, через IN,OUT,CBI,SBI и т.д. А так, в общем случае до назначения виртуальных портов, внешние порты не входят в пространство IO
И это на ассемблере

Сообщение отредактировал V_G - Jan 24 2012, 07:12
Go to the top of the page
 
+Quote Post
demitar
сообщение Jan 24 2012, 07:36
Сообщение #13


Участник
*

Группа: Участник
Сообщений: 17
Регистрация: 3-09-09
Пользователь №: 52 170



Вчера бегло просматривал систему команд не нашел там IN/OUT, да и намекали здесь на LD
Не знаю как там ДМА организован, но с обычными прерываниями можно замутить нечто такое:
CODE

#define US0_BASE_ADDR //... Объявляем адреса устройств и векторов,
#define US1_BASE_ADDR //... вероятно, они уже где-то пределены
#define US0_VECTOR_BASE //...
#define US1_VECTOR_BASE //...

//структурка, которая описывает наши usart'ы

template<int US_BASE_ADDR>
struct us_descr {
static __no_init usart_t usart @ US_BASE_ADDR;

enum {
BASE_VECTOR_ADDR = US_BASE_ADDR == US0_BASE_ADDR? US0_VECTOR_BASE:
US_BASE_ADDR == US1_BASE_ADDR? US1_VECTOR_BASE:
//...
-1L,
RXC_VECTOR_ADDR = BASE_VECTOR_ADDR + RXC_VECTOR_OFFSET,
TXC_VECTOR_ADDR = BASE_VECTOR_ADDR + TXC_VECTOR_OFFSET,
DRE_VECTOR_ADDR = BASE_VECTOR_ADDR + DRE_VECTOR_OFFSET,
//...
};
};

/* базовый клас, в котором реализована вся низкоуровненвая работа,
типа конфигурирования, чтения/записи регистров и тп... */

class basic_usart {
protected:
usart_t &Us;
basic_usart(usart_t &us): Us(us) {}

public:
void do_something_with_us() { Us.REG_NAME = 10; }
//...
};

/* собственно наш класс, зависит от протокола и адреса порта,
с которыми мы хотим его связать. Реализует только обработчики
прерываний и интерфейс для создания экземпляра этого класса */

template <int US_BASE_ADDR, class PROTOCOL>
class usart: public basic_usart {
protected:
static PROTOCOL *protocol;

# pragma vector = us_descr<US_BASE_ADDR>::RXC_VECTOR_ADDR
static __interrupt void RXC_handler() {
protocol->OnRxChar( // в обработчиках делаем что надо с регистрами и
us_descr<US_BASE_ADDR>::usart.DATA_REG; // вызываем нужные методы протокола пусть он сам
); // разбирается с данными
}

# pragma vector = us_descr<US_BASE_ADDR>::TXC_VECTOR_ADDR
static __interrupt void TXC_handler() {
//...
}


# pragma vector = us_descr<US_BASE_ADDR>::DRE_VECTOR_ADDR
static __interrupt void DRE_handler() {
//...
}

//...
public:
usart(PROTOCOL *p): basic_usart(us_descr<US_BASE_ADDR>::usart) {
DRE_handler, RXC_handler, TXC_handler; // тут надо пнуть этих ребят иначе компилятор не создат
// их специализацию (IAR 4.12A)

protocol = p;
//...
}
};

template <int US_BASE_ADDR, class PROTOCOL>
PROTOCOL *usart<US_BASE_ADDR, PROTOCOL>::protocol = NULL;

template<int US_BASE_ADDR> usart_t us_descr<US_BASE_ADDR>::usart;


Классы протоколов тоже можно сделать шаблонными и наследовать их прямо от usart вроде этого


CODE
template <int US_BASE_ADDR>
class Protocol: public usart<US_BASE_ADDR, Protocol<US_BASE_ADDR> >
{
typedef usart<US_BASE_ADDR, Protocol<US_BASE_ADDR> > USART;

public:
void OnRxChar(int ch) {}
Protocol(): USART(this) {}
};


и уже в программе юзать протокол;
дма, тоже нав можно как-то прикрутить сюда
попробовал скомпилиовать под иар 4.12 с максимумом оптимизации, вроде обращается к регистрам как положено, т.е.
прямо по нужным адресам читает и пишет содержимое нужной структурки usart_t через LDS, накладные расходы только на вызов метода через указатель.

Правда мой динозавар о хмеге ничего не знает, так что в настройках целевой процессор - atmega128


Цитата
Вчера бегло просматривал систему команд не нашел там IN/OUT

хм странно, сегодня они там есть, а вчера их небыло cranky.gif
Go to the top of the page
 
+Quote Post
Navovvol
сообщение Jan 26 2012, 05:29
Сообщение #14


Частый гость
**

Группа: Участник
Сообщений: 105
Регистрация: 9-09-11
Пользователь №: 67 080



Цитата(V_G @ Jan 24 2012, 10:11) *
Вообще-то для UARTов в хmege есть очень эффективный механизм DMA...
Но это на ассемблере

Заинтересовал про DMA и USART sm.gif
Сколько не читал про DMA так и не понял как его использовать
Покажи плиз асм код USART+ DMA. sm.gif)

Сообщение отредактировал Navovvol - Jan 26 2012, 05:31
Go to the top of the page
 
+Quote Post

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

 


RSS Текстовая версия Сейчас: 20th July 2025 - 13:23
Рейтинг@Mail.ru


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