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

 
 
> С++, метод шаблонного класса как обработчик прерывания
_pv
сообщение Jun 12 2017, 16:45
Сообщение #1


Гуру
******

Группа: Свой
Сообщений: 2 563
Регистрация: 8-04-05
Из: Nsk
Пользователь №: 3 954



есть базовый класс, пусть будет уарта, которому через шаблон задаётся базовый адрес регистров и размер фифо.
template <int USARTx_BASE, int fifoSize = 32> class UartBase{
void ISRBase();
};

теперь делаем классы под каждый uart, так как немного разная инициализация (как минимум клоки включаются отдельно), и статический обработчик прерывания.

template <int fifoSize = 32> class Uart0 : UartBase<LPC_USART0_BASE, fifoSize>{
Uart0(){...}
static void ISR() { UartBase<LPC_USART0_BASE, fifoSize>::ISRBase(); }
};

вопрос1: как теперь сделать Uart0::ISR() обработчиком прерывания? с шаблоном-то тип у него тип теперь к размеру FIFO привязан.
void UART0_IRQHandler() { Uart0<?????????>::ISR(); }

кроме как убрать шаблон можно по другому это как-то по-человечески сделать?
class Uart0 : UartBase<LPC_USART0_BASE, UART0_FIFO_SIZE>

вопрос2: метод базового класса UartBase<LPC_USART0_BASE, fifoSize>::ISR(); тоже вызываться не хочет из статического метода.
error: cannot call member function 'void UartBase<USARTx_BASE, fifoSize>::ISR() [with int USARTx_BASE = 1074151424; int fifoSize = 32]' without object

наверняка не раз уже обсуждалось, но что-то сходу не нашлось, ткните как с однотипной периферией на плюсах правильно работать.
Go to the top of the page
 
+Quote Post
 
Start new topic
Ответов
sigmaN
сообщение Jun 21 2017, 09:49
Сообщение #2


I WANT TO BELIEVE
******

Группа: Свой
Сообщений: 2 617
Регистрация: 9-03-08
Пользователь №: 35 751



Цитата
Статические методы в классе нужны крайне редко и практически всегда они имеют квалификатор "private", но исключение составляет, пожалуй, лишь паттерн "Singleton" с его методом ::getInstance().
Категорически с вами не соглашусь. Объединение группы методов под крышей одного типа позволяет очень эффективно решать ряд задач! Часто прямо на этапе компиляции.
Ознакомьтесь с http://easyelectronics.ru/rabota-s-portami...erov-na-si.html

А вот вам моя почти на 100% переработанная и допиленная реализация этой идеи. Прикрепленный файл  neiverio_dxEdition_24_.zip ( 120.61 килобайт ) Кол-во скачиваний: 35
Там только для стм32 пока реализации нет, не дошли руки.
Да, это по сути куча функций, но в данном случае стэйт и инстансы нам и не нужны! И как результат имеем адсолютно отсутствующий оверхед и не отступаем от заветов объектно-ориентированного программирования. Таки пины пркерасно передаются как параметр шаблона куда угодно(в драйвер).. В прочем, всё это описано в оригинальной статье.

P.S.
#include "neiverio.hpp"
и прописать путь к папке с нужной реализацией GPIO (сейчас это AVR, XMEGA или STM8)


--------------------
The truth is out there...
Go to the top of the page
 
+Quote Post
Forger
сообщение Jun 21 2017, 10:21
Сообщение #3


Профессионал
*****

Группа: Свой
Сообщений: 1 215
Регистрация: 22-02-05
Пользователь №: 2 831



Цитата(sigmaN @ Jun 21 2017, 12:49) *
И как результат имеем адсолютно отсутствующий оверхед и не отступаем от заветов объектно-ориентированного программирования.

Оверхед, оверхед, оверхед...
Это напоминает автовладельца, которого беспокоит царапина на крыле его авто при том, что ее кузов уже напрочь прогнил sm.gif
Если только и думать об этом мифическом оверхеде, то никогда не получится создавать действительно полноценный ООП-код.

Цитата(sigmaN)
А вот вам моя почти на 100% переработанная и допиленная реализация этой идеи.

~1Мбайт текста ... для портов I/O wacko.gif

Странно, у меня это все влезает в один файлик в 10кб текста (для одного МК). Мне даже как-то стыдно стало sm.gif


--------------------
Кругозор некоторых людей - круг с нулевым радиусом. Они называют его "точкой зрения".
Go to the top of the page
 
