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

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

Само собой использование STL в программе под микроконтроллер сомнительно, так как, к примеру, работа с STL в Keil uVision 4 (видимо их порт STL) обходится в минимум 40 Кбайт (собрал пример из Keil examples). Поэтому выходом из этой ситуации вижу использование либо специальных готовых light библиотек либо написание базовых шаблонов/классов самому. Но так уже стадия "начинающий и все хочу попробовать" прошла уже давно, поэтому писать самому не сильно тянет.

Кто какие C++ библиотеки использует для работы с периферией и данными?

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


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

Я использую исключительно свои библиотеки. Писать их приходится всего один раз.

Все проекты построены под одному и тому же шаблону, прототипу.

Для процов, к которым нет нормального C++ компилятора и среду, построение аналогичное, но не такое красивое :(

 

Например, вот так выглядит весь main.cpp:

#include "TApplication.h"

// Единственный экзэмпляр приложения
static TApplication application; 

int main()
{
    application.run();
}

// Системный таймер для синхронизации приложения (период составляет ровно 1 мс)
extern "C" void SysTick_Handler()
{
    application.synchronize();
}

 

Заметьте - во всем проекте только один глобальный объект, да и тот виден только в main.cpp

 

Вот часть TApplication.h:

#include "..\Target\TTargetSTM32.h"
#include "..\RTOS\RTOS_TNKernel.h"

.....

class TApplication
{
public:
    void run(void);
    inline void synchronize(void) { _rtos.synchronize(); }

    // для примера
    void LED_On(void) { _target.setPinToLOW(PORT_LED_RED, PIN_LED_RED); }    // Включить красный светодиод
    void LED_Off(void) { _target.setPinToHIGH(PORT_LED_RED, PIN_LED_RED); }    // Выключить красный светодиод

private:
    class TThreadDisplay : public TThread<THREAD_DISPLAY_STACK_SIZE, THREAD_DISPLAY_PRIORITY>
    {

        typedef UNSIGNED8 TCommand;    
        typedef UNSIGNED8 TData;
        typedef UNSIGNED8 TPositionX;
        typedef UNSIGNED8 TPositionY;
        typedef const char TChar;
    public:
        virtual void initialize(void * bodyArgument);
    private:
        virtual void body(void);
        void fill(TData);
        void gotoXY(TPositionX, TPositionY);
        void sendCommand(TCommand);
        void sendData(TData);
        void printChar(TChar);
        void printString(TChar*, TPositionX, TPositionY);
        THardwareSTM32 * _target;
    };

    class TThreadWatchDog : public TThread<THREAD_WATCH_DOG_STACK_SIZE, THREAD_WATCH_DOG_PRIORITY>
    {
        virtual void initialize(void * bodyArgument);
        virtual void body(void);
        THardwareSTM32 * _target;
    };

.......
    
private:
    TKernel                    _rtos;
    THardwareSTM32            _target;
    TThreadDisplay            _threadDisplay;

.....
};

 

Вот часть TApplication.cpp:

void TApplication::TThreadWatchDog::initialize(void * bodyArgument) 
{ 
    _target = (THardwareSTM32*)bodyArgument; 
    _target->initializeWatchDogTimer(12); // Период сторожевого таймер 12 мс
}

void TApplication::TThreadWatchDog::body(void)
{
    _target->updateWatchDogTimer(); // Сбрасывать сторожевой таймер каждые 10 мс
    sleep(10);
}

 

Вот часть THardwareSTM32.h:

#include <stdlib.h>
#include <stdio.h>
#include <string.h>

......

typedef unsigned            UNSIGNED;
typedef unsigned char        UNSIGNED8;
typedef unsigned short        UNSIGNED16;
typedef unsigned int        UNSIGNED32;
typedef unsigned long long     UNSIGNED64;

typedef signed char            SIGNED8;
typedef signed short        SIGNED16;
typedef signed int            SIGNED32;
typedef signed long long     SIGNED64;

typedef float                FLOAT32;
typedef double                FLOAT62;

........

class THardwareSTM32
{
public:
    typedef UNSIGNED8    TInterruptChannel;
    typedef UNSIGNED8    TInterruptPreemptionPriority;
    typedef UNSIGNED8    TInterruptSubPriority;
    typedef UNSIGNED32    TSystemTimerPeriodMs;
    typedef UNSIGNED16    TWatchDogTimerPeriodMs;
    typedef UNSIGNED32    TUserTimerPeriodUs;
    typedef UNSIGNED8    TUserTimerChannel;

.....

    void reset(void);
    void initializeWatchDogTimer(TWatchDogTimerPeriodMs);
    void updateWatchDogTimer(void);

    void setSystemFrequency(TSystemFrequency);
    void initializeMainTimer(TSystemTimerPeriodMs);

    THardwareSTM32();
    ~THardwareSTM32() { reset(); }

....
    TSystemFrequency GetSystemFrequency() const { return(_systemFrequency); }

    void initializeUserTimer(TUserTimerChannel channel, TUserTimerPeriodUs periodUs);
    void userTimerInterruptHandler(TUserTimerChannel channel);

    void initializePIN(GPIO_TypeDef*, TGPIO_Pins, TGPIO_Mode, TGPIO_Speed);

    inline void setPinToHIGH(GPIO_TypeDef* GPIOx, TGPIO_Pins pin)
        { GPIOx->BSRR = pin; }

    inline void setPinToLOW(GPIO_TypeDef* GPIOx, TGPIO_Pins pin)
        { GPIOx->BRR = pin; }

    inline bool isPinHIGH(GPIO_TypeDef* GPIOx, TGPIO_Pins pin)
        { return((GPIOx->IDR & pin) != 0); }

    inline bool isPinLOW(GPIO_TypeDef* GPIOx, TGPIO_Pins pin)
        { return((GPIOx->IDR & pin) == 0); }
....
private:
    inline void disableAllInterrupts(void) { asm ("cpsid  I"); }
    inline void enableAllInterrupts(void) { asm ("cpsie  I"); }
.....
private:
    TSystemFrequency    _systemFrequency;
....
};

 

В итоге, аппартная, т.е. платформозависимая часть изолирована от основного кода - Application, RTOS, если используется - тоже изолирована от кода, поскольку RTOS - тоже отчасти платформозависима.

Глобальных переменных вообще нет! (кроме одной - типа TApplication, которую никто и "не видит"). Подобное построение я позаимствовал из старого-доброго Borland Builder C++. В принципе, по мне - у них задумка хорошая, но уж больно "тяжелая".

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

Шаблоны использую только свои, в них использую очень простые вещи.

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

Потом, если позволяет время, можно легко оптимизировать куски низкоуровневого кода.

В принципе, весь проект целиком можно написать на ПК, а потом "подцепить" к нему соответствующий железу THardware и TKernel (RTOS).

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


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

В принципе, весь проект целиком можно написать на ПК, а потом "подцепить" к нему соответствующий железу THardware и TKernel (RTOS).

Я пишу на С, а поступаю точно также -- вся аапликушная часть кода пишется и отлаживается на PC. Просто вместо классов используются HAL модули, которые я подменяю при сборке на PC и для target платформы.

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


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

... выходом из этой ситуации вижу использование либо специальных готовых light библиотек либо написание базовых шаблонов/классов самому. ....

 

В принципе, верное решение.

 

Это мне напомнило извечный вопрос всех времен- использовать printf или не использовать?

 

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

Где проблем с ресурсами нет - можно и STL и Linux и все, что позволяет решить задачу быстрее и проще.

А так - библиотек и исходников и Инете полно на все вкусы и под разные задачи, одной - на все случаи жизни - ИМХО нет и быть не может.

 

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


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

К моему удивлению, в Keil есть поддержка исключений, хотя дает +20Кб и неизвестно сколько к времени выполнения..

 

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


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

К моему удивлению, в Keil есть поддержка исключений, хотя дает +20Кб и неизвестно сколько к времени выполнения..

Поддержка исключений была и есть "в ARM". "В Keil" эта поддержка появилась после того, как они были великодушно куплены компанией ARM :biggrin:

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


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

А давайте помусолим uSTL (ссылка была раньше).

1. какие видятся минусы и плюсы использования?

2. кто в каких проектах использовал? где может быть применена эта библиотека (пример какой-нибудь для начинающих =), чтоб понять куда можно прикручивать ). И стоит ли?

