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

Плавный переход C -> C++ под МК

В целом - нет. Есть множество сложных проектов, написанных на Си, и они прекрасно работают. Сейчас действует, в основном, мода на С××, а мода - это такая двоякая весчь..

Да, щас на меня накинутся адепты С××, дескать только ×× дал им (нужное написать). Хотя сам по себе ×× имеет неплохой инструментарий для высокого уровня абстракции. Но для низкого уровня - вы сами видите, сколько приходится изобретать ухищрений и оеольных путей для того, что на Си записывается очень просто и явно. Ну и ×× - далеко не идеальный язык, он на следовал недостатки Си и усугубил их. А большинство наворотов ×× сделано за счёт STL. 

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

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


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

11 minutes ago, EdgeAligned said:

Но для низкого уровня - вы сами видите, сколько приходится изобретать ухищрений и оеольных путей для того, что на Си записывается очень просто и явно

На плюсах точно также записывается то, что реализовано на С. Абсолютно одинаково.

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

У меня есть старые проекты чисто на С и они же переделанные под плюсы. На плюсах вышло гораздо проще и меньше писанины, да и код даже быстрее выходит, в силу того, что он нормально спроектирован и структурирован.

Просто у голого С есть потолок, который плюсы значительно расширяют. Си это лишь ЧАСТЬ плюсов, причем далеко не самая большая, хотя фундаментальная.

Кто уходит на плюсы, то как раз потому, что сталкиваются с ограниченности голого С. А кто уходит на плюсы под другим причинам - то это как раз и есть те, кто гонится за модой, этих граждан понять сложно :)

Т.е. если вы считаете, что голого С вам хватает, то значит так оно и есть, но лично для вас, а не вообще. Ведь расти есть всегда куда.

Например у тех же плюсов есть масса недостатков, которые устранены в C#...

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


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

1 hour ago, Forger said:

удобство, это когда просто объявляешь самый обычный не виртуальный метод в полях класса и где-то помечаешь что это обработчик

В стандарте на С/С++ нет функций-обработчиков прерываний.

1 hour ago, Forger said:

у вас должна быть где-то большая таблица оберток вокруг каждого обработчика

Зачем возле каждого? Это лишнее. Достаточно указателя на базовый class IRQ.

1 hour ago, Forger said:

короче, покажите ваш полный пример с содержимым этого обработчика и как он вызывается через вектора прерываний

Spoiler
////////////////////////////////////////////////////////////////////////////////
//
//  startup_stm32f407xx.cpp
//
////////////////////////////////////////////////////////////////////////////////

// GCC ARM compatible

#include <stddef.h>
#include "stm32f407xx.h"
#include "system_stm32f4xx.h"
#include "IRQ.h"

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

extern int main( void );

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

