|
|
  |
с++ и прерывания |
|
|
|
Jan 23 2012, 14:14
|
Гуру
     
Группа: Свой
Сообщений: 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. Не понял где вектор указывается.
|
|
|
|
|
Jan 23 2012, 14:37
|
Местный
  
Группа: Участник
Сообщений: 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;
} К сожалению, мой уровень знаний не велик для таких фокусов
|
|
|
|
|
Jan 23 2012, 14:55
|
Участник

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

|
омг На днях за неимением достойного занятия тоже пытался нашаблонить такое для авр под иар использовать предполагаю примерно так: typedef usart<USART0, MyProtocol, 57600L> ext_us; все нормально компилируется, в железе не проверял. правда, все-время мучают два вопроса: что за говнокод получается и нафига мне это надо
|
|
|
|
|
Jan 23 2012, 14:59
|

Гуру
     
Группа: Свой
Сообщений: 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.
--------------------
|
|
|
|
|
Jan 23 2012, 15:00
|
Гуру
     
Группа: Свой
Сообщений: 2 128
Регистрация: 21-05-06
Пользователь №: 17 322

|
Цитата(demitar @ Jan 23 2012, 16:55)  омг На днях за неимением достойного занятия тоже пытался нашаблонить такое для авр под иар использовать предполагаю примерно так: typedef usart<USART0, MyProtocol, 57600L> ext_us; все нормально компилируется, в железе не проверял. правда, все-время мучают два вопроса: что за говнокод получается и нафига мне это надо  Да, выглядит страшно... но для xmeg должно быть гораздо проще (порты все одинаковые). А что без enum и проч. никак нельзя? И адрес порта не получается подсунуть.
|
|
|
|
|
Jan 23 2012, 15:04
|
Участник

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

|
Ну дык я букварь по цпп только в декабре приобрел а адрес порта по первому параметру шаблона выбирается типа для 128 меги: usart<USART0,....> - нулевой порт usart<USART1,....> - первый
|
|
|
|
|
Jan 23 2012, 22:21
|
Гуру
     
Группа: Свой
Сообщений: 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); } ..........
|
|
|
|
|
Jan 24 2012, 06:06
|
Участник

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

|
а правильно ли я понял, что IO регистры у атхмеги в одном адресном пространстве с памятью данных?
|
|
|
|
|
Jan 24 2012, 07:11
|

Профессионал
    
Группа: Свой
Сообщений: 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
|
|
|
|
|
Jan 24 2012, 07:36
|
Участник

Группа: Участник
Сообщений: 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 хм странно, сегодня они там есть, а вчера их небыло
|
|
|
|
|
Jan 26 2012, 05:29
|
Частый гость
 
Группа: Участник
Сообщений: 105
Регистрация: 9-09-11
Пользователь №: 67 080

|
Цитата(V_G @ Jan 24 2012, 10:11)  Вообще-то для UARTов в хmege есть очень эффективный механизм DMA... Но это на ассемблере Заинтересовал про DMA и USART  Сколько не читал про DMA так и не понял как его использовать Покажи плиз асм код USART+ DMA.  )
Сообщение отредактировал Navovvol - Jan 26 2012, 05:31
|
|
|
|
|
  |
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|