+Quote Post
Сергей Борщ
сообщение Jun 21 2017, 11:07
Сообщение #4


Гуру
******

Группа: Модераторы
Сообщений: 8 455
Регистрация: 15-05-06
Из: Рига, Латвия
Пользователь №: 17 095



QUOTE (Forger @ Jun 21 2017, 13:21) *
Странно, у меня это все влезает в один файлик в 10кб текста (для одного МК). Мне даже как-то стыдно стало sm.gif
Да чего уж там стыдиться, показывайте. ваше "это все" можно передавать параметром в шаблон?


--------------------
На любой вопрос даю любой ответ
"Write code that is guaranteed to work, not code that doesn’t seem to break" (C++ FAQ)
Go to the top of the page
 
+Quote Post
Forger
сообщение Jun 21 2017, 11:14
Сообщение #5


Профессионал
*****

Группа: Свой
Сообщений: 1 215
Регистрация: 22-02-05
Пользователь №: 2 831



Цитата(Сергей Борщ @ Jun 21 2017, 14:07) *
Да чего уж там стыдиться, показывайте. ваше "это все" можно передавать параметром в шаблон?

Можно и так, но я в таких случаях передаю не сам шаблонный класс пина, а лишь индекс пина, на котором он должен "висеть".
И уже внутри шаблонного класса, где этот пин должен использоваться, создаю экземпляр этого пина.
Оно и логично - пин должен принадлежать только тому, кто его пользует. Он же и должен создавать этот пин.
Тогда этот пин защищен от других посягателей.

CODE
////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Project: Any
// Description: Pin (STM32L1xx)
////////////////////////////////////////////////////////////////////////////////////////////////////////////////

#pragma once

////////////////////////////////////////////////////////////////////////////////////////////////////////////////

#include "stm32l1xx_rcc.h"

////////////////////////////////////////////////////////////////////////////////////////////////////////////////

typedef enum
{
PA0, PA1, PA2, PA3, PA4, PA5, PA6, PA7, PA8, PA9, PA10, PA11, PA12, PA13, PA14, PA15,
PB0, PB1, PB2, PB3, PB4, PB5, PB6, PB7, PB8, PB9, PB10, PB11, PB12, PB13, PB14, PB15,
PC0, PC1, PC2, PC3, PC4, PC5, PC6, PC7, PC8, PC9, PC10, PC11, PC12, PC13, PC14, PC15,
PD0, PD1, PD2, PD3, PD4, PD5, PD6, PD7, PD8, PD9, PD10, PD11, PD12, PD13, PD14, PD15,
PE0, PE1, PE2, PE3, PE4, PE5, PE6, PE7, PE8, PE9, PE10, PE11, PE12, PE13, PE14, PE15,
PF0, PF1, PF2, PF3, PF4, PF5, PF6, PF7, PF8, PF9, PF10, PF11, PF12, PF13, PF14, PF15,
PH0, PH1, PH2, PH3, PH4, PH5, PH6, PH7, PH8, PH9, PH10, PH11, PH12, PH13, PH14, PH15,
} PIN;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////