extern "C"
{
typedef void( *intfunc )( void );

extern "C" const intfunc __vector_table[];

void Reset_Handler();

void HardFault_Handler( void );
void NMI_Handler( void );
void MemManage_Handler( void );
void BusFault_Handler( void );
void UsageFault_Handler( void );
void DebugMon_Handler( void );

void Default_Handler( void );
void __attribute__((naked, noreturn)) Reset_Handler( void );

void xPortPendSVHandler( void ) __attribute__ (( naked ));
void xPortSysTickHandler( void );
void vPortSVCHandler( void ) __attribute__ (( naked ));

int __low_level_init(void);

#ifdef __VECTORS_IN_RAM__
    extern void* IRQ_handler[ MAX_INTERRUPT_HANDLERS ];
#endif

//void __libc_init_array();
extern void *_sidata, *_sdata, *_edata;
extern void *_sbss, *_ebss;
extern void *_estack;

// These magic symbols are provided by the linker.
extern void (*__preinit_array_start[]) (void) __attribute__((weak));
extern void (*__preinit_array_end[]) (void) __attribute__((weak));
extern void (*__init_array_start[]) (void) __attribute__((weak));
extern void (*__init_array_end[]) (void) __attribute__((weak));
extern void (*__fini_array_start[]) (void) __attribute__((weak));
extern void (*__fini_array_end[]) (void) __attribute__((weak));

//------------------------------------------------------------------------------

const intfunc
__vector_table[] __attribute__ ( ( section (".isr_vector_FLASH" ), used ) ) =
{
  (intfunc)&_estack ,
  &Reset_Handler,
  &NMI_Handler,
  &HardFault_Handler,
  &MemManage_Handler,
  &BusFault_Handler,
  &UsageFault_Handler,
  &Default_Handler,
  &Default_Handler,
  &Default_Handler,
  &Default_Handler,
  &vPortSVCHandler,
  &DebugMon_Handler,
  &Default_Handler,
  &xPortPendSVHandler,
  &xPortSysTickHandler,

  // External Interrupts

  &Default_Handler,
  &Default_Handler,
  &Default_Handler,
  &Default_Handler,
  &Default_Handler,
  &Default_Handler,
  &Default_Handler,
  &Default_Handler,
  &Default_Handler,
  &Default_Handler,
  &Default_Handler,
  &Default_Handler,
  &Default_Handler,
  &Default_Handler,
  &Default_Handler,
  &Default_Handler,
  &Default_Handler,
  &Default_Handler,
  &Default_Handler,
  &Default_Handler,
  &Default_Handler,
  &Default_Handler,
  &Default_Handler,
  &Default_Handler,
  &Default_Handler,
  &Default_Handler,
  &Default_Handler,
  &Default_Handler,
  &Default_Handler,
  &Default_Handler,
  &Default_Handler,
  &Default_Handler,
  &Default_Handler,
  &Default_Handler,
  &Default_Handler,
  &Default_Handler,
  &Default_Handler,
  &Default_Handler,
  &Default_Handler,
  &Default_Handler,
  &Default_Handler,
  &Default_Handler,
  &Default_Handler,
  &Default_Handler,
  &Default_Handler,
  &Default_Handler,
  &Default_Handler,
  &Default_Handler,
  &Default_Handler,
  &Default_Handler,
  &Default_Handler,
  &Default_Handler,
  &Default_Handler,
  &Default_Handler,
  &Default_Handler,
  &Default_Handler,
  &Default_Handler,
  &Default_Handler,
  &Default_Handler,
  &Default_Handler,
  &Default_Handler,
  &Default_Handler,
  &Default_Handler,
  &Default_Handler,
  &Default_Handler,
  &Default_Handler,
  &Default_Handler,
  &Default_Handler,
  &Default_Handler,
  &Default_Handler,
  &Default_Handler,
  &Default_Handler,
  &Default_Handler,
  &Default_Handler,
  &Default_Handler,
  &Default_Handler,
  &Default_Handler,
  &Default_Handler,
  &Default_Handler,
  &Default_Handler,
  &Default_Handler,
  &Default_Handler,
  &Default_Handler,
  &Default_Handler
};

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

// Iterate over all the preinit/init routines (mainly static constructors).
inline void __attribute__((always_inline)) __run_init_array (void)
{
  int count;
  int i;

  count = __preinit_array_end - __preinit_array_start;
  for (i = 0; i < count; i++)
    __preinit_array_start[i] ();

  count = __init_array_end - __init_array_start;
  for (i = 0; i < count; i++)
    __init_array_start[i] ();
}

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

extern "C" void __attribute__((naked, noreturn)) Reset_Handler()
{
    __disable_irq();

    if( __low_level_init() )  // Replace default CMSIS function SystemInit() for IAR compatibility
    {
        void **pSource, **pDest;

        for
        (
            pSource = &_sidata, pDest = &_sdata;
            pDest != &_edata;
            pSource++, pDest++
        )
        {
            *pDest = *pSource;
        }

        for( pDest = &_sbss; pDest != &_ebss; pDest++ )
        {
            *pDest = 0;
        }

        SystemCoreClock = 168'000'000;

        #if defined( __VECTORS_IN_RAM__) || defined( __DEBUG_SRAM__ )
            IRQ::moveVectorsToRAM();
        #endif

        IRQ::initCPPInterruptSubsystem();

        // Use with libc start files instead __run_init_array();
        //__libc_init_array();

        // Use with the "-nostartfiles" linker option instead __libc_init_array();
        __run_init_array();
    }

    main();
}

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

extern "C" void NMI_Handler( void )
{
    for(;;)
    {
        asm( "nop" );
    }
}

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

extern "C" void MemManage_Handler( void )
{
    for(;;)
    {
        asm( "nop" );
    }
}

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

extern "C" void BusFault_Handler( void )
{
    for(;;)
    {
        asm( "nop" );
    }
}

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


extern "C" void DebugMon_Handler( void )
{
    for(;;)
    {
        asm( "nop" );
    }
}

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


extern "C" void HardFault_Handler( void )
{
    for(;;)
    {
        asm( "nop" );
    }
}

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


extern "C" void UsageFault_Handler( void )
{
    for(;;)
    {
        asm( "nop" );
    }
}

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

}   // extern "C"

