|
|
  |
Embedded C++, Кто какие библиотеки использует? |
|
|
|
Oct 28 2010, 12:54
|

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

|
Я использую исключительно свои библиотеки. Писать их приходится всего один раз. Все проекты построены под одному и тому же шаблону, прототипу. Для процов, к которым нет нормального 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).
--------------------
Кругозор некоторых людей - круг с нулевым радиусом. Они называют его "точкой зрения".
|
|
|
|
|
Oct 28 2010, 15:17
|

Частый гость
 
Группа: Свой
Сообщений: 129
Регистрация: 28-09-10
Из: Москва
Пользователь №: 59 793

|
Цитата(Сега @ Oct 28 2010, 16:12)  ... выходом из этой ситуации вижу использование либо специальных готовых light библиотек либо написание базовых шаблонов/классов самому. .... В принципе, верное решение. Это мне напомнило извечный вопрос всех времен- использовать printf или не использовать? Короче, там где с ресурсами напряг - пишу все сам с использованием минимального количества "тяжелых" библиотек. Где проблем с ресурсами нет - можно и STL и Linux и все, что позволяет решить задачу быстрее и проще. А так - библиотек и исходников и Инете полно на все вкусы и под разные задачи, одной - на все случаи жизни - ИМХО нет и быть не может.
|
|
|
|
|
Sep 4 2012, 09:28
|
Местный
  
Группа: Участник
Сообщений: 211
Регистрация: 27-12-11
Из: Челябинск
Пользователь №: 69 111

|
А давайте помусолим uSTL (ссылка была раньше). 1. какие видятся минусы и плюсы использования? 2. кто в каких проектах использовал? где может быть применена эта библиотека (пример какой-нибудь для начинающих =), чтоб понять куда можно прикручивать ). И стоит ли? 3. во что компилируется проект с данной библиотекой: объем кода огромен ? 4. Если код получается небольшим, за счет чего это достигается??? какие трюки? 5. Как я понял одна из плюшек - это Memblocks and Memlinks, которые организованы как классы и содержат в себе все контейнеры, создаваемые в проге, т.е. все они в одном месте локализованы. В STL векторы, например, у нас динамические: если не хватает их размерности, то при достижении конца вектора резервируется при помощи new в два раза большая память. т.е. если мы используем некий вектор на 1024 отсчетов, но должны принять 1060 отсчетов, то по достижении индекса 1023 у нас размерность станет 2048, хотя храниться будут только 1060 значений. Для компов - это пустяк (хотя и там оптимизируется при помощи, вроде бы, метода resize(); ), а для embedded - ужас. И пока не дошло вот что: при помощи Memblocks and Memlinks получается сделать вектора в uSTL статическими?????
Сообщение отредактировал beaRTS - Sep 4 2012, 09:30
--------------------
"Об уме человека вернее судить по его вопросам, нежели по его ответам" (с)
|
|
|
|
|
Sep 5 2012, 02:14
|
Местный
  
Группа: Участник
Сообщений: 211
Регистрация: 27-12-11
Из: Челябинск
Пользователь №: 69 111

|
Спасибо! а на вопросы кто-нибудь прольет свет? Цитата(Major @ Sep 4 2012, 12:58)  Использую для ARM (всех) компилятор C++ и очень доволен (keil). А можете уточнить по АРМам. ведь они бывают очень крутыми Arm9, ARM11 ! Просто волнует информация о том, при каком объеме памяти на борте процессора, тактовой частоте и еще каких-нибудь значимых параметрах, о которых могу и не подозревать, можно использовать С++, шаблоны, ту же uSTL или другие библиотеки. Я просто заложил в устройство TMS320F28235: Frequency (MHz) 150; RAM (KB) 68; Flash (KB) 512.
Сообщение отредактировал beaRTS - Sep 5 2012, 02:15
--------------------
"Об уме человека вернее судить по его вопросам, нежели по его ответам" (с)
|
|
|
|
|
Sep 5 2012, 05:53
|

Гуру
     
Группа: Модераторы
Сообщений: 8 455
Регистрация: 15-05-06
Из: Рига, Латвия
Пользователь №: 17 095

