Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: Как писать на С++ при создание приложений под ARM
Форум разработчиков электроники ELECTRONIX.ru > Микроконтроллеры (MCs) > ARM
Страницы: 1, 2, 3, 4
andrewlekar
Не совсем понял, что нужно в итоге получить, но возможно такая конструкция поможет Base *array[] = {new Derived(0), new Derived(0), new Derived(0)};
Если у вас и new нет реализации, то совсем всё плохо. sm.gif
demiurg_spb
Ему нужно статически всё слинковать и разместить во flash, если я правильно понял.
andrewlekar
Ага, проблема видимо в том, что getItem возвращает Base *. Может тогда просто приводить возвращаемое значение к нужному типу? Вот так: (Derived *)d.getItem(1).
andrewlekar
Не, не получается нифига. Думаю, что стоит getItem вытащить из базового класса - пускай он объект класса принимает на вход.
brag
Цитата
Если у вас и new нет реализации, то совсем всё плохо.

new нету, дорого
Цитата
Не, не получается нифига. Думаю, что стоит getItem вытащить из базового класса - пускай он объект класса принимает на вход.

не пойдет, по сколоьку нaдo иметь такую возможность:
Код
Derived1 derived1;
Derived2 derived2;
Base * const *arraay[]={&derived1,&derived2};
Derived3 d3(array);
dxp
Цитата(brag @ Dec 12 2011, 17:21) *
new нету, дорого

new можно свой написать, будет недорого.
andrewlekar
Ну если забить на наследование, абстракцию и прочую фигню, то можно вот так реализовать:

Код
class Base{
public:
    Base(void **array)
    {
        _a=array;
    }
    void *getItem(int n){ return _a[n]; }
private:
    void **_a;
};

class Derived: public Base{
public:
    Derived(void **array, int z) : Base(array){other = z;}
private:
    int other;
};

Derived derived1(0, 0);
Derived derived2(0, 1);
Derived derived3(0, 2);

void *array[]={&derived1, &derived2, &derived3};

//Derived aaa[]={Derived(0, 0),Derived(0, 1),Derived(0, 2)};

void main()
{
    Derived d3((void **)array, 3);

    Derived *x = (Derived *)d3.getItem(2);
}
brag
Он в принципе написан, почти, только на даной платформе и так вся память забита статикой- много данных...(причем используется почти вся, ну мож 2-4кб в резерве и в редкоиспользуемых переменных из 64), места под кучу нету. я кучи юзаю только если есть внешняя sram

Цитата
Ну если забить на наследование, абстракцию и прочую фигню, то можно вот так реализовать:

ну у меня примерно так и реализовано, только с наследованием, абстракцией,... sm.gif
цель - упростить создание обьектов, тк их много, где-то тупанешь, в массив не туда указатель всунешь и потом сложно найти ошибку...
Гораздо проще, когда в ините массива сразу конструктор видно, те. видно,что за обьект туда впихнули...
Пока создаю каждый под своим именем, хоть какая-то визуализация есть...
типа так
Код
....
static MenuItemInt<U8> miContrast(0,"Contrast:",&g_mainsetup.contrast,1,100);
static MenuItemInt<U8> miBright(0,"Bright:",&g_mainsetup.brightness,0,100);
static MenuItemInt<U8> miLedTime(0,"LED time:",&g_mainsetup.lighto,5,255);
static MenuItemInt<U8> miKbdVol(0,"KBD vol:",&g_mainsetup.kbdsndvol,0,128);
...
static MenuItem* const settingsItemsList[]={ &miContrast,&miBright,&miLedTime,&miKbdVol,... };
...

Forger
немного офф (без холивара):
Че ж вы почте все так упорно адреса объектов передаете через указатели ?!
Чай не на С пишете, а С с плюсами.
В С++ для этого придумана передача по ссылке - удобнее и безопаснее.
Да и код становится чище и более читаем.
К тому же существует такая чудесная вещь - перегрузка стандарных операторов: = + - << >> &* и т.д.
Оч. сильно сокращает текст кода. Кто-нить пользуется?
Тем более без "наследования, абстракции и прочей фигни", ну, уже никак нельзя.
Иначе это возврат в каменный век - чистый С.


Цитата(brag @ Dec 12 2011, 15:53) *
Код
....
static MenuItemInt<U8> miContrast(0,"Contrast:",&g_mainsetup.contrast,1,100);
static MenuItemInt<U8> miBright(0,"Bright:",&g_mainsetup.brightness,0,100);
static MenuItemInt<U8> miLedTime(0,"LED time:",&g_mainsetup.lighto,5,255);
static MenuItemInt<U8> miKbdVol(0,"KBD vol:",&g_mainsetup.kbdsndvol,0,128);
...
static MenuItem* const settingsItemsList[]={ &miContrast,&miBright,&miLedTime,&miKbdVol,... };
...

В догонку у меня к brag (и к остальным) несколько вопросов:
Как вы определяет порядок создания объектов (вызовы конструкторов) при таком статическом размещении?
Понятно, что в пределах одного С++ файла объекты скорее всего будут создаваться в порядке размещения в коде.
А как быть, если таких файлов более одного?
И как быть, если объекты должны создаваться в определенном порядке, а надежды на разум линкера мало?

