|
С++, метод шаблонного класса как обработчик прерывания |
|
|
|
Jun 21 2017, 09:49
|

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...
|
|
|
|
|
Jun 21 2017, 10:21
|

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

|
Цитата(sigmaN @ Jun 21 2017, 12:49)  И как результат имеем адсолютно отсутствующий оверхед и не отступаем от заветов объектно-ориентированного программирования. Оверхед, оверхед, оверхед... Это напоминает автовладельца, которого беспокоит царапина на крыле его авто при том, что ее кузов уже напрочь прогнил  Если только и думать об этом мифическом оверхеде, то никогда не получится создавать действительно полноценный ООП-код. Цитата(sigmaN) А вот вам моя почти на 100% переработанная и допиленная реализация этой идеи. ~1Мбайт текста ... для портов I/O  Странно, у меня это все влезает в один файлик в 10кб текста (для одного МК). Мне даже как-то стыдно стало
--------------------
Кругозор некоторых людей - круг с нулевым радиусом. Они называют его "точкой зрения".
|
|
|
|
|
Jun 21 2017, 10:45
|

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

|
Цитата(sigmaN @ Jun 21 2017, 13:30)  Ну таки если бы это противоречило ООП то я бы с вами согласился. Мегабайты кода на ровном месте как-то не очень вяжутся с ООП Полагаю, что наши понятия читаемого кода сильно разнятся: я лучше потеряю полкило ОЗУ МК на неком оверхеде, чем буду разгребрать кучу файлов с красными глазами, хотя бы пытаясь понять их работу.... Цитата А так - просто бла бла бла и попытка акцентировать внимание на и так всем известным прописным истинам о преждевременной оптимизации и оверхеде.... Скучно ) Судя по вашему коду, оптимизация не то что преждевременная, она по ходу являлась мотиватором по созданию этой груды тесно связанных файлов. Честно говоря, впервые сталкиваюсь с таким. Напоминает "из пушки по воробьям" Один только вопрос: не жалко было тратить столько времени на эту детскую задачку?
--------------------
Кругозор некоторых людей - круг с нулевым радиусом. Они называют его "точкой зрения".
|
|
|
|
|
Jun 21 2017, 11:14
|

Профессионал
    
Группа: Свой
Сообщений: 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(); } };
......
--------------------
Кругозор некоторых людей - круг с нулевым радиусом. Они называют его "точкой зрения".
|
|
|
|
|
Jun 21 2017, 11:32
|

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...
|
|
|
|
|
Jun 21 2017, 11:44
|

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

|
Цитата(Сергей Борщ @ Jun 21 2017, 14:23)  Ооо! На каждую ногу выделить 12 байт памяти под указатель, маску и индексы? Если после сборки проекта остается куча невостребованного ОЗУ во много-много кБ (который обычно нужен для отладки), то это не представляет никаких проблем. Экономия на спичках  По мне важнее, чтобы все это можно было читать обычными людьми, а не т. н."вассерманами". Цитата Во-вторых я понятия не имею как большой объем кода вообще вяжется с ООП ООП подразумевает читаемый людьми код, и чем меньше этого, тем легче его читать и сопровождать. При переводе структурного кода на ООП, читаемость кода обычно резко улучшается (если конечно его объем не возрастает в десятки, а то и сотни раз). Чем проще конструкции, используемые в коде с ООП, тем более читаем этот код и тем более понятен он другим людям. Многие не пользуются даже шаблонами, но при этом создают вполне понятный и простой ООП код (пусть он без шаблонов и не совсем ООП). Простой код не требует документации, он понятен сходу при чтении. Разве что нужна задокументировать хотя бы в простом виде иерархию классов. Поэтому "теплое" в данном случае очень даже "мягкое"  Цитата(sigmaN @ Jun 21 2017, 14:32)  Во-первых там 200Кб текста, Беру свои слова назад, это ж все меняет! Цитата Я думаю до такого уровня просто надо дорасти. Так точно, Ваше Сиятельство, будем стараться! Цитата Взглянул я на вашу реализацию... Это конечно вещи которые и сравнивать то нельзя. Ну, да, куда уж мне до метапрограммирования ... пинов  Цитата Всему своё место и применение. Ни больше ни меньше ) Абсолютно согласен!
--------------------
Кругозор некоторых людей - круг с нулевым радиусом. Они называют его "точкой зрения".
|
|
|
|
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|