class PinBase
{
public:
PinBase(PIN pin)
{
portIndex = pin / 16;
pinIndex = pin % 16;
pinMask = (((int32_t)1) << pinIndex);

switch (portIndex)
{
#ifdef GPIOA_BASE
case (0): port = GPIOA; RCC->AHBENR |= RCC_AHBPeriph_GPIOA; break;
#endif
#ifdef GPIOB_BASE
case (1): port = GPIOB; RCC->AHBENR |= RCC_AHBPeriph_GPIOB; break;
#endif
#ifdef GPIOC_BASE
case (2): port = GPIOC; RCC->AHBENR |= RCC_AHBPeriph_GPIOC; break;
#endif
#ifdef GPIOD_BASE
case (3): port = GPIOD; RCC->AHBENR |= RCC_AHBPeriph_GPIOD; break;
#endif
#ifdef GPIOE_BASE
case (4): port = GPIOE; RCC->AHBENR |= RCC_AHBPeriph_GPIOE; break;
#endif
#ifdef GPIOF_BASE
case (5): port = GPIOF; RCC->AHBENR |= RCC_AHBPeriph_GPIOF; break;
#endif
#ifdef GPIOH_BASE
case (6): port = GPIOH; RCC->AHBENR |= RCC_AHBPeriph_GPIOH; break;
#endif
default : break;
}

disablePullUpAndPullDown();
}

void setAsDigitalInput() // MODER = 0
{
port->MODER &= ~(((int32_t)0x03) << (pinIndex * 2));
port->MODER |= (((int32_t)0x00) << (pinIndex * 2));
}

void setAsDigitalOutput() // MODER = 1
{
port->MODER &= ~(((int32_t)0x03) << (pinIndex * 2));
port->MODER |= (((int32_t)0x01) << (pinIndex * 2));
}

typedef int8_t AlternativeFunction;
void setAsAlternative(AlternativeFunction function) // MODER = 2
{
port->MODER &= ~(((int32_t)0x03) << (pinIndex * 2));
port->MODER |= (((int32_t)0x02) << (pinIndex * 2));
if (pinIndex < 8)
{
port->AFR[0] &= ~(((int32_t)0x0F) << (pinIndex * 4));
port->AFR[0] |= (((int32_t)function & 0x0F) << (pinIndex * 4));
}
else
{
port->AFR[1] &= ~(((int32_t)0x0F) << ((pinIndex - 8) * 4));
port->AFR[1] |= (((int32_t)function & 0x0F) << ((pinIndex - 8) * 4));
}
}

void setAsAnalogInput() // MODER = 3
{
disablePullUpAndPullDown();
port->MODER &= ~(((int32_t)0x03) << (pinIndex * 2));
port->MODER |= (((int32_t)0x03) << (pinIndex * 2));
}

void setAsAnalogOutput() // MODER = 3
{
disablePullUpAndPullDown();
port->MODER &= ~(((int32_t)0x03) << (pinIndex * 2));
port->MODER |= (((int32_t)0x03) << (pinIndex * 2));
}

void setAsPushPull() { port->OTYPER &= ~(1 << pinIndex); } // OTYPER = 0
void setAsOpenDrain() { port->OTYPER |= (1 << pinIndex); } // OTYPER = 1

void setOutputSpeed400kHz() { port->OSPEEDR &= ~(((int32_t)0x03) << (pinIndex * 2)); port->OSPEEDR |= (((int32_t)0x00) << (pinIndex * 2)); } // OSPEEDR = 0
void setOutputSpeed2MHz() { port->OSPEEDR &= ~(((int32_t)0x03) << (pinIndex * 2)); port->OSPEEDR |= (((int32_t)0x01) << (pinIndex * 2)); } // OSPEEDR = 1
void setOutputSpeed10MHz() { port->OSPEEDR &= ~(((int32_t)0x03) << (pinIndex * 2)); port->OSPEEDR |= (((int32_t)0x02) << (pinIndex * 2)); } // OSPEEDR = 2
void setOutputSpeed40MHz() { port->OSPEEDR &= ~(((int32_t)0x03) << (pinIndex * 2)); port->OSPEEDR |= (((int32_t)0x03) << (pinIndex * 2)); } // OSPEEDR = 3

void disablePullUpAndPullDown() { port->PUPDR &= ~(((int32_t)0x03) << (pinIndex * 2)); port->PUPDR |= (((int32_t)0x00) << (pinIndex * 2)); } // PUPDR = 0
void enablePullUp() { port->PUPDR &= ~(((int32_t)0x03) << (pinIndex * 2)); port->PUPDR |= (((int32_t)0x01) << (pinIndex * 2)); } // PUPDR = 1
void enablePullDown() { port->PUPDR &= ~(((int32_t)0x03) << (pinIndex * 2)); port->PUPDR |= (((int32_t)0x02) << (pinIndex * 2)); } // PUPDR = 2

inline void setToHigh() __attribute__((always_inline)) { port->BSRRL = pinMask; }
inline void setToLow() __attribute__((always_inline)) { port->BSRRH = pinMask; }
inline bool isHigh() __attribute__((always_inline)) { return (((port->IDR) & pinMask) != 0); }
inline bool isLow() __attribute__((always_inline)) { return (((port->IDR) & pinMask) == 0); }
inline void toggle() __attribute__((always_inline)) { if (isLow()) setToHigh(); else setToLow(); }

void lock()
{
volatile int32_t tempRegister = ((int32_t)1 << pinIndex);
GPIOA->LCKR = tempRegister + GPIO_LCKR_LCKK; // (1) Write LCKK bit to 1 and set the pin bits to lock
GPIOA->LCKR = tempRegister; // (2) Write LCKK bit to 0 and set the pin bits to lock
GPIOA->LCKR = tempRegister + GPIO_LCKR_LCKK ; // (3) Write LCKK bit to 1 and set the pin bits to lock
tempRegister = GPIOA->LCKR; // (4) Read the Lock register
if ((GPIOA->LCKR & GPIO_LCKR_LCKK) == 0) // (5) Check the Lock register (optional)
{
// TODO: manage an error
}
}

protected:
volatile GPIO_TypeDef * port;
volatile int8_t portIndex;
volatile int8_t pinIndex;
volatile int32_t pinMask;
};