Вот пример такой ситуации:
Один объект - драйвер ЖК экрана (монитора), а другой - некий видгет.
Видгет прямо в конструкторе хочет нарисоваться на экране.
Это возможно, если сначала в С++ файле будет объявлен драйвер, а потом видгет.
Это сработает всегда, т.к. это видно визуально прямо в тексте кода, наглядно.
А что делать, если видгетов - оч. много, многие являются полями других объектов и размещены в других файлах?
Где гарантия, что линкер в сначала засунет в список вызова перед main конструктор драйвера экрана, а потом всего остального?
Ну, ясно, что есть такая штука, как отложенная инициализация. Но это раздувает код.
Есть идеи?

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

Цитата
Как вы определяет порядок создания объектов (вызовы конструкторов) при таком статическом размещении?

Поа никак, но смотрел init_array - тулит в нужном порядке.
Цитата
Понятно, что в пределах одного С++ файла объекты скорее всего будут создаваться в порядке размещения в коде.

ну да. Этот код предназначен для компиляции в одном файле, потому везде ключевые слова "static".
Далее после создания массива идет создание обьекта, которые его использует, типа
Код
static Menu settingsMenu(Rect(0,8,96,56),0,settingsItemsList,sizeof(settingsItemsList)/sizeof(MenuItem*));

Вся эта муть создается в одном файле, а уже реализация классов в других

Цитата
И как быть, если объекты должны создаваться в определенном порядке, а надежды на разум линкера мало?

Если есть хоть какая-то зависимость от порядка - я делаю либо отдельный метод init() в классах либо создается обьявляется пустышка в статике, а затем присваивается уже в коде нужное значение:
Код
BragClassebta c1;
...
somecoolfunction(){
      c1=BragClassebta(hlam_usjakij,...);
}


Цитата
Видгет прямо в конструкторе хочет нарисоваться на экране.

Лично у меня в конструкторах рисовалок нету, рисавалки далеко в недрах всяких message-loop.

Цитата
Ну, ясно, что есть такая штука, как отложенная инициализация. Но это раздувает код.
Есть идеи?

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

но по моему единохренственно, что в коде будет что-то типа
Код
MyFuckingClass *a;
...
Someclass::somefunction(){
a=new MyFuckingClass();
}


Что
Код
MyFuckingClass a;
...
Someclass::somefunction(){
a.init();
}

AHTOXA
Цитата(Forger @ Dec 12 2011, 23:32) *
Вот пример такой ситуации:
Один объект - драйвер ЖК экрана (монитора), а другой - некий видгет.
Видгет прямо в конструкторе хочет нарисоваться на экране.

Делаем у драйвера статическую функцию-член:
Код
static Driver& Instanse()
{
  static Driver instance;
  return instance;
}

И все, кто хочет отрисоваться на экране, обращаются к драйверу через неё:
Код
Vidget::Draw()
{
  Driver& drv = Driver::Instanse();
  drv.Draw(this);
}
brag
Цитата
И все, кто хочет отрисоваться на экране, обращаются к драйверу через неё:

Ага, только мютекс для static Driver instance; кто будет создавать, лочить,... и когда?
Forger
Цитата(AHTOXA @ Dec 12 2011, 21:47) *
И все, кто хочет отрисоваться на экране, обращаются к драйверу через неё:
Код
Vidget::Draw()
{
  Driver& drv = Driver::Instanse();
  drv.Draw(this);
}

Наверно, я предложил не очень наглядный пример для этого случая...
По сути то, что вы предлагаете - класс-синглтон. В нем можно тогда уже все функции сделать статическими ))
Да, я согласен, это идеальный вариант для единственного экрана, порта или какой-нить периферии и т.п.
А как быть, если их больше одного?
Сам отвечу - разные классы драйверов, наследованные от одного абстрактного класса драйвера с парой-тройкой чисто виртуальных функций, которые определяют разницу между разными драйверами.

Короче, вот другой пример:
есть некий протокол обмена к которому привязан свой драйвер,
нужно совместное проживаение более одного такого протокола в прелах одного кода
протоколы абсолютно одинаковые (пусть это будут два TCP/IP каждый на своем ETH)
экзэмпляр одного протокола находится в одном файле, другой - в другом файле, объявлены через static
их нужно запускать в определеном порядке, синхронизировать,
Как это сделать без глобальных объектов?



Цитата(brag @ Dec 12 2011, 21:49) *
Ага, только мютекс для static Driver instance; кто будет создавать, лочить,... и когда?

В принципе, лочить можно внутри каждого метода отрисовки. Я так однажды делал.
Мьютекс лежит среди полей класса драйвера, инитится в initialize() методе драйвера.


Цитата(brag)
Массив ссылок в C++ создать нельзя.

А это сделано намеренно sm.gif
Ссылку можно дать на экзэмпляр класса, который владеет этим массивом и т.о. защить его от прямых попыток изменения соотв. методами.
Так код делается значительнее безопаснее.
Цитата
Перегрузкой пользуемся конечно, только как ее сюда втулить -хз, похоже таки никак

Я ж предупредил - немного офф ))
А перегрузку можно вообще всунуть куда угодно ))
Но подобный фанатизм до добра не доведет...
Цитата
Поа никак, но смотрел init_array - тулит в нужном порядке.

Прощу прощения за мое невежество, а что это такое?

Цитата
Код
static Menu settingsMenu(Rect(0,8,96,56),0,settingsItemsList,sizeof(settingsItemsList)/sizeof(MenuItem*));

