|
|
  |
Как писать на С++ при создание приложений под ARM, Примеры |
|
|
|
Mar 2 2012, 18:24
|
Местный
  
Группа: Участник
Сообщений: 214
Регистрация: 22-03-10
Из: Саратов
Пользователь №: 56 123

|
Цитата(brag @ Mar 2 2012, 15:43)  Да вот я какраз хотел запретить. Спасибо за подсказку Запретить бы вообще копирование по дефолту Легко. Код class NotCopyable { private: NotCopyable(const NotCopyable&);//конструктор копирования NotCopyable & operator=(const NotCopyable&);//оператор присваивания }; ... class Foo :NotCopyable { public: ... }; В классе NotCopyable конструктор копирования и оператор присваивания закрыты и не имеют реализации. Все классы, копирования которых мы хотим запретить, просто наследуем от NotCopyable.
|
|
|
|
|
May 28 2012, 19:24
|
Профессионал
    
Группа: Свой
Сообщений: 1 047
Регистрация: 2-12-06
Из: Kyiv, Ukraine
Пользователь №: 23 046

|
Из соседней ветки возник вопрос по умным указателям Допустим есть такая штука(типа наш указатель): CODE template<class T> class smart_ptr{ public: // create constructor (first reference) smart_ptr(T* ptr) : pData(ptr), pctr(&ctr), ctr(1) { printf("new\n"); } // copy constructor (following references) smart_ptr(const smart_ptr<T> &sp) : pData(sp.pData), pctr(sp.pctr) { ++*pctr; printf("ref %d\n",*pctr); } ~smart_ptr(){ --*pctr; printf("ref %d\n",*pctr); if(*pctr<1)delete pData; } T& operator*(){ return *pData; } T* operator->(){ return pData; } T& operator[](int i){ return pData[i]; } private: T *pData; int *pctr; int ctr; smart_ptr& operator=(const smart_ptr&); // disabled temporary }; И примерно так используем: CODE void f1(smart_ptr<char> p){ printf("f1 %s\n",&p[0]); }
main(){ smart_ptr<char> p(new char[256]); sprintf(&p[0],"blabla"); f1(p); }
результат:
new ref 2 f1 blabla ref 1 ref 0 Все конечно ок, но для экономии памяти и повеышения производительности хотелось бы иметь f1(smart_ptr<char> &p); Работает некорректно: Код new f1 blabla ref 0 Как в таком случаи его заставить правильно работать? апд. в принципе оно вроде корректно, тк пока указатель не будет скопирован - можно считать, что больше ссылок на него не появилось. Но хотелось бы сделать этот код более красивым и уменьшить размер smart_ptr до 8 байт... апд2. а не, код глючний, ибо если удалить самый первый обьект, то *pctr станет нерабочим. надо делать другой... Как-то так вроде красиво CODE class ref_ctr{ public: ref_ctr(): ctr(1) {} int aquire(){ return ++ctr; } int release(){ return --ctr; } int count()const{ return ctr; } private: int ctr; };
template<class T> class smart_ptr{ public: // create constructor (first reference) smart_ptr(T* ptr): pData(ptr) { printf("new\n"); } // copy constructor (following references) smart_ptr(const smart_ptr<T> &sp): pData(sp.pData){ pData->aquire(); printf("ref %d\n",pData->count()); } ~smart_ptr(){ if(pData->release()<1){ delete pData; printf("delete\n"); }else printf("ref %d\n",pData->count()); } T& operator*(){ return *pData; } T* operator->(){ return pData; } T& operator[](int i){ return pData[i]; } private: T *pData; smart_ptr& operator=(const smart_ptr&); // disable temporary }; CODE class chr: public ref_ctr{ public: char c[256]; };
void f1(smart_ptr<chr> &p){ static smart_ptr<chr> pp=p; printf("f1 %s\n",p->c); }
void main(){ smart_ptr<chr> p(new chr); sprintf(p->c,"blabla"); f1(p); printf("exit\n"); }
new ref 2 f1 blabla exit ref 1 delete
Сообщение отредактировал IgorKossak - May 29 2012, 06:57
Причина редактирования: [codebox] для длинного кода
|
|
|
|
|
Jun 7 2012, 09:40
|
Профессионал
    
Группа: Свой
Сообщений: 1 047
Регистрация: 2-12-06
Из: Kyiv, Ukraine
Пользователь №: 23 046

|
Имена, то такое, это пример  Потокобезопастность всегда прикручиваю позже, когда она нужна, наследуясь от потоконебезопасного класса и вешаю необходимую приблуду, а они могут быть разные (от запрета переключения контекста до хитрых lock-free структур) Довольно редко для таких указателей оно надо. Счетчик в указатель добавлять геморно, поскольку возникнет проблемма дублирования счетчика (хз с каким счетчиком потом работать). Списки - хорошо, но потокобезопасный список - вещ не тривиальная, если lock-free, то довольно сложно реализуемая либо вообще не реализуемая. А в реализации ref_ctr легко сделать потокобезопасным на ARMv7m без всяких локов: Код void ref_ctr::aquire(){ int c; do{ c=__ldrex(&ctr)+1; }while(__strex(c,&ctr)); }
bool ref_ctr::release(){ int c; do{ c=__ldrex(&ctr)-1; }while(__strex(c,&ctr)); return c<=0; }
|
|
|
|
|
Jun 16 2012, 16:02
|
Профессионал
    
Группа: Свой
Сообщений: 1 047
Регистрация: 2-12-06
Из: Kyiv, Ukraine
Пользователь №: 23 046

|
Возникла тут задача с аналогичным смыслом, который был изложен господином dxp в посте http://electronix.ru/forum/index.php?s=&am...st&p=942993 про сообщения. Код, предложенный dxp потокоопасный и от части делает на рантайме то, что мог бы сделать компилятор на компилтайме.. Предлагаю такой вот упрощенный вариант Код class basewrapper{ public: virtual int id()=0; };
template<class T> class wrapper :public basewrapper{ public: explicit wrapper(T *msg) :basewrapper(),pbody(msg) {} static int getClassId(){ return reinterpret_cast<int>(getClassId); } virtual int id(){ return getClassId(); } T* body()const{ return pbody; } private: T *pbody; }; Использовать как-то так: Код void ztest(){ msg1 m1; msg2 m2; wrapper<msg1> wmsg1(&m1); wrapper<msg2> wmsg2(&m2); dbgprintf("%d %d\n",wmsg1.id(),wmsg2.id()); } Конечно, поведение компилятора в функции getClassId() не совсем детерминировано(хотя хз), но тесты на gcc-4.7.1 и rvct-4.1 [Build 894] со всевозможными опциями оптимизации дали положительный результат.
|
|
|
|
|
Jun 16 2012, 17:09
|
Профессионал
    
Группа: Свой
Сообщений: 1 047
Регистрация: 2-12-06
Из: Kyiv, Ukraine
Пользователь №: 23 046

|
Ну и еще один вариант, гарантирующий однозначность в принципе но увеличивающий размер кода, но без ущерба производительности. Использовать предефайнд-константу __PRETTY_FUNCTION__, бпльшинство компиляторов это поддерживают. Код template<class T> class wrapper :public basewrapper{ public: explicit wrapper(T *msg) :basewrapper(),pbody(msg) {} static int getClassId(){ return reinterpret_cast<int>(__PRETTY_FUNCTION__); } virtual int id(){ return getClassId(); } T* body()const{ return pbody; } private: T *pbody; }; UPD. Подумал я тут на счет первого варианта... Чтобы линкер вдруг не умудрулся слить функции getClassId() шаблонов разных типов в одну, нужно ему как-то об'яснить, что выходной файл - динамическая библиотека, тогда каждая getClassId() однозначно будет иметь свое имя, и ессно свой адрес. Хотя есть еще алиасы, хз в общем  ) Будем надятся, что линкер не на столько умный, чтобы сливать функции с разными именами и одинаковым телом в одну  При самой агрессивной оптимизации ничего криминального не произошло: CODE arm-none-eabi-g++ -mcpu=cortex-m3 -mthumb -O3 -Wall -Wextra -flto -ffreestanding -fno-rtti -fno-exceptions -g -c ztest.cpp arm-none-eabi-g++ -mcpu=cortex-m3 -mthumb -O3 -Wall -Wextra -flto -ffreestanding -nostdlib -g\ -Wl,-emain -Wl,--gc-sections -o z.elf ztest.o arm-none-eabi-objdump -d z.elf
Disassembly of section .text:
00008000 <main>: 8000: f248 003c movw r0, #32828; 0x803c 8004: f248 0125 movw r1, #32805; 0x8025 <-----| Уникальные 8008: f248 0231 movw r2, #32817; 0x8031 <-----| 800c: b508 push {r3, lr} 800e: f2c0 0000 movt r0, #0 8012: f2c0 0100 movt r1, #0 8016: f2c0 0200 movt r2, #0 801a: f241 2334 movw r3, #4660; 0x1234 801e: 4798 blx r3; printf 8020: 2000 movs r0, #0 8022: bd08 pop {r3, pc}
00008024 <_ZN7wrapperI4msg1E10getClassIdEv.local.3.4006>: 8024: f248 0025 movw r0, #32805; 0x8025 8028: f2c0 0000 movt r0, #0 802c: 4770 bx lr 802e: bf00 nop
00008030 <_ZN7wrapperI4msg2E10getClassIdEv.local.2.4020>: 8030: f248 0031 movw r0, #32817; 0x8031 8034: f2c0 0000 movt r0, #0 8038: 4770 bx lr 803a: bf00 nop
|
|
|
|
|
Jun 17 2012, 00:35
|
Профессионал
    
Группа: Свой
Сообщений: 1 047
Регистрация: 2-12-06
Из: Kyiv, Ukraine
Пользователь №: 23 046

|
До коллекции еще один вариант, без виртуальных функций - чуть выше производительность при проверке типа и исполняемый код меньше. Код class IClassId{ public: explicit IClassId(unsigned id) :classid(id) {}; unsigned id()const{ return classid; } private: unsigned classid; };
template<class T> class ClassIdBase: public IClassId{ public: explicit ClassIdBase(T*) :IClassId(getClassId()) {} static int getClassId(){ return reinterpret_cast<unsigned>(getClassId); } static T* getObjptr(IClassId *p){ if(p->id()==getClassId())return static_cast<T*>(p); else return 0; } }; Использовать как-то так Код class c1: public ClassIdBase<c1>{ public: c1() :ClassIdBase(this) {} }; class c2: public ClassIdBase<c2>{ public: c2() :ClassIdBase(this) {} };
void zt1(IClassId *wrp){ printf("%d %d\n", ClassIdBase<c1>::getObjptr(wrp), ClassIdBase<c2>::getObjptr(wrp)); }
void ztest(){ c2 w1; zt1(&w1); }
0 536888040 Указатель this конструктору ClassIdBase передается специально, чтобы чтобы компилятор выдал ошибку, если вдруг при копипасте случайно забудем исправить параметр шаблона ClassIdBase, типа так: Код class c2: public ClassIdBase<c1>{ public: c2() :ClassIdBase(this) {} };
|
|
|
|
|
Jun 18 2012, 00:41
|

фанат Linux'а
    
Группа: Свой
Сообщений: 1 353
Регистрация: 23-10-05
Из: SPB.RU
Пользователь №: 10 008

|
Цитата(Forger @ Dec 13 2011, 12:55)  Идеи Qt дает интересные, но она изначально ориентирована на кучу. А чтобы приучить ее к статике - нужно изрядно попотеть, а смысл? Т.е. в эмбеддерских делах пока ей, по-моему, пока нет места. шутки шутками, а я на полном серьезе просто воткнул Linux на ARM SAM9G45, зарядил туда Qt и спокойно пишу на своей любимой библиотеке для участков, критичных к производительности и памяти можно спокойно обойти использование Qt-шных классов как раз по названной Вами причине, но все остальное, что не надо чтобы шустрило, пишется на Qt и экономится время и нервы в моей гипер-мега-системе два ARM-а разных классов (второй Cortex-A9), один x86, ну и еще телефон на базе Android - с помощью Qt я спокойно пишу код который совместим со всеми этими платформами и любыми ОС в широком смысле ЗЫ некоторые даже предпочтут питон или даже Mono/C# для своих проектов, ускоряя критичные участки нативщиной =)
--------------------
|
|
|
|
|
Jun 18 2012, 19:27
|

фанат Linux'а
    
Группа: Свой
Сообщений: 1 353
Регистрация: 23-10-05
Из: SPB.RU
Пользователь №: 10 008

|
Цитата(brag @ Jun 18 2012, 10:46)  AVR, все так, только linux і Qt не вдуть на проц с 64кб озу  а городить тяжеловес как-то не логично,особенно,если от батарейки должен работать.. Хотя может скоро и можно будет себе такое позволить - даешь дешевые китайские платы,дешевые армы, дешевый фен шоб паять BGA есть  ) всё зависит от задачи и величины партии, а чтобы работал от батарейки - есть специальные меры в ОС Linux для этого... вот сколько стоит 32 Мб DDR2? а теперь берете калькулятор и считаете - вам проще потратить три копейки и влепить ОСь Linux и кучу дешевой рамы или страдать дедовским способом?  в общем, для мелких и средних партий я сторонник полновесной ОС (Linux лишь одна из таких), быть может такие проекты и есть то большинство...
--------------------
|
|
|
|
|
Jun 19 2012, 20:34
|

фанат Linux'а
    
Группа: Свой
Сообщений: 1 353
Регистрация: 23-10-05
Из: SPB.RU
Пользователь №: 10 008

|
Цитата(dxp @ Jun 19 2012, 08:48)  А не оценивали, как влияет на энергопотребление использование такой взрослой оси (да ещё и + Qt)? не совсем понял, это скорее намек или вопрос? я полагаю что энергопотребление при работе Linux и Qt будет несколько выше я сравнивал официальные отчеты от Ti для OMAP3 - при максимальной нагрузке - разницы между потреблением с ОС и без нее - не нашел, при отсутствии нагрузки - да, у Linux было процентов на 15 выше, не более но как и во всем, есть недосказанные моменты - у Linux есть специальные средства для отладки энергопотребления системы, чтобы всегда знать что не дает держать процессор в глубоком сне и минимальном потреблении, да и сама ОС Linux жрет скорее оперативку, чем процессор - что приятно а учитывая HRT возможности Linux-а с его максимум 25 мкс что я видел в одном из тестов - вообще универсальная ОСь получается - ни за что ее не променяю, и подкормлю сотней милливатт если надо  P.S. понимаю какое отвращение могут вызвать мои слова у профессионалов, пишущих на голом железе для экономии энергии, но мне-то хорошо - ценой некоторого потребления и стоимость DDR2 - получаю платформу для легкой и быстрой разработки
--------------------
|
|
|
|
|
Jun 19 2012, 22:02
|
Профессионал
    
Группа: Свой
Сообщений: 1 047
Регистрация: 2-12-06
Из: Kyiv, Ukraine
Пользователь №: 23 046

|
32мб ddr2 не так уж и дешево, и проц под это дело в том числе. плата дорогая, сама требующая больше времени для отладки и оборудования дорогого нередко - частоты не те уже, хотя и не свч. какраз на мелкосерийке выйдет дорого - Китай + дорогая пайка бга корпусов(ну запаяю я феном парочку образцов, но на продажные девайсы никогда такое бы не делал). размер. вес. потребление, особенно,если железка алгоритмы выполняет, а не просто висит в глубоком сне в ожидании нажатие кнопочки... Потом этот весь софt сам кишит багами(а свои баги ловить проще,чем чужие), вон я недавно даже в релизе компилятора gcc баг поймал, компилер иногда удалял запись в регистры периферии, при чем по словам разработчиков, баг есть и в более ранних версиях. пруф-линк http://gcc.gnu.org/bugzilla/show_bug.cgi?id=53085И как ни странно - обучение работы с тем софтом(чего только стоит драйвер написать, а если тайм критикал + многопоточность - как говорят буржуи - synchronization will kill you) и реализацией задач, которые легко ложатся на простые Cortex-M3 ~70mhz соизмеримо с их реализацией на этом самом голом железе, а знания C++, умение программировать в ОО нужно там и там. вобщем всему свое место
|
|
|
|
|
Jun 19 2012, 22:21
|

фанат Linux'а
    
Группа: Свой
Сообщений: 1 353
Регистрация: 23-10-05
Из: SPB.RU
Пользователь №: 10 008

|
Цитата(brag @ Jun 20 2012, 02:02)  вобщем всему свое место спасибо, интересное мнение ясно одно - PoP у нас уже есть, так что скоро все эти разговоры про сложность разводки DDR2/3 для возможности запуска полновесной ОС типа Linux уже не будет стоять так остро, останется лишь вопрос цены, но объемы оперативной памяти растут, а "минимальные системные требования" у Linux с годами растут крайне медленно насчет багов, я бы не был так категоричен про "кишащий багами софт", в экзотических местах такое может быть - но на то и есть отладка не соглашусь и с временем обучения работы с софтом - и чего же стоит драйвер написать? правильно ли я понял что данная оценка из личного опыта?
--------------------
|
|
|
|
|
  |
3 чел. читают эту тему (гостей: 3, скрытых пользователей: 0)
Пользователей: 0
|
|
|