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

 
 
> C++ templates и mcu peripherals
_Артём_
сообщение Mar 23 2012, 00:03
Сообщение #1


Гуру
******

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



Доброе утро.
Такой простой вопрос: сейчас многие современные контроллеры оснащаются несколькими однотипными блоками периферии. Что толкает к повторному использованию кода и templates в частности.
Как правило структура блока однотипна (имеет одинаково расположенные в памяти регистры) и каждый блок занимает в памяти некоторую непрерывную область начинающиюся с базового адреса.
Ну так вот вопрос: как правильней передать шаблону этот самый базовый адрес?
Код
template <int BASE_ADDRESS> class TIOBlock {
.....
}

И потом приводить этот адрес к тому что надо?
Или использовать enum или ещё что?
Как делать правильней?

Спасибо.
Go to the top of the page
 
+Quote Post
 
Start new topic
Ответов
neiver
сообщение Mar 23 2012, 11:06
Сообщение #2


Местный
***

Группа: Участник
Сообщений: 214
Регистрация: 22-03-10
Из: Саратов
Пользователь №: 56 123



Сложность здесь заключается в том, что эти структуры регистров периферии часто объявляются очень разными способами. Это может быть дефайн, в котором целочисленный литерал приводится к указателю на соответствующую структуру. А может быть хитрым образом переменная, размещенная по нужному адресу с помощью каких-то компиляторных расширений. Просто взять адрес такой структуры и передать его как параметр шаблона в большинстве случаев не получится, так как компилятор может не посчитать его пригоднам для параметра шаблона. Самый надёжный, на мой взгляд, способ - обращаться к этой структуре по имени. Для этого делаем макрос, который объявляет хитрую структуру-обёртку:
Код
#define IO_STRUCT_WRAPPER(STRUCT_PTR, CLASS_NAME, STRUCT_TYPE) \
    struct CLASS_NAME\
    {\
        typedef STRUCT_TYPE DataT;\
        STRUCT_TYPE* operator->(){return ((STRUCT_TYPE *)(STRUCT_PTR));}\
    }

В ней определён оператор ->, который позволяет прозрачно обращаться к отдельным регистрам в структуре. С помощью этого макроса объявляем обёртки:
Код
IO_STRUCT_WRAPPER(DMA1, Dma1, DMA_TypeDef);
IO_STRUCT_WRAPPER(DMA1_Channel1, Dma1Channel1, DMA_Channel_TypeDef);
...
IO_STRUCT_WRAPPER(DMA1_Channel7, Dma1Channel7, DMA_Channel_TypeDef);


Код
template<class DmaRegs, class Clock, int Channels>
class DmaModule :public DmaBase
{
...
};
В шаблон структура-обёртка передаётся как обычный типовой параметр:
template<class Module, class ChannelRegs, int Channel>
class DmaChannel :public DmaBase
{
    public:        
    static void Init(Mode mode, void *buffer, void *periph, uint32_t bufferSize)
    {
        Module::Enable();
        ChannelRegs()->CCR = 0;
        ChannelRegs()->CNDTR = bufferSize;
        ChannelRegs()->CPAR = reinterpret_cast<uint32_t>(periph);
        ChannelRegs()->CMAR = reinterpret_cast<uint32_t>(buffer);
        ChannelRegs()->CCR = mode | DMA_CCR1_EN;
    }
...
};

typedef DmaModule<Private::Dma1, Clock::Dma1Clock, 7> Dma1;
typedef DmaChannel<Dma1, Private::Dma1Channel1, 1> Dma1Channel1;

Для доступа к отдельным регистрам в структуре используестя стрелка:
Код
ChannelRegs()->CCR = 0;

Go to the top of the page
 
+Quote Post



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

 


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


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