Вся эта муть создается в одном файле, а уже реализация классов в других

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

Цитата
Если есть хоть какая-то зависимость от порядка - я делаю либо отдельный метод init() в классах либо создается обьявляется пустышка в статике, а затем присваивается уже в коде нужное значение:

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

Цитата
но по моему единохренственно, что в коде будет что-то типа
Код
MyFuckingClass *a;
...
Someclass::somefunction(){
a=new MyFuckingClass();
}


Что
Код
MyFuckingClass a;
...
Someclass::somefunction(){
a.init();
}

Согласен, одно и то же, но классическая хуча в эмбэддед софтах - величайшее зло sm.gif
brag
Цитата
Как это сделать без глобальных объектов?

Легко. Через интерфейсы. А выбор интерфейса где-то предусмотреть.
А экземпляр обьекта TCP создавать непосредственно перед использованием, к стати и тут может происходить выбор интерфейса.
Код выглядит всегда одинаково и никакой связи между файлами драйвера и файлами протокола нету.

Код
class IPaintEngine{
public:
    virtual int w()=0;
    virtual int h()=0;
    virtual void drawText(const Point &pos,const char *text,const Palette &pal)=0;
    virtual void drawRect(const Rect &rect,const Palette &pal)=0;
};


Сама рисовалка. Пусть это будет наш протокол. Экземпляр создается тогда,когда он нам нужен:
Код
class Painter{
public:
    Painter(PaintDevice *dev);
    void drawText(const Point &pos,const char *text,const Palette &pal);
    void drawRect(const Rect &rect,const Palette &pal);
    void fillBackground(const Palette &pal);
...
private:
    PaintDevice *paintdev;
...
};


От этого наследуемся, если хотим уметь рисовать:
Код
class PaintDevice{
public:
    virtual IPaintEngine* paintEngine()=0;
...
};

И организовываем выбор драйвера через virtual IPaintEngine* paintEngine();

Рисуем
Код
class Widget : public PaintDevice{
public:
...
    virtual void draw(){
        Painter painter(this);
        painter.drawText(Point(0,0),"Hello word");
    }
...
};


Наверное заметили некое сходство с Qt... sm.gif Да, некоторые идеи я передрал с докуминтации Qt wink.gif

Цитата
В принципе, лочить можно внутри каждого метода отрисовки. Я так однажды делал.
Мьютекс лежит среди полей класса драйвера, инитится в initialize() методе драйвера.

Нет, вы немного не поняли. Кто лочить будет static Driver instance; ?
Ведь вызватся функция static Driver& Instanse() может одновременно, когда обьект instance еще не создан.
Один тред вызвал Instanse(), та запустила конструктор для instance (тк instance еще не создан) и тут процесс посреди конструктора прервался и кто-то другой опять вызвал Instanse() и ...и сами понимаете что sm.gif
Ведь процесс создания instance мы никак не контроллируем...

Я синглтоны делаю так:
Код
class BragUI{
public:
    BragUI();
              static BragUI& getInst()const{ return ui; }
private:
    static BragUI ui;
};
....
BragUI::ui=BragUI();


Цитата
Прощу прощения за мое невежество, а что это такое?

Это такая хреновина... Регламентировано ARM IHI0041C CPPABI:
Цитата
Each element of the vector contains the address of a function of type extern “C” void (* const)(void) that, when
called, performs part or all of the global object construction for the translation unit.

Нам остается их вызвать где-то при старте for(i=0;i<sizeofinitarray;i++)__init_array[i]();

Цитата
Вот именно и выходит муть - ее не разобрать без "словаря" уже через месяц отдыха ))
Куча параметров в одной строчке. Куча static объектов.
А так как их конструторы с параметрами, то их уже не засунуть никуда, кроме как в начало С++ файла (это я про читаемость кода).
С развитием проекта наступит точка хаоса... ))

Это процесс создания окошек. А реализация уже в других файлах. в будущем вообще этот код будет софтиной-дизайнером генерится( типа как в Qt sm.gif ).
В файле с этой кучей статиков больше ничего нету.
Согласитесь, создание графических обьектов где-попало в коде в разных файлах приведет к еще хужему хаоссу sm.gif
Ну всякие там MessageBox-ы и диалоги ессно создаются в стеке когда это нужно, эти массивы надо только для построения основного ui.

Цитата
А как вы ссылаетесь на них из других объектов, объявленных в других файлах?

Зачем на них ссылаться? Досточно выполнить execMenu(); где нам нужно
Код
static Menu mainMenu(Rect(0,8,96,56),0,mainItemsList,sizeof(mainItemsList)/sizeof(MenuItem*));
void execMenu(){
     mainMenu.exec();
}


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

Поможет разве что раздельная линковка ОС и программы с тредами. Сначала стартует ОС, подготавливает почву для создания всяких мютексов, а потом стартует прога и уже спокойно можно реализовывать такие синглтоны:
Код
class Single{
public:
    Single(){ initialized=0; }
    static Single& getInst(){
        inst.m.lock();
        if(!inst.initialized)inst.init();
        inst.m.unlock();
        return inst;
    }
private:
    static Single inst;
    Mutex m;
    bool initialized;
    void init();
};

Single Single::inst=Single();



Цитата
Согласен, одно и то же, но классическая хуча в эмбэддед софтах - величайшее зло

