Перейти к содержанию
    

С++, обработчик прерывания как статическая ф-я класса.

мдя... С++ пошел в микроконтроллеры. кчему бы это ;)

тенденция однако..... вывод; много лишнего озу и флеша ;)

 

если не использовать "гадости" типа виртуальных функций, RTTI , эксепшены и прочих архитектрных излишестьв то получается удобно и почти бесплатно.

пробывал сделать обертку для FreeRTOS, все задачи наследуются от базового класа в котором все есть - отается переопределить функцию задачи. в резултате кода приложения стало процентов на 90 :) меньше, стало проще читать код. скорость не страдает, размер чуток - небольшие с++ накладные расходы. такчто я думаю что при умном применении с++ польза есть.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

мдя... С++ пошел в микроконтроллеры. кчему бы это ;)

тенденция однако.....

Да уж C# давно пошёл...

Я даже кидал ссылку, для PIC чего-то пытались сваять

Не по теме, конечно, но всё же...

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Да уж C# давно пошёл...

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

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

если не использовать "гадости" типа виртуальных функций...

Ну Вы зря так про виртуальные ф-ции! Они тянут, конечно, за собой дополнительный код, но иногда без никак!

Как пример, после некоторой адаптации State Machine к (выработанным мною, для себя) требованиям к встраиваемой технике (в частности отказался от динамической памяти и заставил все работать в стеке), я познал дао (или дзен? :-)

 

Как бы то ни было, предпочитаю статический полиморфизм динамическому (выражаясь словами Дэвида Вандевурда, Николайа М. Джосаттиса). Он меньше места занимает, потому как, оптимизируется лучше.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

    static void IRQHandler( ) asm( "__vector_10" ); // Или, не 10 ( взято "с потолка" ), в любом случае, меняя нумер можно
                                                                                 //  подставить куда угодно
};

Вот-вот. 10 надо подставлять вручную, что убивает всю красоту.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Вот-вот. 10 надо подставлять вручную, что убивает всю красоту.

Не обязательно. :-)

В оригинале ( C++ Interrupts ) использовался макрос:

#define CLASS_IRQ(name, vector) \
    static void name(void) asm(__STRINGIFY(vector)) \
    __attribute__ ((signal, __INTR_ATTRS))

Он рабочий, как я понял, только с некоторыми оговорками:

  1. при описании тела ф-ции необходимо добавить перед ней 'extern "C"'
  2. заменить "YYYYYYY_XXX_vect" (например, TIMER0_OVF_vect) на "__vector_XX"

Второй пункт можно реализовать через макросы (что-то навроде #define TIMER0_OVF_vect __vector_XX)

 

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

 

Да и скрыто это будет от енд-юзера... Код получается практически повторно используемым. Фактически, как это нынче модно называть, Framework'ом. Таким образом можно охватить фактически всю перефирию контроллера и код станет вполне повторно используемым. Но здесь есть одна засада! Начну немного издалека.

 

В Delphi и .NET, компоненты на форме делегируют обработку событий методам формы, что весьма удобно и выглядит красиво.

Хотелось бы реализовать что-то подобное. Т.е. класс таймера, к примеру реагирует на прерывание от него и, например, перезагружает регистр счетчика необходимым значением, на этом его функции обработки прерывания заканчиваются. Сама же обработка события делегируется другому объекту для обработки и следованию общей логики выполнения программы. Сама идея не нова -- паттерн command из книжки GoF. Лично мне очень понравилась реализация этого паттерна от Александреску. После того, как продрался через его описание в книжке. ИМХО, объяснять Александреску нихрена не умеет! Вот только есть нюанс, любые реализации этого паттерна используют виртуальные ф-ции, что тянет за собой доп код и мешает оптимизации. В случае Александреску, получается пара ф-ций "пересылки" аргументов к месту назначения. Даже после оптимизации все равно останется косвенный переход по VTable, т.ч. "сквозной" оптимизации не получится. И если для ARM'ов еще можно махнуть рукой или плюнуть (нужное подчеркнуть), то, например, для ATmega48, плеваться придется много и долго...

Есть вариант решения с использованием шаблонов. Данный пример для "большой" машины и только в целях иллюстрации принципа (не надо мне потом предъявлять по поводу использования std::list на ATmega48! :-).

/*
* Command.h
*
*  Created on: 26.05.2010
*      Author: damon
*/

#ifndef COMMAND_H_
#define COMMAND_H_

#include <iostream>
#include <list>
#include <string>

template< class Handlers >
class Command: public Handlers
{
public:
    Command( ) { }

    void Signal( int sign )
    {
        Handlers::OnSignal( sign );
    }
};

class CommandHandler
{
private:
    std::string str_;

public:
    CommandHandler( char *str )
    {
        str_ = str;
    }

    void Print( int val )
    {
        std::cout << str_ << std::endl << "\t Полученное значение: " << val << std::endl;
    }
};

class CommandSwitcher
{
private:
    std::list< CommandHandler * > handlers_;

public:
    void AddHandler( CommandHandler *handler )
    {
        handlers_.push_back( handler );
    }

    void operator+=( CommandHandler *handler )
    {
        AddHandler( handler );
    }

    void DelHandler( CommandHandler *handler )
    {
        handlers_.remove( handler );
    }

    void operator-=( CommandHandler *handler )
    {
        DelHandler( handler );
    }

    void OnSignal( int sign )
    {
        std::for_each( handlers_.begin( ), handlers_.end( ), bind2nd( mem_fun( &CommandHandler::Print ), sign ) );
    }
};

#endif /* COMMAND_H_ */

 

//main.cpp
#include "Command.h"

int main()
{
    Command< CommandSwitcher > command;

    CommandHandler firstHandler(  ( char * ) "First handler"  );
    CommandHandler secondHandler( ( char * ) "Second handler" );
    CommandHandler thirdHandler(  ( char * ) "Third handler"  );

    command += &firstHandler;
    command += &secondHandler;
    command += &thirdHandler;

    command.Signal( 10 );

    std::cout << std::endl;

    command -= &firstHandler;

    command.Signal( 1 );

    return 0;
}

 

Таким образом вся логика "коммутации" сигнала о событии сосредоточена в классе CommandSwitcher, который никоим образом не зависит от класса Command. При этом, при использовании класса Command в другом проекте не понадобится вносит в него никаких изменений! Меняться будет только CommandSwitcher!

 

При этом виртуальные ф-ции не используются, а поскольку шаблонные методы описываются в хидере, есть надежда на их "сквозную" оптимизацию, что благотворно скажется на размере и скорости прошивки контроллера!

Изменено пользователем Damon

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Присоединяйтесь к обсуждению

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

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

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...