////////////////////////////////////////////////////////////////////////////////
//
//  The end of startup_stm32f407xx.cpp
//
////////////////////////////////////////////////////////////////////////////////
Spoiler
//      IRQ.cpp
//
////////////////////////////////////////////////////////////////////////////////

#include "IRQ.h"

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

IRQ* CPP_handler[ MAX_INTERRUPT_HANDLERS ];

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

extern "C" void Default_Handler( void )
{
    IRQn_Type
        irq_idx = ( IRQn_Type )( __get_IPSR() - 16 );

    if( CPP_handler[ irq_idx ] )
    {
        IRQ*
            cpp_irq = CPP_handler[ irq_idx ];

        cpp_irq -> IRQ_Handler();

        // Вызовем обработчики этого прерывания всех объектов, подключившихся
        // к нему.
        while( cpp_irq -> previouse_handler != 0 )
        {
            cpp_irq = cpp_irq -> previouse_handler;

            cpp_irq -> IRQ_Handler();
        }
    }
    else
    {
        #ifdef DEBUG
            asm( "nop" );
            for(;;){}
        #else
            abort();
        #endif
    }

}

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

void IRQ::initCPPInterruptSubsystem( void )
{
    memset( CPP_handler, 0, sizeof( CPP_handler ) );
}

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

IRQ::IRQ( void )
{
    previouse_handler = 0;
}

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

IRQ::~IRQ( void )
{
}

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

IRQ* IRQ::installInterruptHandler
(
    IRQn_Type   _IRQn   // See "stm32fXXX.h", enum IRQn_Type.
)
{
    if
    ( 
        ( _IRQn >= ( IRQn_Type )0 ) ||
        ( _IRQn < ( IRQn_Type )MAX_INTERRUPT_HANDLERS )
    )
    {
        previouse_handler = ( IRQ* )CPP_handler[ _IRQn ];
        CPP_handler[ _IRQn ] = this;

        NVIC_t::getInstance() -> enableIRQ( _IRQn );
    }

    return( previouse_handler );
}
                                             
////////////////////////////////////////////////////////////////////////////////

IRQ* IRQ::uninstallInterruptHandler
(
    IRQn_Type   _IRQn           // See "stm32f10x.h", enum IRQn_Type.
)
{
    IRQ*
        currentHandler = 0;

    if
    ( 
        ( _IRQn >= 0 ) || 
        ( _IRQn < ( IRQn_Type )MAX_INTERRUPT_HANDLERS )
    )
    {
        NVIC_t::getInstance() -> disableIRQ( _IRQn );
        currentHandler = ( IRQ* )CPP_handler[ _IRQn ];

        CPP_handler[ _IRQn ] = previouse_handler;
    }

    return( currentHandler );

}

////////////////////////////////////////////////////////////////////////////////
//
//  end of IRQ.cpp
//
////////////////////////////////////////////////////////////////////////////////

 

 

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


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

Ну это стандартная отговорка, дескать на ×× меньше писянины. Но я например знаю одного чела, который потратил не один год на переписывание заголовочных и прочих поставляемых файлов под каконы ×× только ради того, чтобы выглядело няшно-плюсово. 