Ну да, потому я за init() sm.gif
Не так их уж и много этих синглтонов (у меня только они требуют init() ). Это обычно всякие драйвера там.
Да и можно этот init как-то назвать,чтобы заметен был и софтину сделать, которая код прочесывает и выдает ошиибку, если эта ф-я не вызвана sm.gif
dxp
Цитата(Forger @ Dec 13 2011, 00:32) *
К тому же существует такая чудесная вещь - перегрузка стандарных операторов: = + - << >> &* и т.д.
Оч. сильно сокращает текст кода. Кто-нить пользуется?

А как же. sm.gif Регулярно. Но без фанатизма. Там, где уместно. Например, при работе с координатами экране есть класс TPoint, который предоставляет всю арифметику вычисления координат. Получается удобнее и читабельнее, нежели функции вызывать.


Цитата(Forger @ Dec 13 2011, 00:32) *
В догонку у меня к brag (и к остальным) несколько вопросов:
Как вы определяет порядок создания объектов (вызовы конструкторов) при таком статическом размещении?
Понятно, что в пределах одного С++ файла объекты скорее всего будут создаваться в порядке размещения в коде.
А как быть, если таких файлов более одного?
И как быть, если объекты должны создаваться в определенном порядке, а надежды на разум линкера мало?

Ну, штатное решение - singleton. Но он вас почему-то не устраивает. А, тем не менее, работает предсказуемо, надёжно и эффективно. Пользуемся.


Цитата(brag @ Dec 13 2011, 00:43) *
ну да. Этот код предназначен для компиляции в одном файле, потому везде ключевые слова "static".

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

Цитата(Forger @ Dec 13 2011, 01:36) *
Короче, вот другой пример:
есть некий протокол обмена к которому привязан свой драйвер,
нужно совместное проживаение более одного такого протокола в прелах одного кода
протоколы абсолютно одинаковые (пусть это будут два TCP/IP каждый на своем ETH)
экзэмпляр одного протокола находится в одном файле, другой - в другом файле, объявлены через static
их нужно запускать в определеном порядке, синхронизировать,
Как это сделать без глобальных объектов?

Что-то всё равно не понятно, что вы хотите сделать. cranky.gif

Цитата(Forger @ Dec 13 2011, 01:36) *
Ну вот так и рождаются "костыли". Неправильно это как-то. Пока код маленький - все гуд, но потом приходит жопа.
Ну, должно ж быть "резиновое" решение, которое будет работать на коде любой сложности и объема.

Кстати, фреймворк Qt идёт по совсем простому пути - там до старта main(), а точнее, до создания объекта QAppication никакие GUI'ные объекты не рожаются - это запрещено идеологически. Поэтому с порядком создания объектов проблем нет. Очень простой и эффективный способ. Правда, для embedded в том виде, как это там реализовано, это не годицца - там всё это живёт на new.
brag
Цитата
Не понимаю, почему вы упорно проводите в жизнь икапсуляцию на уровне единиц трансляции, а не на основе классов, кои есть штатное средство языка для этого? Ведь если бы классами не пользовались, было бы понятно. В С такой подход тоже понятен. Но не в С++.

А как в данном случаи быть иначе?

Цитата
Ну, штатное решение - singleton. Но он вас почему-то не устраивает. А, тем не менее, работает предсказуемо, надёжно и эффективно. Пользуемся.

выше я писал почему не конает... "Нет, вы немного не поняли. Кто лочить будет static Driver instance; ?....."
я еще буду думать, возможно удстся сделать что-то такое, чтобы можно было создавать мютексы в static, тогда см. реализацию синглтона выше

Цитата
Кстати, фреймворк Qt идёт по совсем простому пути - там до старта main(), а точнее, до создания объекта QAppication никакие GUI'ные объекты не рожаются - это запрещено идеологически. Поэтому с порядком создания объектов проблем нет. Очень простой и эффективный способ. Правда, для embedded в том виде, как это там реализовано, это не годицца - там всё это живёт на new.

Моя реализация выше идеологически примерно такая же, только по проще и без new.
conncet прикольная штука у них, сокращает число строк кода, но для embedded не годится.
dxp
Цитата(brag @ Dec 13 2011, 08:51) *
Я синглтоны делаю так:
Код
class BragUI{
public:
    BragUI();
              static BragUI& getInst()const{ return ui; }
private:
    static BragUI ui;
};
....
BragUI::ui=BragUI();

А зачем так сложно и неуниверсально? Почему не сделать так:
Код
template<typename T> class singleton
{
public:
    static T& instance() { static T Instance; return Instance; }
};

?

Тут не нужно руками размещать внутреннюю переменную и нет привязки к конкретному типу - синглтон создаётся под конкретный тип компилятором.
brag
Цитата
А зачем так сложно и неуниверсально? Почему не сделать так:

