Вчера бегло просматривал систему команд не нашел там 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
хм странно, сегодня они там есть, а вчера их небыло