3. во что компилируется проект с данной библиотекой: объем кода огромен ?

4. Если код получается небольшим, за счет чего это достигается??? какие трюки?

5. Как я понял одна из плюшек - это Memblocks and Memlinks, которые организованы как классы и содержат в себе все контейнеры, создаваемые в проге, т.е. все они в одном месте локализованы.

В STL векторы, например, у нас динамические: если не хватает их размерности, то при достижении конца вектора резервируется при помощи new в два раза большая память. т.е. если мы используем некий вектор на 1024 отсчетов, но должны принять 1060 отсчетов, то по достижении индекса 1023 у нас размерность станет 2048, хотя храниться будут только 1060 значений. Для компов - это пустяк (хотя и там оптимизируется при помощи, вроде бы, метода resize(); ), а для embedded - ужас.

И пока не дошло вот что: при помощи Memblocks and Memlinks получается сделать вектора в uSTL статическими?????

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

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


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

Использую для ARM (всех) компилятор C++ и очень доволен (keil).

Шаблоны в арме не пользовал, не было необходимости.

Использую для вывода printf, и тоже доволен.

Единственное ограничение - работаю только со статическим распределением памяти на этапе запуска программы.

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

 

 

 

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


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

Спасибо!

 

а на вопросы кто-нибудь прольет свет?

 

 

 