Уже писал, одновременный вызов static T& instance() { static T Instance;
даст гонки!
вернее захочет это предотвратить и попытается вызвать __cxa_guard_acquire, которая должна в свою очередь обработать это дело (это что касается gcc).
если даже мы ее реализуем, то мютекс не всегда можно создавать, вдруг мы instance() вызовем до того, как можно создавать мютексы?
или еще хуже - вызовем из прерывания, где вообще запрещены всякие блокировки и синхронизация там происходит совсем по другим принцыпам?
dxp
Цитата(brag @ Dec 13 2011, 09:09) *
А как в данном случаи быть иначе?

Я что-то туплю, не понимаю, что тут дают статики.


Цитата(brag @ Dec 13 2011, 09:09) *
выше я писал почему не конает... "Нет, вы немного не поняли. Кто лочить будет static Driver instance; ?....."
я еще буду думать, возможно удстся сделать что-то такое, чтобы можно было создавать мютексы в static, тогда см. реализацию синглтона выше

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


Цитата(brag @ Dec 13 2011, 09:27) *
Уже писал, одновременный вызов static T& instance() { static T Instance;
даст гонки!

Если это так важно, то можно использовать критическую секцию, она оверхеда почти не добавит и динамику не ухудшит.

Цитата(brag @ Dec 13 2011, 09:27) *
вернее захочет это предотвратить и попытается вызвать __cxa_guard_acquire, которая должна в свою очередь обработать это дело (это что касается gcc).
если даже мы ее реализуем, то мютекс не всегда можно создавать, вдруг мы instance() вызовем до того, как можно создавать мютексы?
или еще хуже - вызовем из прерывания, где вообще запрещены всякие блокировки и синхронизация там происходит совсем по другим принцыпам?

Я не понимаю, причём тут мутексы? Для защиты синглтона? Так тут мутексы слишком тяжелы и избыточны - враппер критической секции в этом случае рулит безальтернативно. Возможно, вы имеет в виду какие-то нюансы своего проекта, которые мне неизвестны. Но я и не про конкретный проект говорю, а про синглтоны в общем случае.
brag
Спасибо
У мена какраз на lock-free очередях реализована синхронизация в прерываниях и внутри сис.вызовов. Локов там нет.

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

Цитата
Если это так важно, то можно использовать критическую секцию, она оверхеда почти не добавит и динамику не ухудшит.

Критическая секция, в смысле запрет прерываний? ессли да, то в моем случаи,на пример, этого делать нельзя. прерывания разрешены всегда, еще где-то с начала старта ОС.
а то этим термином много чего называют...
Цитата
Я не понимаю, причём тут мутексы? Для защиты синглтона?

да
Цитата
Так тут мутексы слишком тяжелы и избыточны

Ну у меня они довольно легкие

__cxa_guard тоже документированы в arm cppabi
Цитата
3.2.3.2 One-time construction API
extern "C" int __cxa_guard_acquire(int *guard_object);
If the guarded object has not yet been initialized, this function returns 1. Otherwise it returns 0.
If it returns 1, a semaphore might have been claimed and associated with guard_object, and either
__cxa_guard_release or __cxa_guard_abort must be called with the same argument to release the semaphore.
extern "C" void __cxa_guard_release(int *guard_object);


еще будем думать над этим... к тому же я MPU использую, там все еще хуже...

Цитата
Я что-то туплю, не понимаю, что тут дают статики.

Просто чтобы прятать с глаз всякую муть. в Qt это реализовано аналогично - генерится отдельный ui_ххх.h файл, где есть функция создания всех обьектов интерфейса, запихнуто в namespace.
У меня это тоже отдельный файл, только у меня все построено на статической памяти, а у них на new
AHTOXA
Цитата(brag @ Dec 13 2011, 08:27) *
Уже писал, одновременный вызов static T& instance() { static T Instance;
даст гонки!
вернее захочет это предотвратить и попытается вызвать __cxa_guard_acquire, которая должна в свою очередь обработать это дело (это что касается gcc).
если даже мы ее реализуем, то мютекс не всегда можно создавать, вдруг мы instance() вызовем до того, как можно создавать мютексы?
или еще хуже - вызовем из прерывания, где вообще запрещены всякие блокировки и синхронизация там происходит совсем по другим принцыпам?

Какие нафиг мутексы? Зачем они там? Элементарный флаг:
Код
int __cxa_guard_acquire(__guard *g) {return !*(char *)(g);}
void __cxa_guard_release (__guard *g) {*(char *)g = 1;}

И никаких гонок.
brag
Цитата
Какие нафиг мутексы? Зачем они там? Элементарный флаг:
Код
int __cxa_guard_acquire(__guard *g) {return !*(char *)(g);}
void __cxa_guard_release (__guard *g) {*(char *)g = 1;}

И никаких гонок.

че то я там не увидел, каким образом *g становится 0.
Процитирую еще раз:
Цитата
extern "C" int __cxa_guard_acquire(int *guard_object);
If the guarded object has not yet been initialized, this function returns 1. Otherwise it returns 0.

dxp
Цитата(brag @ Dec 13 2011, 09:45) *
Критическая секция, в смысле запрет прерываний? ессли да, то в моем случаи,на пример, этого делать нельзя. прерывания разрешены всегда, еще где-то с начала старта ОС.
а то этим термином много чего называют...

Да, имелся в виду именно лок прерываний. Но там же он очень короткий - всего несколько инструкций. Мутекс-то всяко потолще будет.
AHTOXA
Цитата(brag @ Dec 13 2011, 09:18) *
че то я там не увидел, каким образом *g становится 0.

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

Потолще онозначно, но на конкретной архитектуре в конкретном месте может быть совсем по другому.
Кроме того, что религия не позволяет запрещать прерывания, может не позволить и проц, скажем в cortex-m3 в thread unprivileged mode этого делать нельзя, вывалимся в UsageFault
Там рулит lock-free конструкция из ldrex/strex, надо будет подумать, как ее можно универсально туда приаттачить...

Цитата
Он изначально инициализирован нулём.

Ну ок.
1. Допуситм g=0;
2. тогда наш return !*(char *)(g); вернет 1
3. тогда, в соответствии "If the guarded object has not yet been initialized", (см Page 19 of 24 ARM IHI 0041C, там даже кусок кода приведен, как и когда вызывается __cxa_guard_acquire) запустится конструктор.
В это время же время сменился тред и эта хрень выполнится опять начиная с пункта 1 и что в итоге будет?
AHTOXA
Цитата(brag @ Dec 13 2011, 09:32) *
Ну ок.
1. Допуситм g=0;
2. тогда наш return !*(char *)(g); вернет 1
3. тогда, в соответствии "If the guarded object has not yet been initialized", (см Page 19 of 24 ARM IHI 0041C, там даже кусок кода приведен, как и когда вызывается __cxa_guard_acquire) запустится конструктор.
В это время же время сменился тред и эта хрень выполнится опять начиная с пункта 1 и что в итоге будет?

Второй тред сначала проверяет первый байт гуарда на равенство нулю. Если не ноль (а у нас уже не ноль), то объект считается инициализированным.
То есть, если поток прервётся до завершения инициализации, то будет бякаsm.gif Поэтому при таком подходе инициализацию желательно выполнять из одного, наиболее приоритетного потока.
brag
Цитата
Второй тред сначала проверяет первый байт гуарда на равенство нулю. Если не ноль (а у нас уже не ноль), то объект считается инициализированным.

Почему это не 0? конструктор запущен, void __cxa_guard_release (__guard *g) {*(char *)g = 1;} еще не вызван . распишите плиз алгоритм а то я чет наврное вас не понял...

Цитата
То есть, если поток прервётся до завершения инициализации, то будет бяка Поэтому при таком подходе инициализацию желательно выполнять из одного, наиболее приоритетного потока.

Тоесть вы предлагаете делать вызов getInstance() из другого приоритетного потока? Представляете сколько у вас уйдет времени на синхронизацию этого дела?

Вообще синхронизация - такая штука, что надо продумывать чуть ли не каждую ассемблерную инструкцию на выходе. Времени очень много занимает, чтобы сделать действительно качественный код без гонок. тестирование здесь не катит. глюк может вылесть спустя годы и натворить большой беды sm.gif
Лучше 1 раз продумать типовые конструкци и потом юзать, чем каждый раз парицца.
AHTOXA
Цитата(brag @ Dec 13 2011, 10:11) *
Почему это не 0? конструктор запущен, void __cxa_guard_release (__guard *g) {*(char *)g = 1;} еще не вызван . распишите плиз алгоритм а то я чет наврное вас не понял...

Да, я неверно описал. Это у нас как раз получается флаг завершения инициализации.
Цитата(brag @ Dec 13 2011, 10:11) *
Тоесть вы предлагаете делать вызов getInstance() из другого приоритетного потока?

Нет, я предлагаю выполнять инициализацию из приоритетного потока. А последующие вызовы getInstance() - уже из любых.
brag
в случаи вашего кода какраз в getInstance() компилятором автоматически встраивается код инициализации static Driver instance;
и для защиты его какраз применяются __cxa_guard
собсно эти guard можно реализовать на основе семафора, запрета прерываний, а можно при поддержке архитектуры на всяких хитрых lock-free конструкциях
AHTOXA
Да, я знаю этоsm.gif
А ещё я знаю, что перед тем, как вызвать __cxa_guard_acquire(), gcc проверяет первый байт гуарда. И если он не ноль, то объект считается инициализированным. И именно на этом факте основано то решение, которое я привёл.
Forger
Цитата(brag @ Dec 13 2011, 05:51) *
Легко. Через интерфейсы. А выбор интерфейса где-то предусмотреть.
А экземпляр обьекта TCP создавать непосредственно перед использованием, к стати и тут может происходить выбор интерфейса.

Т.е. в стеке. А если этот класс имеет массу полей, т.е. немалый размер и толстый конструктор.
Что-то как-то громоздков выходит - каждый раз создавать и удалять объект, с которым это нужно проделывать всего один раз.
Я к чему такие вопросы задавал - наводил на мысль иерархически выстроенного проекта, в котором нет ни одного статического поля, а все классы кому-либо пренадлежат. Т.е. нет ни одного "бесхозного" объекта.

Цитата
Наверное заметили некое сходство с Qt... sm.gif Да, некоторые идеи я передрал с докуминтации Qt wink.gif

Идеи Qt дает интересные, но она изначально ориентирована на кучу.
А чтобы приучить ее к статике - нужно изрядно попотеть, а смысл?
Т.е. в эмбеддерских делах пока ей, по-моему, пока нет места.

Цитата
Нет, вы немного не поняли. Кто лочить будет static Driver instance; ?
Ведь вызватся функция static Driver& Instanse() может одновременно, когда обьект instance еще не создан.
Один тред вызвал Instanse(), та запустила конструктор для instance (тк instance еще не создан) и тут процесс посреди конструктора прервался и кто-то другой опять вызвал Instanse() и ...и сами понимаете что sm.gif
Ведь процесс создания instance мы никак не контроллируем...

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

Цитата
Это процесс создания окошек. А реализация уже в других файлах. в будущем вообще этот код будет софтиной-дизайнером генерится( типа как в Qt sm.gif ).

Я тоже что-то подобное планирую для своей реализации CANopen на чистом С++.
В частности все пользовательские объекты словаря создаются исходя из содержимого EDS-файла.
В коде остается лишь реализовать методы этих объектов, привязав их к конкретномы требованиям девайса.

Цитата
Согласитесь, создание графических обьектов где-попало в коде в разных файлах приведет к еще хужему хаоссу sm.gif

Да, разумеется, должна существовать некая строгая иерархия - кто что может и кто кем владеет.

Цитата
Ну всякие там MessageBox-ы и диалоги ессно создаются в стеке когда это нужно, эти массивы надо только для построения основного ui.

Вот себе и противоречите - это ж опять костыль, в коде их не должно быть - все нужно прятатять в глубине самого gui.
А GUI нужно только указать ссылку на экзэмпляр OS и драйвер экрана. Что-то типа того.
Программер, который юзает гуи не должен думать о том, где чего создать в стеке и как обезапасить код.
Это все должно быть сделано и отлажено один раз - в гуи.

Короче, вот что я предлагал и предлагаю:
http://electronix.ru/forum/lofiversion/index.php/t82244.html
Правда, щас немного по-ловчее и лаконичнее, но в целом такая конструкция кода работает на ура.

brag
Цитата
Т.е. в стеке. А если этот класс имеет массу полей, т.е. немалый размер и толстый конструктор.

Все зависит от конкретной ситуации... стандартного решения "под онду мерку" нету

Цитата
Идеи Qt дает интересные, но она изначально ориентирована на кучу.А чтобы приучить ее к статике - нужно изрядно попотеть, а смысл?
Т.е. в эмбеддерских делах пока ей, по-моему, пока нет места.

Ну мы их и переориентировали на arm sm.gif код то свой, содраны только части названий и некоторые идеи

Цитата
Синглтоном может быть, например, сама OS.

Она довольно раздутая в плане обхвата, там своя организация...

Цитата
Это все должно быть сделано и отлажено один раз - в гуи.

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

brag
Наткнулся на такой прикол (скорее всего из за незнания C++ sm.gif)
Код
MsgBox box(0,"Writing...");box.show();
.....
box.close();
box=MsgBox(0,"OK");box.show()

Я думал box=MsgBox(0,"OK"); работает аналогично delete box;box=new MsgBox(0,"OK"); только без выделения памяти, используя стековую переменную.
А оказалось оно создает новый MsgBox(0,"OK"); при чем не удаляя старого, тупо копирует из него все данные в box, а потом удаляет этот временный MsgBox(0,"OK");
В итоге при создании MsgBox он становится во всякие системные очереди итп(используя указатель this), затем сразу же после копирования удалятся из всяких очередей. А вот копия уже нерабочая - все указатели были на временный обьект, а не на реальный box, к тому же обьект вообще считается удален, тк был вызван деструктор. Ну и старый обьект вообще затертый, но не удаленный, тк для него небыл вызван деструктор
Код
new box
Widget(): 00007EEC
Widget(): 00007E5C
~Widget(): 00007E5C
Widget()::show(00007EEC)

Вобщем я пришел к выводу, что так делать нельзя, а запариватся с перегрузкой оператора = тоже влом
neiver
В данном случае, лучше вообще запретить копирование - сделать конструктор копирования и оператор присваивания закрытыми и без реализации.
brag
Да вот я какраз хотел запретить. Спасибо за подсказку
Запретить бы вообще копирование по дефолту
neiver
Цитата(brag @ Mar 2 2012, 15:43) *
Да вот я какраз хотел запретить. Спасибо за подсказку
Запретить бы вообще копирование по дефолту

Легко.
Код
class NotCopyable
{
private:
    NotCopyable(const NotCopyable&);//конструктор копирования
    NotCopyable & operator=(const NotCopyable&);//оператор присваивания
};
...
class Foo :NotCopyable
{
public:
...
};

В классе NotCopyable конструктор копирования и оператор присваивания закрыты и не имеют реализации. Все классы, копирования которых мы хотим запретить, просто наследуем от NotCopyable.
brag
neiver, типа такого и сделал, чтоб меньше буковок было.. Вот бы не забывать от него наследоватся, вернее взять за правило от него наследоватся всегда. (копи-абельные классы - в виде исключений, в основном просто структуры данных)
я имел в виду в компилере отключить эти '=' и default copy constructor
но тогда штука типа int a=21 работать не быдет, так что прийдется все же помнить про такой базовый класс
brag
Из соседней ветки возник вопрос по умным указателям
Допустим есть такая штука(типа наш указатель):
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
neiver
Вообще-то такой указатель должен канонично называться shared_ptr. smart_ptr - это уж больно общее название объектов, изображающих из себя указатели.
Еще надо не забыть ref_ctr сделать потоко-безопасным. Сейчас если такой указатель поделить между потоками, то... Наследовать данные от счетчика ссылок? Ну не знаю. Уж лучше в этот счетчик добавить указатель на данные.
Я когда делал подобную вещь, организовал shared_ptr-ы в связанный список. shared_ptr содержит указатель на данные и указатель на следующий shared_ptr в списке. Список можно сделать односвязный, двусвязный - как больше нравится. Скопировали указатель - добавили в список, при уничтожении - убрали из списка, удалили последний указатель - удалили данные. Если аккуратно реализовать, то будет потокобезопасно, поскольку нет разделяемых между потоками объектов.
brag
Имена, то такое, это пример sm.gif
Потокобезопастность всегда прикручиваю позже, когда она нужна, наследуясь от потоконебезопасного класса и вешаю необходимую приблуду, а они могут быть разные (от запрета переключения контекста до хитрых 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;
}
brag
Возникла тут задача с аналогичным смыслом, который был изложен господином 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] со всевозможными опциями оптимизации дали положительный результат.
brag
Ну и еще один вариант, гарантирующий однозначность в принципе но увеличивающий размер кода, но без ущерба производительности. Использовать предефайнд-константу __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() однозначно будет иметь свое имя, и ессно свой адрес. Хотя есть еще алиасы, хз в общем sm.gif) Будем надятся, что линкер не на столько умный, чтобы сливать функции с разными именами и одинаковым телом в одну wink.gif
При самой агрессивной оптимизации ничего криминального не произошло:
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
brag
До коллекции еще один вариант, без виртуальных функций - чуть выше производительность при проверке типа и исполняемый код меньше.
Код
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) {}
};
AVR
Цитата(Forger @ Dec 13 2011, 12:55) *
Идеи Qt дает интересные, но она изначально ориентирована на кучу.
А чтобы приучить ее к статике - нужно изрядно попотеть, а смысл?
Т.е. в эмбеддерских делах пока ей, по-моему, пока нет места.


