Jump to content

    
Sign in to follow this  
HEX

call back

Recommended Posts

Читал архивы и наткнулся... Стало интересно, прочитал, кое - что взял на вооружение. Но непонятен один момент - как устроен класс "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

Что я неправильно написал?

 

Для начала считаю необходимым заметить, что приводил пример с классами, а не с функциями, с которыми все немного по-другому. Ну а если конкретнее, то мне всегда казалось, что параметризируется только тип аргумента функции, но никак не внутренние переменные. Иначе как ее вообще объявлять?

Share this post


Link to post
Share on other sites
Захотел сделать работу с периферией посредством классов. Но возникло два вопроса: как написать один код для каждого типа периферии, но чтоб он работал независимо от ее количества (к примеру UART0, UART1..) и как потом прерывания обрабатывать. Ответ был найден в параметризации шаблона класса базовым адресом в памяти. что-то вроде template<unsigned Adr> class CUart {..}; Соответственно в нем уже работать только по смещению.

 

Но тут возник интересный ньюанс: а как делать обработчик прерывания? Ведь его адрес надо записать в контроллер? Сделал так: все наследуются от одного базового сласса с виртуальной функцией Isr. В конструкторе все экземпляры регистрируются в глобальном массиве. Для каждого класса (читай номера устройства) делается статическая функция, которая и регистрируется в контроллере прерываний. А уже она по своему вызову выбирает из массива адрес соответствующего ей экзепляра и дергает его Isr.

 

Так к чему все это? Казалось бы работает, и не надо трогать.. Но нет! Ведь можно же еще уменьшить текст кода! А именно: сделать эту статическую функцию параметризируемой номером периферии и записать всего один раз template<unsigned N> void IsrExe(){ Array[N]->Isr();} Так вот мой Keil Arm не хочет адрес так описанной функции помещать в котроллер, а под MS VC проверяю - все в порядке.

 

Так что речь, пока, к сожалению, можно вести не о том, как хотелось бы, а о том, что позволяет выбранный инструментарий..

 

Почитав это можно только спросить и к чему так е-ть себе мозги? :))

Share this post


Link to post
Share on other sites
Почитав это можно только спросить и к чему так е-ть себе мозги? :))

 

Как поуказывает практика, у большинства людей мозги чаще ржавеют, чем истираются.

Так что не спи - замерзнешь:)

Share this post


Link to post
Share on other sites
Для начала считаю необходимым заметить, что приводил пример с классами, а не с функциями, с которыми все немного по-другому. Ну а если конкретнее, то мне всегда казалось, что параметризируется только тип аргумента функции, но никак не внутренние переменные. Иначе как ее вообще объявлять?

 

Прошу прощения, я сморозил глупость. Все-таки я вначале расписал класс, потом из-за ошибок компиляции начал поочередно все откидывать, потом по старой русской традиции решил все-таки заглянуть в 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;
}

Опять та же ошибка. Обидно

Share this post


Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Sign in to follow this