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

 
 
2 страниц V  < 1 2  
Reply to this topicStart new topic
> С++, метод шаблонного класса как обработчик прерывания
sigmaN
сообщение Jun 21 2017, 09:49
Сообщение #16


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
Сообщение #17


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

Группа: Свой
Сообщений: 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
sigmaN
сообщение Jun 21 2017, 10:30
Сообщение #18


I WANT TO BELIEVE
******

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



Ну таки если бы это противоречило ООП то я бы с вами согласился. А так - просто бла бла бла и попытка акцентировать внимание на и так всем известным прописным истинам о преждевременной оптимизации и оверхеде.... Скучно )


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


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

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



Цитата(sigmaN @ Jun 21 2017, 13:30) *
Ну таки если бы это противоречило ООП то я бы с вами согласился.

Мегабайты кода на ровном месте как-то не очень вяжутся с ООП laughing.gif

Полагаю, что наши понятия читаемого кода сильно разнятся: я лучше потеряю полкило ОЗУ МК на неком оверхеде, чем буду разгребрать кучу файлов с красными глазами, хотя бы пытаясь понять их работу....

Цитата
А так - просто бла бла бла и попытка акцентировать внимание на и так всем известным прописным истинам о преждевременной оптимизации и оверхеде.... Скучно )

Судя по вашему коду, оптимизация не то что преждевременная, она по ходу являлась мотиватором по созданию этой груды тесно связанных файлов.
Честно говоря, впервые сталкиваюсь с таким. Напоминает "из пушки по воробьям" wacko.gif
Один только вопрос: не жалко было тратить столько времени на эту детскую задачку? wink.gif


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


Гуру
******

Группа: Модераторы
Сообщений: 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
Сообщение #21


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

Группа: Свой
Сообщений: 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
Сообщение #22


Гуру
******

Группа: Модераторы
Сообщений: 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
sigmaN
сообщение Jun 21 2017, 11:32
Сообщение #23


I WANT TO BELIEVE
******

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



Во-первых там 200Кб текста, а не мегабайт(вы внимательнее посмотрите что там папка STM32 затянула на 700кб, в которую я даже не заглядывал)

Во-вторых я понятия не имею как большой объем кода вообще вяжется с ООП...... Не путайте теплое с мягким пожалуйста.

В-третьих там всё прекрасно структурированно и раскидано на независимые модули. Не думаю, что у вас было достаточно времени на изучение исходников, чтобы отметить неуместную "тесную связь"... Единственное, что там есть сложного - это реализация списков линий и utils, который лежит рядом с ней.
Всё что вокруг TPin и обертки регистров - элементарно, понятно и очень модульно. Это подтверждается представленными реализациями для совершенно различных архитектур, в которых меняется только один файл.

Цитата
Один только вопрос: не жалко было тратить столько времени на эту детскую задачку?
Мне нет. Я прекрасно по упражнялся в мета программировании на С++(особенно при реализации списков линий и вводе концепии ForEach для списка типов), получил огромное кол-во опыта и использую полученную библиотеку в продакшине! Она прекрасно и красиво решает поставленную задачу, полностью отделяет реализацию GPIO от кода драйверов, при этом не создавая не нужных экземпляров там, где в асме должна появиться одна инструкция по типу BSET ODR,#1... Я думаю до такого уровня просто надо дорасти.

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

Спорить здесь в таком ключе контр продуктивно. Вы передаете номер пина, вам нравится? Отлично!

Я всего лишь выложил реализацию как аргумент в пользу утверждения, что не все статические классы одинаково вредны. Равно как и создание экземпляров. Всему своё место и применение. Ни больше ни меньше )


Add:
Взглянул я на вашу реализацию... Это конечно вещи которые и сравнивать то нельзя. Но если вам нравится то ОК )))


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


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

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



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

Если после сборки проекта остается куча невостребованного ОЗУ во много-много кБ (который обычно нужен для отладки), то это не представляет никаких проблем. Экономия на спичках sm.gif
По мне важнее, чтобы все это можно было читать обычными людьми, а не т. н."вассерманами".


Цитата
Во-вторых я понятия не имею как большой объем кода вообще вяжется с ООП

ООП подразумевает читаемый людьми код, и чем меньше этого, тем легче его читать и сопровождать.
При переводе структурного кода на ООП, читаемость кода обычно резко улучшается (если конечно его объем не возрастает в десятки, а то и сотни раз).
Чем проще конструкции, используемые в коде с ООП, тем более читаем этот код и тем более понятен он другим людям.
Многие не пользуются даже шаблонами, но при этом создают вполне понятный и простой ООП код (пусть он без шаблонов и не совсем ООП).
Простой код не требует документации, он понятен сходу при чтении. Разве что нужна задокументировать хотя бы в простом виде иерархию классов.
Поэтому "теплое" в данном случае очень даже "мягкое" wink.gif

Цитата(sigmaN @ Jun 21 2017, 14:32) *
Во-первых там 200Кб текста,
Беру свои слова назад, это ж все меняет!

Цитата
Я думаю до такого уровня просто надо дорасти.
Так точно, Ваше Сиятельство, будем стараться!

Цитата
Взглянул я на вашу реализацию... Это конечно вещи которые и сравнивать то нельзя.

Ну, да, куда уж мне до метапрограммирования ... пинов lol.gif


Цитата
Всему своё место и применение. Ни больше ни меньше )
Абсолютно согласен!


--------------------
Кругозор некоторых людей - круг с нулевым радиусом. Они называют его "точкой зрения".
Go to the top of the page
 
+Quote Post

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

 


RSS Текстовая версия Сейчас: 29th June 2025 - 21:46
Рейтинг@Mail.ru


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