шутки шутками, а я на полном серьезе просто воткнул Linux на ARM SAM9G45, зарядил туда Qt и спокойно пишу на своей любимой библиотеке

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

в моей гипер-мега-системе два ARM-а разных классов (второй Cortex-A9), один x86, ну и еще телефон на базе Android - с помощью Qt я спокойно пишу код который совместим со всеми этими платформами и любыми ОС в широком смысле

ЗЫ
некоторые даже предпочтут питон или даже Mono/C# для своих проектов, ускоряя критичные участки нативщиной =)
brag
AVR, все так, только linux і Qt не вдуть на проц с 64кб озу sm.gif а городить тяжеловес как-то не логично,особенно,если от батарейки должен работать.. Хотя может скоро и можно будет себе такое позволить - даешь дешевые китайские платы,дешевые армы, дешевый фен шоб паять BGA есть sm.gif)
AVR
Цитата(brag @ Jun 18 2012, 10:46) *
AVR, все так, только linux і Qt не вдуть на проц с 64кб озу sm.gif а городить тяжеловес как-то не логично,особенно,если от батарейки должен работать.. Хотя может скоро и можно будет себе такое позволить - даешь дешевые китайские платы,дешевые армы, дешевый фен шоб паять BGA есть sm.gif)

всё зависит от задачи и величины партии, а чтобы работал от батарейки - есть специальные меры в ОС Linux для этого... вот сколько стоит 32 Мб DDR2? а теперь берете калькулятор и считаете - вам проще потратить три копейки и влепить ОСь Linux и кучу дешевой рамы или страдать дедовским способом? sm.gif