|
QUOTE (beaRTS @ Sep 5 2012, 05:14)  Просто волнует информация о том, при каком объеме памяти на борте процессора, тактовой частоте и еще каких-нибудь значимых параметрах, о которых могу и не подозревать, можно использовать С++, шаблоны, Наличие ОЗУ и адресуемого стека. Необходимый объем зависит от вашей задачи. Но везде, где можно писать на С, можно писать и на С++ с шаблонами, наследованием и т.д. Активно используя и голову, разумеется. STL и исключения - другой вопрос, там надо смотреть на реализацию, пробовать.
--------------------
На любой вопрос даю любой ответ"Write code that is guaranteed to work, not code that doesn’t seem to break" ( C++ FAQ)
|
|
|
|
|
Sep 5 2012, 07:21
|
Местный
  
Группа: Участник
Сообщений: 211
Регистрация: 27-12-11
Из: Челябинск
Пользователь №: 69 111

|
Цитата(Сергей Борщ @ Sep 5 2012, 08:53)  можно писать и на С++ с шаблонами, наследованием и т.д. Активно используя и голову, разумеется. голову нужно ставить на место), привыкать к ООП: к ООП применительно к embedded в связке с ОСРВ (будет у меня DSP/BIOS). вот тут не все понятно. Например, что брать за сущности, если , скажем, требуется сделать детектор : отдельные матлабовские блоки умножителей, дециматоров , фильтров оформлять разными классами или же делать одним классом под названием DetectorClass, куда и впихнуть весь алгоритм работы детектора?... (склоняюсь ко второму). теории прочитано достаточно - надоело. взял книжку с задачками, к которым есть примеры решения, и начал тупо повторять с главы про ООП, изменяя примеры в книге (где-то названия не нравятся - не в той нотации, где-то вижу, что функцию проще сделать можно и т.п.) Думаю посидеть так чуток, и дальше двигаться.. Хочется понять как повторить с полным пониманием происходящего то, о чем пишется во 2ом сообщении, как прикручивать ОСРВ к этому. А в общем, Как достичь подобного просветления =) ! ) ????
Сообщение отредактировал beaRTS - Sep 5 2012, 14:21
--------------------
"Об уме человека вернее судить по его вопросам, нежели по его ответам" (с)
|
|
|
|
|
Sep 5 2012, 14:53
|
Местный
  
Группа: Участник
Сообщений: 211
Регистрация: 27-12-11
Из: Челябинск
Пользователь №: 69 111

|
Цитата(Major @ Sep 5 2012, 15:32)  Зачем писать на чистом С реализацию ++? В этом случае надо использовать C++. да, я сместил вектор своего развития в сторону С++, и дома в после рабочее время пытаюсь углубляться, ставя задачи из компьютерного зрения и openCV. Бесплатные курсы пытаюсь проходить, связанные с этой темой, которые одна фирма у нас устраивает. Цитата(Major @ Sep 5 2012, 15:32)  Инкапсуляция, Полиморфизм, Наследование - приоритеты в таком порядке. СПС! за советы. Вот, кстати, таких советов и не хватает молодым - таких, как, Ваши и как, например, в книжке Экеля Thinking in C++ в Приложении Б "советы по программированию". Очень дельные советы на мой взгляд. Были б такие в С++ embedded ... Кстати, товарищ Neiver выкладывал подобный труд-статью , которая продублирована была на EasyElectronics . за что спасибо.. Но это капля в море и системной картины не вырисовывает Цитата(Major @ Sep 5 2012, 15:32)  Как только я начинаю передавать в функции указатели на структуры-описатели - то при рефакторинге сразу перехожу на классы. Это Вы имеете в виду следующий случай? Когда Вы пишите некую функцию и у нее становится слишком много входных параметров, тогда чтоб их передать более сгруппировано Вам приходится их объединять в структуры ( не нашел внятное объяснение термина "структуры-описатели"), а в функции передавать указатели на эти структуры, но т.к. это не комильфо, то Вы все нужные параметры всместо структур объединяете в класс и передаете по ссылке в функцию... Вы об этом??
Сообщение отредактировал beaRTS - Sep 5 2012, 15:15
--------------------
"Об уме человека вернее судить по его вопросам, нежели по его ответам" (с)
|
|
|
|
|
Sep 5 2012, 23:51
|

Познающий...
     
Группа: Свой
Сообщений: 2 963
Регистрация: 1-09-05
Из: г. Иркутск
Пользователь №: 8 125

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