Использую для ARM (всех) компилятор C++ и очень доволен (keil).

А можете уточнить по АРМам. ведь они бывают очень крутыми Arm9, ARM11 ! Просто волнует информация о том, при каком объеме памяти на борте процессора, тактовой частоте и еще каких-нибудь значимых параметрах, о которых могу и не подозревать, можно использовать С++, шаблоны, ту же uSTL или другие библиотеки.

Я просто заложил в устройство TMS320F28235: Frequency (MHz) 150; RAM (KB) 68; Flash (KB) 512.

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

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


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

Просто волнует информация о том, при каком объеме памяти на борте процессора, тактовой частоте и еще каких-нибудь значимых параметрах, о которых могу и не подозревать, можно использовать С++, шаблоны,
Наличие ОЗУ и адресуемого стека. Необходимый объем зависит от вашей задачи. Но везде, где можно писать на С, можно писать и на С++ с шаблонами, наследованием и т.д. Активно используя и голову, разумеется. STL и исключения - другой вопрос, там надо смотреть на реализацию, пробовать.

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


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

можно писать и на С++ с шаблонами, наследованием и т.д. Активно используя и голову, разумеется.

голову нужно ставить на место), привыкать к ООП: к ООП применительно к embedded в связке с ОСРВ (будет у меня DSP/BIOS). вот тут не все понятно. Например, что брать за сущности, если , скажем, требуется сделать детектор : отдельные матлабовские блоки умножителей, дециматоров , фильтров оформлять разными классами или же делать одним классом под названием DetectorClass, куда и впихнуть весь алгоритм работы детектора?... (склоняюсь ко второму).

 

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

Хочется понять как повторить с полным пониманием происходящего то, о чем пишется во 2ом сообщении, как прикручивать ОСРВ к этому. А в общем, Как достичь подобного просветления =) ! ) ????

:smile3046:

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

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


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

Использую и на 128КБайт и на 256МБайт (тут уже линукс и винСЕ).

Память не критерий.

Зачем писать на чистом С реализацию ++? В этом случае надо использовать C++.

Инкапсуляция, Полиморфизм, Наследование - приоритеты в таком порядке.

На С++ даже обработчик прерываний (STM32F1хх) нормально получается ( с использование __forceinlice).

Например на 3-х уартах висят однотипные устройства (SIM и SAM модули).

Как только я начинаю передавать в функции указатели на структуры-описатели - то при рефакторинге сразу перехожу на классы.

 

 

 

 

 

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


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

Зачем писать на чистом С реализацию ++? В этом случае надо использовать C++.

да, я сместил вектор своего развития в сторону С++, и дома в после рабочее время пытаюсь углубляться, ставя задачи из компьютерного зрения и openCV. Бесплатные курсы пытаюсь проходить, связанные с этой темой, которые одна фирма у нас устраивает.

 

 

 

Инкапсуляция, Полиморфизм, Наследование - приоритеты в таком порядке.

СПС! за советы. Вот, кстати, таких советов и не хватает молодым - таких, как, Ваши и как, например, в книжке Экеля Thinking in C++ в Приложении Б "советы по программированию". Очень дельные советы на мой взгляд. Были б такие в С++ embedded ... Кстати, товарищ Neiver выкладывал подобный труд-статью , которая продублирована была на EasyElectronics . за что спасибо.. Но это капля в море и системной картины не вырисовывает

 

 

Как только я начинаю передавать в функции указатели на структуры-описатели - то при рефакторинге сразу перехожу на классы.

Это Вы имеете в виду следующий случай? Когда Вы пишите некую функцию и у нее становится слишком много входных параметров, тогда чтоб их передать более сгруппировано Вам приходится их объединять в структуры ( не нашел внятное объяснение термина "структуры-описатели"), а в функции передавать указатели на эти структуры, но т.к. это не комильфо, то Вы все нужные параметры всместо структур объединяете в класс и передаете по ссылке в функцию... Вы об этом??

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

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


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

Да, Си++ иногда тянет за собой кучу ненужного и тяжелого (полагаю, что и Си иногда тоже). На AVR я с этим не сталкивался, но столкнулся на ARM7TDMI, когда захотел использовать динамическую память (оператор new). Как только использовал, так код с 40 кБ вырос до 300 кБ. Пока чихаю на это, т.к. идет отладка. Но потом хочу прикрутить "легкую" реализацию менеджера памяти, любезно представленного уважаемым zltigo, и не менее любезно адаптированным к Си++ уважаемым Сергеем Борщем.

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

 

Как-то так.

 

Ну в общем подходишь к этому вопросу с необходимой долей разума. Где готовое используешь, где адаптируешь, где свое накропаешь)

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


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

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

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

Гость
Ответить в этой теме...

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

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

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

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

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

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