Поэтому я и отметил, что ×× хорош для высокого уровня абстракции, но на низком уровне приходится много переписывать. В частности, даже постом выше это видно. Няшненко, но писанины доталова. 

Разговоры про потолок голого Си - это понятно. Потолок наступает на высоком уровне абстракции при попытке сделать няшненько и лампово. В основном, потолок касается полиморфизма и расширения STL. 

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


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

19 minutes ago, tonyk_av said:

Зачем возле каждого?

Так вот же эта таблица ))

IRQ* CPP_handler[ MAX_INTERRUPT_HANDLERS ];

А теперь посмотрите как происходит вызов прерывания в disasm вплоть до входа в саму виртуальную функцию того или иного класса.

Как понимаю, вам приходится класс, где требуется использовать обработчик, обязательно наследовать от класса IRQ?

т.е. если внутри одного класса требуется несколько обработчиков, то такая схема уже не сработает. Я правильно понял?

Я делал обработчики через виртуальные методы, мне это не зашло, вот пытаюсь вспомнить почему ))

  

19 minutes ago, tonyk_av said:

В стандарте на С/С++ нет функций-обработчиков прерываний.

Вот именно, нет, и это печально ((

 

 

10 minutes ago, EdgeAligned said:

Но я например знаю одного чела, который потратил не один год на переписывание заголовочных и прочих поставляемых файлов под каконы ×× только ради того, чтобы выглядело няшно-плюсово. 

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

 

 

10 minutes ago, EdgeAligned said:

Ну это стандартная отговорка

Нет, это правда жизни, через это прошел, поэтому знаю о чем говорю. Если бы плюсы не зашли, то так и сидел бы на голых сях ))

10 minutes ago, EdgeAligned said:

В основном, потолок касается полиморфизма и расширения STL.

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

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

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

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


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

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

Функций обработчиков прерываний нет в рассматриваемый языках. Нужно всего лишь получить адрес одной функции (для каждого вектора), реализующей начало  исполняемого кода прерывания и поместить этот адрес (число) в указанное место таблицы. 

 

12 минут назад, Forger сказал:

Полиморфизм - тоже редко, в простых проектах он не требуетс

Тогда как же у вас сокращается кол-во писянины то? 🙂 иль для вас "более читаемый" - это когда функции объединили под одними скобочками class {}? 

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


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

Just now, EdgeAligned said:

поэтому у меня нет иллюзий и воздействия моды. 

У вас какое-то странное предвзятое представление о тех, кто пользуется тем или иным инструментом. Плюсы - это прежде всего инструмент, как и голый С, а вопросы "моды" и т.п. это кмк не для этой темы.

 

3 minutes ago, EdgeAligned said:

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

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

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


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

9 minutes ago, Forger said:

Как понимаю, вам приходится класс, где требуется использовать обработчик, обязательно наследовать от класса IRQ?

Естественно.

9 minutes ago, Forger said:

если внутри одного класса требуется несколько обработчиков, то такая схема уже не сработает. Я правильно понял?

Нет, не правильно.

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

Spoiler
////////////////////////////////////////////////////////////////////////////////

void MB_RTU_UART::IRQ_Handler( void )
{
	.....

    IRQn_Type
        irq = IRQ::getActiveIRQn() ;

    if( irq == IRQn_dma_tx )
    {
        // Обработка прерывания от потока ПДП передатчика.

		......
    }
    else if( irq == usart_IRQn )
    {
        // Запрос IDLE сбросится при последовательном чтении SR и DR (ниже).
        // Сначала прочитаем и сохраним копию SR.
        volatile uint32
            usart_sr = usart -> SR;

        // Обработка прерывания от передатчика.
        //----------------------------------------------------------------------

        if( usart_sr & USART_SR_TC )
        {
			......
        }

        // Обработка прерывания от приёмника.
        //----------------------------------------------------------------------

        if( usart_sr & USART_SR_IDLE )
        {
			......
        }
    }
    else
    {
        // Чушь какая-то. Поймали прерывание, на которое не подписывались.
        // Занавес!
        abort();
    }
}

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

 

 

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


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

