grau 0 Posted February 18, 2008 · Report post Читал архивы и наткнулся... Стало интересно, прочитал, кое - что взял на вооружение. Но непонятен один момент - как устроен класс "CBitsRO", а конкретно каким образом он осуществляет доступ к регистру с адресом, определяемым параметром шаблона? Сорри, что долго не отвечал.. Класс CBitsRO является фактически обычным макросом. Его задача обеспечить корректность возращаемого значения. Т.е. прозрачно читаем значение битов по маске и сдвигаем их. template <unsigned A, unsigned P, unsigned L> class CBitsRO{ public: operator unsigned(){ return ((*((volatile unsigned*) A))>>P)&((1<<L)-1); } }; template <IO_REG &r> void f(uint8_t mask) int main(){ f<PORTB>(0x77); return 0; } На это ругается компилятор: Internal Error: [any]: Unexpected exception Что я неправильно написал? Для начала считаю необходимым заметить, что приводил пример с классами, а не с функциями, с которыми все немного по-другому. Ну а если конкретнее, то мне всегда казалось, что параметризируется только тип аргумента функции, но никак не внутренние переменные. Иначе как ее вообще объявлять? Quote Ответить с цитированием Share this post Link to post Share on other sites
SpiritDance 0 Posted February 19, 2008 · Report post Захотел сделать работу с периферией посредством классов. Но возникло два вопроса: как написать один код для каждого типа периферии, но чтоб он работал независимо от ее количества (к примеру UART0, UART1..) и как потом прерывания обрабатывать. Ответ был найден в параметризации шаблона класса базовым адресом в памяти. что-то вроде template<unsigned Adr> class CUart {..}; Соответственно в нем уже работать только по смещению. Но тут возник интересный ньюанс: а как делать обработчик прерывания? Ведь его адрес надо записать в контроллер? Сделал так: все наследуются от одного базового сласса с виртуальной функцией Isr. В конструкторе все экземпляры регистрируются в глобальном массиве. Для каждого класса (читай номера устройства) делается статическая функция, которая и регистрируется в контроллере прерываний. А уже она по своему вызову выбирает из массива адрес соответствующего ей экзепляра и дергает его Isr. Так к чему все это? Казалось бы работает, и не надо трогать.. Но нет! Ведь можно же еще уменьшить текст кода! А именно: сделать эту статическую функцию параметризируемой номером периферии и записать всего один раз template<unsigned N> void IsrExe(){ Array[N]->Isr();} Так вот мой Keil Arm не хочет адрес так описанной функции помещать в котроллер, а под MS VC проверяю - все в порядке. Так что речь, пока, к сожалению, можно вести не о том, как хотелось бы, а о том, что позволяет выбранный инструментарий.. Почитав это можно только спросить и к чему так е-ть себе мозги? :)) Quote Ответить с цитированием Share this post Link to post Share on other sites
grau 0 Posted February 20, 2008 · Report post Почитав это можно только спросить и к чему так е-ть себе мозги? :)) Как поуказывает практика, у большинства людей мозги чаще ржавеют, чем истираются. Так что не спи - замерзнешь:) Quote Ответить с цитированием Share this post Link to post Share on other sites
landrey 0 Posted February 23, 2008 · Report post Для начала считаю необходимым заметить, что приводил пример с классами, а не с функциями, с которыми все немного по-другому. Ну а если конкретнее, то мне всегда казалось, что параметризируется только тип аргумента функции, но никак не внутренние переменные. Иначе как ее вообще объявлять? Прошу прощения, я сморозил глупость. Все-таки я вначале расписал класс, потом из-за ошибок компиляции начал поочередно все откидывать, потом по старой русской традиции решил все-таки заглянуть в EVAVR_CompilerReference.pdf. вот что я там нашел (цитирую): Non-type template parameters It is allowed to have a reference to a memory type as a template parameter, even if pointers to that memory type are not allowed. Example extern int __io x; template<__io int &y> void foo() { y = 17; } void bar() { foo<x>(); } Пробую этот кусок - та же ошибка. Поэтому и в своем посте я изобразил подобное. Но вот вырезка из моего класса: typedef uint8_t volatile __tiny IO_REG; template <IO_REG &UDR, IO_REG &UBRRH, IO_REG &UBRRL> class CBaseUart { private: enum { DEFAULT_BAUDRATE = 115200, }; public: CBaseUart(uint32_t baudRate=DEFAULT_BAUDRATE) { uint16_t tmp_baud = CPU_CLK_Hz / (16 * baudRate) - 1; UBRRH = (uint8_t)(tmp_baud >> 8); UBRRL = (uint8_t)tmp_baud; } virtual ~CBaseUart(); inline void transmit(uint8_t data) { UDR = data; } }; Вот так я пытаюсь использовать: int main() { CBaseUart <UDR0, UBRR0H, UBRR0L> uart; uart.transmit(0x55); return 0; } Опять та же ошибка. Обидно Quote Ответить с цитированием Share this post Link to post Share on other sites