в общем, для мелких и средних партий я сторонник полновесной ОС (Linux лишь одна из таких), быть может такие проекты и есть то большинство...
dxp
QUOTE (AVR @ Jun 19 2012, 02:27) *
всё зависит от задачи и величины партии, а чтобы работал от батарейки - есть специальные меры в ОС Linux для этого... вот сколько стоит 32 Мб DDR2? а теперь берете калькулятор и считаете - вам проще потратить три копейки и влепить ОСь Linux и кучу дешевой рамы или страдать дедовским способом? sm.gif

в общем, для мелких и средних партий я сторонник полновесной ОС (Linux лишь одна из таких), быть может такие проекты и есть то большинство...

А не оценивали, как влияет на энергопотребление использование такой взрослой оси (да ещё и + Qt)?
AVR
Цитата(dxp @ Jun 19 2012, 08:48) *
А не оценивали, как влияет на энергопотребление использование такой взрослой оси (да ещё и + Qt)?
не совсем понял, это скорее намек или вопрос? я полагаю что энергопотребление при работе Linux и Qt будет несколько выше

я сравнивал официальные отчеты от Ti для OMAP3 - при максимальной нагрузке - разницы между потреблением с ОС и без нее - не нашел, при отсутствии нагрузки - да, у Linux было процентов на 15 выше, не более

но как и во всем, есть недосказанные моменты - у Linux есть специальные средства для отладки энергопотребления системы, чтобы всегда знать что не дает держать процессор в глубоком сне и минимальном потреблении, да и сама ОС Linux жрет скорее оперативку, чем процессор - что приятно

а учитывая HRT возможности Linux-а с его максимум 25 мкс что я видел в одном из тестов - вообще универсальная ОСь получается - ни за что ее не променяю, и подкормлю сотней милливатт если надо sm.gif

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

ясно одно - PoP у нас уже есть, так что скоро все эти разговоры про сложность разводки DDR2/3 для возможности запуска полновесной ОС типа Linux уже не будет стоять так остро, останется лишь вопрос цены, но объемы оперативной памяти растут, а "минимальные системные требования" у Linux с годами растут крайне медленно

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

не соглашусь и с временем обучения работы с софтом - и чего же стоит драйвер написать? правильно ли я понял что данная оценка из личного опыта?
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.