7 minutes ago, EdgeAligned said:

Тогда как же у вас сокращается кол-во писянины то?

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

 

9 minutes ago, EdgeAligned said:

это когда функции объединили под одними скобочками class {}? 

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

Ну и читаемость куда выше, ведь длина названий функций куда короче, чем на си, не надо делать чудовищные по длине префиксы, чтобы избежать проблем с совпадающими именами )

2 minutes ago, tonyk_av said:

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

А как происходит вызов из обработчика такой виртуальной функции, в disasm, от момента срабатывания исключения до входа внутрь обработчик ?

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


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

Длина названий функций не сокращается, используется просто другой разделитель - :: вместо _ 

Модули на Си точно так же переносятся из проекта в проект, просто выглядят чуть иначе. 

Я ж говорю - у меня нет иллюзий за счёт того, что я прошёл все это даже более глуього и более трезво

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

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


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

13 minutes ago, Forger said:

А как происходит вызов из обработчика такой виртуальной функции

Я же показал код:

const intfunc
__vector_table[] __attribute__ ( ( section (".isr_vector_FLASH" ), used ) ) =
{
  (intfunc)&_estack ,
  &Reset_Handler,
  &NMI_Handler,
  &HardFault_Handler,
  &MemManage_Handler,
  &BusFault_Handler,
  &UsageFault_Handler,
  &Default_Handler,
  &Default_Handler,
  &Default_Handler,
  &Default_Handler,
  &vPortSVCHandler,
  &DebugMon_Handler,
  &Default_Handler,
  &xPortPendSVHandler,
  &xPortSysTickHandler,

  // External Interrupts

  &Default_Handler,
  &Default_Handler,
  &Default_Handler,

.....
extern "C" void Default_Handler( void )
{
    IRQn_Type
        irq_idx = ( IRQn_Type )( __get_IPSR() - 16 );

    if( CPP_handler[ irq_idx ] )
    {
        IRQ*
            cpp_irq = CPP_handler[ irq_idx ];

        cpp_irq -> IRQ_Handler();

        // Вызовем обработчики этого прерывания всех объектов, подключившихся
        // к нему.
        while( cpp_irq -> previouse_handler != 0 )
        {
            cpp_irq = cpp_irq -> previouse_handler;

            cpp_irq -> IRQ_Handler();
        }
    }
    else
    {
        #ifdef DEBUG
            asm( "nop" );
            for(;;){}
        #else
            abort();
        #endif
    }

}

 

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


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

55 minutes ago, EdgeAligned said:

Длина названий функций не сокращается, используется просто другой разделитель - :: вместо _ 

Это только для пространств имен и то это легко решается с помощью локальных using.

Для объектов такие длинные имена не требуются.

 

 

55 minutes ago, EdgeAligned said:

Я ж говорю - у меня нет иллюзий за счёт того, что я прошёл все это даже более глуього и более трезво

Очень раз за вас, видимо применение "::" где надо и не надо наложило свои отпечатки на впечатления от в целом весьма и весьма гибкого инструмента ))

 

46 minutes ago, tonyk_av said:

Я же показал код:

Я про disasm код (по моему повторяюсь уже в третий раз ))), вопрос в то, насколько эффективно такое решение в сравнении с обычными С-обработчиками?

Речь об эффективности тоже. Это - вторая  не менее важная часть всей затеи )

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


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

А вы можете похвастаться непогрешимым безошибочным владением языком без опечаток? 

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


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

5 minutes ago, EdgeAligned said:

А вы можете похвастаться непогрешимым безошибочным владением языком без опечаток? 

не очень хочу чем-то хвастаться, и какое это имеет отношение к теме?

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


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

Ну вы обвиняете с плохом знании языка. Вот я и спрашиваю - а вы сами достаточно хорошо его знаете? 

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


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

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

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

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

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

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

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

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

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

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