////////////////////////////////////////////////////////////////////////////////////////////////////////////////

template <PIN pin>
class Pin : public PinBase
{
public:
Pin() : PinBase(pin) { }
};

////////////////////////////////////////////////////////////////////////////////////////////////////////////////

template <PIN pin>
class DigitalOutputPin : public PinBase
{
public:
DigitalOutputPin() : PinBase(pin)
{
setAsDigitalOutput();
setAsPushPull();
setOutputSpeed40MHz();
}
};

////////////////////////////////////////////////////////////////////////////////////////////////////////////////

template <PIN pin>
class LedOpenDrain : public PinBase
{
public:
LedOpenDrain() : PinBase(pin)
{
setAsDigitalOutput();
setAsOpenDrain();
setOutputSpeed10MHz();
off();
}

void on() { setToLow(); }
void off() { setToHigh(); }
};

......


--------------------
Кругозор некоторых людей - круг с нулевым радиусом. Они называют его "точкой зрения".
Go to the top of the page
 
+Quote Post
Сергей Борщ
сообщение Jun 21 2017, 11:23
Сообщение #6


Гуру
******

Группа: Модераторы
Сообщений: 8 455
Регистрация: 15-05-06
Из: Рига, Латвия
Пользователь №: 17 095



QUOTE (Forger @ Jun 21 2017, 14:14) *
Ооо! На каждую ногу выделить 12 байт памяти под указатель, маску и индексы? Ну да, у каждого свой подход. Оба имеют право на жизнь.


--------------------
На любой вопрос даю любой ответ
"Write code that is guaranteed to work, not code that doesn’t seem to break" (C++ FAQ)
Go to the top of the page
 
+Quote Post

Сообщений в этой теме
- _pv   С++, метод шаблонного класса как обработчик прерывания   Jun 12 2017, 16:45
- - conan   2. Нестатический метод класса можно вызывать тольк...   Jun 12 2017, 19:40
- - _pv   помойка нужна для, как мне казалось, упрощения код...   Jun 12 2017, 20:33
|- - AHTOXA   Цитата(_pv @ Jun 13 2017, 01:33) Uart ...   Jun 12 2017, 21:42
|- - conan   Цитата(_pv @ Jun 12 2017, 23:33) помойка ...   Jun 12 2017, 22:01
|- - Forger   Цитата(conan @ Jun 13 2017, 01:01) Нельзя...   Jun 19 2017, 18:32
|- - _pv   Цитата(conan @ Jun 13 2017, 04:01) Можно ...   Jun 20 2017, 09:35
|- - Forger   Цитата(_pv @ Jun 20 2017, 12:35) вот с эт...   Jun 20 2017, 10:40
- - sigmaN   Ну там в зависимости от везения может появляться н...   Jun 19 2017, 21:35
|- - Forger   Цитата(sigmaN @ Jun 20 2017, 00:35) Ну та...   Jun 20 2017, 05:34
- - sigmaN   Цитатавот с этим и вопрос, как объявить обработчик...   Jun 20 2017, 10:40
|- - _pv   Цитата(sigmaN @ Jun 20 2017, 16:40) Из об...   Jun 20 2017, 14:08
- - sigmaN   ну вот это вот Uart0<64> то зачем по всей пр...   Jun 20 2017, 15:42
|- - Forger   Цитата(sigmaN @ Jun 20 2017, 18:42) Какое...   Jun 21 2017, 06:24
- - Lagman   Вот посмотрите видео https://www.youtube.com/watch...   Jun 21 2017, 06:50
|- - Forger   Цитата(Сергей Борщ @ Jun 21 2017, 14:23) ...   Jun 21 2017, 11:44
- - sigmaN   Ну таки если бы это противоречило ООП то я бы с ва...   Jun 21 2017, 10:30
|- - Forger   Цитата(sigmaN @ Jun 21 2017, 13:30) Ну та...   Jun 21 2017, 10:45
- - sigmaN   Во-первых там 200Кб текста, а не мегабайт(вы внима...   Jun 21 2017, 11:32


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

 


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


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