ICC AVR и стpоки - Page 4

Do you have a question? Post it now! No Registration Necessary

Translate This Thread From Russian to

Threaded View
ICC AVR и стpоки
Hello Vladimir.

24 Sep 03 18:35, Vladimir Vassilevsky wrote to Yuriy K:

 VV>  Да даже менюшный ввод/вывод на двухстрочник удобнее писать на ++.

ты пpо pеализацию или использование?

Пpо pеализацию

деpево меню pеализyется связным списком, пpичем тyт С/С++/любой дpyгой язык ?

Пpо использование

есть набоp модyлей, котоpым я пользyюсь для вывода на экpан 16х4 ЖКИ
(на самом деле инфа посылается чеpез CAN в модyль, к котоpомy подключен ЖКИ)

=== Begin Windows Clipboard ===
    /* стираем дисплей и выводим статическую информацию на дисплей */
    SsScrPutStr ("  Версия ПО", 0,    SCR_CONST_STR_FLG | SCR_DISP_CLR_FLG);
    SsScrPutStr ("  "VERSION_STR, 0,  SCR_POS_L2 | SCR_POS_P1 |
SCR_CONST_STR_FLG);
=== End Windows Clipboard ===

Главное пpоблема в ++ для меня - надо _по-дpyгомy_ пpоектиpовать.

Си++ пока не пpименял, но там есть вкyсности вpоде шаблонов (но их нет в EC++),
inline, (pеже надо делать cast.

Alexey


ICC AVR и стpоки
Thu Sep 25 2003 12:51, Alexey Musin wrote to Vladimir Vassilevsky:


 VV>>  Да даже менюшный ввод/вывод на двухстрочник удобнее писать на ++.
 AM> ты пpо pеализацию или использование?

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

 AM> Пpо pеализацию

 AM> деpево меню pеализyется связным списком, пpичем тyт С/С++/любой дpyгой
 AM> язык ?

 Совершенно необязательно. Способов много: в лоб, через машину состояний,
 событийно управляемое или функционально управляемое,
 c/без многозадачностью и пр.
  

 AM> Пpо использование

 AM> есть набоp модyлей, котоpым я пользyюсь для вывода на экpан 16х4 ЖКИ
 AM> (на самом деле инфа посылается чеpез CAN в модyль, к котоpомy подключен
 AM> ЖКИ)

 AM> === Begin Windows Clipboard ===
 AM>     /* стираем дисплей и выводим статическую информацию на дисплей */
 AM>     SsScrPutStr ("  Версия ПО", 0,    SCR_CONST_STR_FLG |
 AM> SCR_DISP_CLR_FLG);
 AM>     SsScrPutStr ("  "VERSION_STR, 0,  SCR_POS_L2 | SCR_POS_P1 |
 AM> SCR_CONST_STR_FLG); === End Windows Clipboard ===


 То есть в лоб. Добавить/убавить/изменить при этом подходе что-то сложно.

 menu = new MENU(RESOURCE, enter); все меню описано как ресурс -
 и куда оно входит, и куда оно выходит, и что и как вводится.

 AM> Главное пpоблема в ++ для меня - надо _по-дpyгомy_ пpоектиpовать.

 Просто дело привычки и вкуса.

 VLV


Re: ICC AVR и стpоки
Hello, Harry Zhurov !

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

Да элементарно. Или еще один массив с типами (если их не много) а потом switch
по этому параметру, или switch прямо по индексу в массиве. И пиши себе в ветках
обработку без всяких косвенных вызовов.

С уважением, Дима Орлов.


Re: ICC AVR и стpоки
Hello "Harry.

26 Sep 03 21:35, you wrote to me:

 HZ>>>     А они в С/С++ только одномерными и бывают. int A[5][4] - это
 HZ>>> тоже одномерный массив размером [5]*[4].
 AB>> ??? чего-то тебя не в ту степь понесло.

 HZ>     Будь А полноценным двумерным массивом - т.е. законченным,
 HZ> целостным объектом, то выражение:
 HZ>         А + 1
 HZ>     означало бы адрес следующего такого двумерного массива,

Это эще почему? 'A' ведь не является указателем на объект, а есть сам объект.
(Я не имею в виду, что в Си можно имя массива использовать как указатель)

 HZ>     Hадеюсь, ты не будешь спорить с тем, что двумерный массив и массив
 HZ> массивов - это разные вещи?

Что то я в этом не уверен. Если массив разных массивов, тогда разница есть,
но в Си нельзя без хаков объявить массив разных массивов.

 HZ>     Вот теперь ты снова реши, в ту ли степь меня понесло или нет?! :)

Тебя понесло в математическое философствование. Я же отношусь к массиву по
простому - по программистскому. ;)

 AB>> Вижу, ты очень сильно заплюсовался. Hикаких функций писать я не
 AB>> предлагал. В массивах max, min, delta я предлагал хранить числа, а
 AB>> не адреса функций.
 HZ>     Hу, тогда я вообще ничего не понял - как ты собираешься
 HZ> реализовать ту функциональность, которая была приведена в том примере:

 HZ>  // ----------------------------------
 HZ>     ...
 HZ>     if( keySelect.IsClick() ) CurrentParameter++;
 HZ>     if( keyPlus.IsClick()   ) CurrentParameter->Increase();
 HZ>     if( keyMinus.IsClick()  ) CurrentParameter->Decrease();
 HZ>     ...
 HZ>  // ----------------------------------

 HZ>     Как ты предлагаешь достичь того же без функций, а только с помощью
 HZ> какого-то массива?

дык я же вроде приводил кусочек кода.

if (keySelect.IsClick()) // В данном случае я не рассматриваю опрос кнопок
                    CurrentParameter = (CurrentParameter+1) % ParameterCount;

if (keyPlus.IsClick()) {
    if ((current[CurrentParameter] += delta[CurrentParameter]) >
max[CurrentParameter]) {
        current[CurrentParameter] = max[CurrentParameter];
    }

if (keyMinus.isClick()) {
    if ((current[CurrentParameter] -= delta[CurrentParameter]) <
min[CurrentParameter]) {
        current[CurrentParameter] = min[CurrentParameter];
    }
}

Я не предлагаю реализовывать функциональность С++ на Си. Просто на Си принято
по
другому писать.

Видел GTK+? это реализация С++ функциональности на Си. Жуткая штука. Hо
работает.

 HZ>     Во-первых, первый и второй варианы предоставляют весьма различную
 HZ> функциональность, поэтому говорить, что первый вариант отстойный, и
 HZ> надо пользоваться вторым, т.к. он эффективнее, не слишком разумно. Они
 HZ> не лучше или хуже друг друга, они просто разные.

Да.

 HZ>     Во-вторых, много команд в первом варианте берется из-за того, что
 HZ> процессор-то 8-разрядный, а адреса-то 16-разрядные.

Вот я привел пример для 32-х разрядного.


Alexey


Re: ICC AVR и стpоки
27-Sep-03 12:36 Alexey Boyko wrote to "Harry Zhurov" <Harry Zhurov:

HZ>>     Как ты предлагаешь достичь того же без функций, а только с помощью
HZ>> какого-то массива?

AB> дык я же вроде приводил кусочек кода.

AB> if (keySelect.IsClick()) // В данном случае я не рассматриваю опрос
AB> кнопок
AB>                     CurrentParameter = (CurrentParameter+1) % ParameterCount;

AB> if (keyPlus.IsClick()) {
AB>     if ((current[CurrentParameter] += delta[CurrentParameter]) >
AB> max[CurrentParameter]) {
AB>         current[CurrentParameter] = max[CurrentParameter];
AB>     }
 Даже не так, а в таком духе (всё сложнее, это так, псевдокод).

  u08 key;
  do {
    key=GetKey();
    switch( key) {
    case KEY_ESC:
      break;

    case KEY_LEFT:
    case KEY_RIGHT:
      if( fNeedSave) SaveParameter( parampage, paramno);
      if( KEY_LEFT) {
        if( --paramno < 0)
          paramno = maxparam[ parampage];
      } else {
        if( ++paramno > maxparam[parampage] )
          paramno = 0;
      }
      LoadParameter( parampage, paramno);
      break;

    case KEY_INC:
      ++parameter;
    // и т.д.

   } while( key != KEY_ESC);

 На самом деле параметры описываются массивами структур во флеше,
массивами указателей на эти массивы и т.п. Всё инициализируется
статически, да, структура меню жёстко забита во флеше.
У каждого параметра в структуре описателя - его тип (int, byte,
string), начальный адрес в EEPROM, длина (для строк), min и max
значения (для int/byte), после смены параметра по ещё одному
небольшому switch() вызывается нужная функция Edit() (и уже она
делает GetKey() и разбирает INC/DEC/CLR, по KEY_UP возвращается
на уровень перебора параметров).
 Итого всё меню конфигурирования - это немножко кода
и таблицы констант, которые занимают _гораздо_ меньше места, чем
если бы это всё реализовывать в виде функций или кода по switch().
В некотором смысле машина состояний, заданная в виде таблиц переходов,
а не в виде структуры кода.
И в итоге нет никаких многоэтажных switch, которые предлагается
заменить на виртуальные функции и (всё равно!) массив указателей
на экземпляры классов Parameter, по которому ходит указатель
CurrentParameter.

AB> Просто на С принято по другому писать.
 Вот именно. И, самое главное, это все не есть "попытка эмуляции
средствами C поведения C++".

wbr,
--
/* Oleksandr Redchuk, Brovary, Ukraine */
/* real '\x40' real '\x2E' kiev '\x2E' ua     */


ICC AVR и стpоки
Oleksandr Redchuk wrote to Alexey Boyko
(UTC):

HZ>>>     Как ты предлагаешь достичь того же без функций, а только с помощью
HZ>>> какого-то массива?

AB>> дык я же вроде приводил кусочек кода.

AB>> if (keySelect.IsClick()) // В данном случае я не рассматриваю опрос

[...]

OR>  Даже не так, а в таком духе (всё сложнее, это так, псевдокод).

OR>   u08 key;
OR>   do {

[...]

OR>     // и т.д.

OR>    } while( key != KEY_ESC);

OR>  На самом деле параметры описываются массивами структур во флеше,
OR> массивами указателей на эти массивы и т.п. Всё инициализируется
OR> статически, да, структура меню жёстко забита во флеше.
OR> У каждого параметра в структуре описателя - его тип (int, byte,
OR> string)

    А что такое "увеличить/уменьшить" для строки? Я так понимаю, что имеется в
виду обычная С-строка?

OR> , начальный адрес в EEPROM, длина (для строк), min и max значения (для
OR> int/byte), после смены параметра по ещё одному небольшому switch()
OR> вызывается нужная функция Edit() (и уже она делает GetKey() и разбирает
OR> INC/DEC/CLR, по KEY_UP возвращается
OR> на уровень перебора параметров).
OR>  Итого всё меню конфигурирования - это немножко кода
OR> и таблицы констант, которые занимают _гораздо_ меньше места, чем
OR> если бы это всё реализовывать в виде функций или кода по switch().

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

OR> В некотором смысле машина состояний, заданная в виде таблиц переходов,

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

OR> И в итоге нет никаких многоэтажных switch, которые предлагается
OR> заменить на виртуальные функции

    И в итоге совсем не та функциональность, как и положено. Как где-то у
Страуструпа было написано: "Чтобы оценить мощь указателей на функции, нужно
попытаться сделать то, где они применяются, без них".

OR> и (всё равно!) массив указателей на экземпляры классов Parameter, по
OR> которому ходит указатель CurrentParameter.

    А чем оно тебе так не нравится? Уж по читабельности, понятности и
логичности вариант с простым линейным массивом однокачественных объектов куда
как лучше, чем даже тот кусок псевдокода (а уж что там за монстр в конечной
реализации, можно только представить!)

    Убежден, что ты все это знаешь лучше меня, и тем более не понятно, с чем ты
тут споришь?

AB>> Просто на С принято по другому писать.
OR>  Вот именно. И, самое главное, это все не есть "попытка эмуляции
                    ^^^^^^^^^^^^^
OR> средствами C поведения C++".

    :)) Так это, оказывается, принципиальная позиция?! Хотя тут и нет ни
попытки эмуляции, ни самой эмуляции - тут нет, самое главное, того же
результата по функциональности, который дают самые обычные массивы указателей
на функции. Т.ч. сравнивать просто нечего.


...so long!

### Чтобы был тонкий юмор, нужны толстые знания.



Re: ICC AVR и стpоки
28-Sep-03 11:02 Harry Zhurov wrote to Oleksandr Redchuk:

OR>>  На самом деле параметры описываются массивами структур во флеше,
OR>> массивами указателей на эти массивы и т.п. Всё инициализируется
OR>> статически, да, структура меню жёстко забита во флеше.
OR>> У каждого параметра в структуре описателя - его тип (int, byte,
OR>> string)

HZ>     А что такое "увеличить/уменьшить" для строки? Я так понимаю, что
HZ> имеется в виду обычная С-строка?
 Ну я же сказал сразу, что это "так, наляпано", а на самом деле
на этом уровне только навигация, редактирование вызывается отсюда:

OR>> , начальный адрес в EEPROM, длина (для строк), min и max значения (для
OR>> int/byte), после смены параметра по ещё одному небольшому switch()
OR>> вызывается нужная функция Edit() (и уже она делает GetKey() и разбирает
OR>> INC/DEC/CLR, по KEY_UP возвращается
OR>> на уровень перебора параметров).
 А inc/dec применяются не к строке, а к символу (а как ещё
отредактировать текстовую строку пятью кнопками :-).

OR>>  Итого всё меню конфигурирования - это немножко кода
OR>> и таблицы констант, которые занимают _гораздо_ меньше места, чем
OR>> если бы это всё реализовывать в виде функций или кода по switch().

HZ>     Экономия кода достигается исключительно за счет унификации
модифицирования

HZ> параметров. Это работает только когда параметры однокачественные (числа,
HZ> например).
 Ну, во первых,

18 Sep 03 21:46, you wrote to Dimmy Timchenko:
 HZ> // ----------------------------------
 HZ>     ...
 HZ>     if( keySelect.IsClick() ) CurrentParameter++;
 HZ>     if( keyPlus.IsClick()   ) CurrentParameter->Increase();
 HZ>     if( keyMinus.IsClick()  ) CurrentParameter->Decrease();
 HZ>     ...
 HZ> // ----------------------------------
в приведённом примере тоже как-то параметры могут только увеличиваться
и уменьшаться, достаточно ограниченная модель. А когда тебе это
написали на C, ты сразу "ну так это ограниченное решение!".

  А во-вторых - ты не вчитался. Повторяю. Каждый параметр описывается
структурой, в которой кроме его положения в EEPROM задан его тип.
По типу мы можем вызвать нужную функцию редактирования.
  Экономия кода заключается в том, что сам вызов функций чтения и
записи EEPROM при редактировании конфигурации имеется в одном
единственном месте, т.е. не в каждой виртуальной функции каждого
параметра (группы параметров с одинаковым редактированием).

Вместо

CurrentParameter->Load(); // косвенный вызов через vmt
// у каждого параметра персонально
SomeParameter::Load() {
    EEread( this, смещение, длина);
}

имеем
 eeparam *parptr = &eep_table[parmano];
// ptr будет использован много раз ниже, при редактировании,
// проверке и записи назад
 EEread( editbuf, parptr->offset, parptr->len);
// editbuf - буфер в функции конфигурирования размером с самый
// длинный параметр

Аналогично с вызовом редактирующей функции, аналогично с проверкой
на min/max для целочисленных параметров -- этот код в единственном
месте для всех таких параметров. Из структуры-описателя параметра
берутся его min и max значения.


HZ> Как только нужно кроме простого инкремента/декремента делать
HZ> еще
HZ> что-то разное для разных параметров, то и привет вашим массивам без
HZ> функций.
 Зависит от того, сколько вариантов этого "что-то разное".
Будет или
 switch( parptr->type) {
 case PARAM_INT:
 case PARAM_STRING:
или
 (param_editors[parptr->type])( )


OR>> В некотором смысле машина состояний, заданная в виде таблиц переходов,

HZ>  А чем принципиально отличается передача потока управления по таблице
HZ> переходов от передачи оного по таблице указателей на функции?
 Принципиальной разницы нет, ты назвал две вещи, которые практически
одинаковы (переходы по индексам из массива и переходы по адресам из
массива). И обе эти вещи не используются в такой организации меню
вообще.
 В случае с несколькими страницами параметров по кучке параметров
в каждом передачи потока управления не происходит. В данном случае
"граф" переходов машины примитивен и реализуется на ++parampage
--parampage ++paramno --paramno. В массивы забиты не переходы,
а действия в состояниях -- и то не все, действие EEread производится
каждом, поэтому в массиве для этого действия хранится информаация
"где и сколько".

HZ>     И в итоге совсем не та функциональность, как и положено.
 По сравнению с чем? А то ты уже писал пример для Тимченко, тебе
изобразили решение на массивах на C, а вышло "не та
функциональность". Перечисли нужную функциональность _ДО_ того,
как тебе напишут пример на C.

HZ> Как где-то у
HZ> Страуструпа было написано: "Чтобы оценить мощь указателей на функции,
 А то я не знаю, какая это классная штука, особенно если она на
процессоре легко реализуема.

HZ> нужно попытаться сделать то, где они применяются, без них".
  Знаешь, система меню редактрования параметров может обойтись
без указателей на функции очень легко. Сейчас в однокристалках
я "вспомнил" подход, который применял для построения многоуровневых
иерархических меню в бытность на ДВК. На VT100. А когда
в лаборатории появился "Невроз И9.66" и кто-то из не видевших
до этого ничего студентов что-то ляпнул в сторону ДВК в духе
"этот гроб" - я сел и переделал на ДВК это меню в "как у нортона",
да в окошке график вывел, а там КЦГД был, а это 800 по горизонтали :-)
Вот там в "активной" части указатели на функции были, а вот при
редактировании параметров -- ну не нужны они. Без них код меньше был,
несмотря на то, что на PDP работа с указателями превосходна.
А мне это жгло, памяти-то 56КБ было на всех с операционкой.


HZ>     А чем оно тебе так не нравится? Уж по читабельности, понятности и
HZ> логичности вариант с простым линейным массивом однокачественных объектов
HZ> куда как лучше,
 А вот тут я скажу "функциональность не та" :-)
У меня там несколько страниц параметров, с разным числом параметров
на странице :-))

HZ> чем даже тот кусок псевдокода (а уж что там за монстр в
HZ> конечной реализации, можно только представить!)
 Программа, которая на ДВК вводила картинки с моего контроллера,
легонько обрабатывала их (некоторое количество фильтров, гистограмма,
яркость/контраст), вырезала куски, показывала на монохромном
мониторе (с дизерингом) - вместе с движком меню и его содержимым
была около 1100 строк. Правда, с малым довльно количеством
комментариев и с форматированием
  if() {
  } else {
  }
  for(;;) {
  }
и т.д. На 24 строках и при медленных матричниках с постоянным
дефицитом бумаги делать
  if ()
  {
  }
  else
  {
  }
                    // внимание - пустая строка
  for()
  {
  }
жаба давила.

Я тогда страшно гордился тем, какие большие программы я пишу :-)

HZ>     Убежден, что ты все это знаешь лучше меня, и тем более не понятно, с
HZ> чем ты тут споришь?
 Я, излагая своё видение, пытаюсь понять - о чём мы спорим :-)
 Первый момент кажется ясен:
Ты считаешь, что C++ можно и НУЖНО применять всем и вплоть до самых
   мелких программ.
Я считаю, что даже на средних программах его стоит применять только тем,
   кто и так "по жизни" без него не может обойтись, а уж на мелких
   задачах переходить на него только потому, что он имеет (длинный
   список) преимуществ на очень больших проектах -- смысла не вижу.

Вторая точка, похоже, сформулирована Алексеем.
AB>>> Просто на С принято по другому писать.
OR>>  Вот именно. И, самое главное, это все не есть "попытка эмуляции
HZ>                     ^^^^^^^^^^^^^
OR>> средствами C поведения C++".
HZ>     :)) Так это, оказывается, принципиальная позиция?!
 Ну раз ты обычное и стандартное от рождения языка C упрятывание от
пользователя ненужных ему внутренних переменных и функций (а заодно
уменьшение размера объектников и сокращение времени работы линкера)
при помощи static обозвал "попыткой средствами С проэмулировать
поведение C++" -- я считаю своим долгом этот момент особо отмечать :-)))

HZ> попытки эмуляции, ни самой эмуляции - тут нет, самое главное, того же
HZ> результата по функциональности, который дают самые обычные массивы
HZ> указателей на функции. Т.ч. сравнивать просто нечего.
 Ну уж не волнуйся. Там, где я считаю указатели на функции
осмысленными -- я их применяю. А через период пихания их, очень
мне понравивщихся, во все дыры - я прошёл довольно давно.
Сейчас уже
 (mode ? func1 : func2) (param1, param2, param3);
или
 (mode ? struct1 : struct2)->func(param1, param2, param3);
не пишу :-)
И могу оценить где они нужны, а где надо написать небольшой
"движок" а его функциональность забить в массив структур или
отдельные массивы. И движок обеспечит навигацию по сложному
многоуровневому меню без указателей на функции (за исключенем
тех мест, где вызывается действие). А задано всё меню будет при
помощи статически инициализированных массивов структру, ссылающихся
на другие массивы структур, отдельные структуры, строки и массивы
строк. И увидеть на распечатке структуру получившегося меню
гораздо проще, чем продираться сквозь
menu1.addItem( new menuitem(..., ..., ..., ...) )
не говоря уже о гораздо более коротком коде.
Это выходило что-то типа .rc-файла при программировании в винде.
(только, чесслово, оно не пыталось его эмулировать :-))

wbr,
p.s. кстати, о функциональности.
awk, а тем более perl имеют ГОРАЗДО БОЛЬШИЕ возможности, чем sed.
Но у меня на машине есть и awk, и sed (перла нет, нужды для себя
пока не вижу). Но почему-то я в подавляющем большинстве случаев
вызываю sed. Странно, ведь у awk-а то функциональность ого-го...

--
/* Oleksandr Redchuk, Brovary, Ukraine */
/* real '\x40' real '\x2E' kiev '\x2E' ua     */


ICC AVR и стpоки
Sep 2003 18:00:52 +0000 (UTC):


[...]

OR> 18 Sep 03 21:46, you wrote to Dimmy Timchenko:
HZ>> // ----------------------------------
HZ>>     ...
HZ>>     if( keySelect.IsClick() ) CurrentParameter++;
HZ>>     if( keyPlus.IsClick()   ) CurrentParameter->Increase();
HZ>>     if( keyMinus.IsClick()  ) CurrentParameter->Decrease();
HZ>>     ...
HZ>> // ----------------------------------
OR> в приведённом примере тоже как-то параметры могут только увеличиваться
OR> и уменьшаться, достаточно ограниченная модель. А когда тебе это
OR> написали на C, ты сразу "ну так это ограниченное решение!".

OR>   А во-вторых - ты не вчитался. Повторяю. Каждый параметр описывается
OR> структурой, в которой кроме его положения в EEPROM задан его тип.
OR> По типу мы можем вызвать нужную функцию редактирования.

[...]

OR> Это выходило что-то типа .rc-файла при программировании в винде.
OR> (только, чесслово, оно не пыталось его эмулировать :-))

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


OR> wbr,
OR> p.s. кстати, о функциональности.
OR> awk, а тем более perl имеют ГОРАЗДО БОЛЬШИЕ возможности, чем sed.
OR> Но у меня на машине есть и awk, и sed (перла нет, нужды для себя
OR> пока не вижу). Но почему-то я в подавляющем большинстве случаев
OR> вызываю sed. Странно, ведь у awk-а то функциональность ого-го...

    А я вот перешел. Задачи-то те же, простенькие вполне, но реализовывать их
на awk проще. Из однозначно полезного, что упрощает работу, это явно выраженные
секции начала и окончания (BEGIN, END), "человеческие" операторы управления
(if, for etc) и предварительный разбор строки на элементы, когда к ним можно
обращаться как $n, где n - номер элемента в строке. Все это весьма упрощает
работу, так почему бы не пользоваться? Из соображений, что "все это можно и на
SED'е сделать?" :)))

...so long!

### Убегая от бандитов, милиционер Грищенко выстрелил три раза задом...




ICC AVR и стpоки
Alexey Boyko wrote to "Harry Zhurov" <Harry Zhurov on Sat, 27 Sep 2003 12:36:58
+0400:

HZ>>     Будь А полноценным двумерным массивом - т.е. законченным,
HZ>> целостным объектом, то выражение:
HZ>>         А + 1
HZ>>     означало бы адрес следующего такого двумерного массива,

AB> Это эще почему? 'A' ведь не является указателем на объект, а есть сам
AB> объект.

    Да, наврал, прошу прощения?! Правильно объяснение такое: в операциях
адресной арифметики имя массива неявно преобразовывается к указателю на первый
элемент массива. Соответственно выражение:

        А + 1

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

    Но в любом случае С/С++ массив int A[n][m] ведет себя как:

        typedef int [m] SubArray;

        SubArray A[n];

AB> (Я не имею в виду, что в Си можно имя массива использовать как указатель)

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

HZ>>     Hадеюсь, ты не будешь спорить с тем, что двумерный массив и массив
HZ>> массивов - это разные вещи?

AB> Что то я в этом не уверен. Если массив разных массивов, тогда разница есть,

    Массив - это агрегатный тип, состоящий из _одинаковых_ элементов.
Соответственно, массивов с неодинаковыми элементами в С/С++ не бывает!

AB> но в Си нельзя без хаков объявить массив разных массивов.

    Структура - это агрегатный тип, допускающий наличие разных элементов.
Следовательно, "массив разных массивов" - это может быть структура. Но
структура - _не_ массив!


HZ>>     Вот теперь ты снова реши, в ту ли степь меня понесло или нет?! :)

AB> Тебя понесло в математическое философствование. Я же отношусь к массиву по
AB> простому - по программистскому. ;)

    Нет тут ни математики, ни философии - все одно только сплошное
программирование в контексте С/С++, которые вполне четко определяют массивы. И
детальное понимание таких вещей очень важно, иначе можно легко получить
неожиданности.


AB>>> Вижу, ты очень сильно заплюсовался. Hикаких функций писать я не
AB>>> предлагал. В массивах max, min, delta я предлагал хранить числа, а
AB>>> не адреса функций.
HZ>>     Hу, тогда я вообще ничего не понял - как ты собираешься
HZ>> реализовать ту функциональность, которая была приведена в том примере:

HZ>>  // ----------------------------------
HZ>>     ...
HZ>>     if( keySelect.IsClick() ) CurrentParameter++;
HZ>>     if( keyPlus.IsClick()   ) CurrentParameter->Increase();
HZ>>     if( keyMinus.IsClick()  ) CurrentParameter->Decrease();
HZ>>     ...
HZ>>  // ----------------------------------

HZ>>     Как ты предлагаешь достичь того же без функций, а только с помощью
HZ>> какого-то массива?

AB> дык я же вроде приводил кусочек кода.

AB> if (keySelect.IsClick()) // В данном случае я не рассматриваю опрос кнопок
AB>                  CurrentParameter = (CurrentParameter+1) % ParameterCount;
                                         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
                                          |
    Крайне неэффективный способ по сравнению с обычной проверкой перехода через
границу массива. Но тут писать явно код проверки - это еще более загромоздить
этот фрагмент программы.

AB> if (keyPlus.IsClick()) {
AB>     if ((current[CurrentParameter] += delta[CurrentParameter]) >
AB> max[CurrentParameter]) {
AB>         current[CurrentParameter] = max[CurrentParameter];
AB>     }

AB> if (keyMinus.isClick()) {
AB>     if ((current[CurrentParameter] -= delta[CurrentParameter]) <
AB> min[CurrentParameter]) {
AB>         current[CurrentParameter] = min[CurrentParameter];
AB>     }
AB> }

    Это код _совершенно_ функционально не эквивалентен варианту с функциями (не
важно, на каком языке). Функция реально делает помимо увеличения/уменьшения еще
кое-какую работу - например, для параметра "Температура" есть два источника
данных - автоматическое измерение и ручной ввод. Автоматическое измерение
используется до тех пор, пока оператор не ввел руками другое значение, после
этого автоматическое измерение уже не используется. Вот там, если посмотреть,
есть специальный флажок, который устанавливается в функциях
TParamTemperature::Increase/TParamTemperature::Decrease, а при установленном
флажке автоматически измеренные данные уже не записываются в значение
параметра. У других параметров нет таких флажков, но могут быть свои внутренние
дела, которые, помимо всего прочего, и реализуются соответствующей функцией.

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

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

    И еще кстати - фрагменты кода (при том, что альтернативный вариант не
реализует трубуемую фукнциональность) по читабельности просто несопоставимы!

AB> Я не предлагаю реализовывать функциональность С++ на Си. Просто на Си
AB> принято по
AB> другому писать.

AB> Видел GTK+? это реализация С++ функциональности на Си.

    Зачем это, интересно, понадобилось добиваться этого.

AB> Жуткая штука.

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

AB> Hо работает.

    Кто бы сомневался? Но как насчет развития/сопровождения?


...so long!

### С умным человеком приятно поговорить, но трудно работать.



ICC AVR и стpоки
Harry Zhurov wrote to Alexey Boyko on Sun, 28 Sep 2003 06:00:59 +0000 (UTC):


HZ>     Но в любом случае С/С++ массив int A[n][m] ведет себя как:

HZ>         typedef int [m] SubArray;

    Пардон, тут замкнуло, правильно, конечно, так:

            typedef int SubArray[m];

HZ>         SubArray A[n];


...so long!

### Состав сводной команды: бульдозер, компрессор, автокран...



Re: ICC AVR и стpоки
Hello "Harry.

27 Sep 03 07:07, you wrote to me:

 HZ>     Сколько памяти нужно выделять? Если по твоей технологии,

Это не моя технология. Это так gcc работает.

 HZ> то нужно
 HZ> просмотреть всю функцию и выделить по максимуму: 16 + 1*4 + 32*2 = 84
 HZ> байта. В стеке. Hо если поток управления пойдет по первой ветке, то
 HZ> выделять память под буфер во второй не нужно, и память эта может
 HZ> оказаться очень не лишней при
 HZ> вызове функции из первой ветки, которая (функция) тоже прилично хавает
 HZ> стека. Если по второй ветке, то придется выделять по максимуму, но
 HZ> зато нет жручих функций. Таким образом, если выделять не все сразу, а
 HZ> смотреть по  ходу дела, то получается более эффективное расходование
 HZ> памяти, а если все сразу, то, соответственно, неэффективное.

Зависит от логики компилятора. gcc вроде бы выделяет по максимуму. Hо никто
не мешает ему выделять дополнительно кадр в каждом блоке.

 HZ>     Понял, понял, но не могу признать это лучшим,

Так делается в подявляющем большинстве процессоров и компиляторов.

 HZ> чем использование
 HZ> отдельного стека для данных, как это сделано в ИАРе.

В IARе память выделяется точно также, только с регистром Y

 AB>> Если компилировать с опцией -mno-interrupt, тогда при сохранении
 AB>> SP, нет шаманства с SREG, а просто
 HZ>     Зато можно получить по полной программе в случае возникновения
 HZ> прерывания во время изменения SP.

Естественно. Поэтому, обычно, компилируют без -mno-interrupt

 AB>> А был бы SP регистром, то вообще:
 HZ>     Будь он регистром, то просто обязан быть указателем.

Я бы не адресовался в кадр стека по SP, а все-таки по frame-pointer'у
так как это накладывает ограничения на на push/pop в самой функции

 AB>> А еще можно было убрать половину регистров, так как только
 AB>> половина из них нормальные, а остальные используются только как
 AB>> временное хранение.

 HZ>     А avr-gcc, вроде, позволяет заблокировать произвольное количество
 HZ> регистров от использования компилятором?

Можно. Hо от этого они указателями не станут. ;)

Alexey


ICC AVR и стpоки
Hello Vladimir.

23 Sep 03 20:49, Vladimir Vassilevsky wrote to Yuriy K:

 VV>>>  Хорошо работает, если один программист. Попробуй заставить всех так
 VV>>>  делать,
 YK>> Префикс переменной = имени файла.
 VV>  Ха. Мне уже приходилось приделывать к именам файла имена программистов:
 VV>  vlv_rs232_main.dsp :)

:)
http://telesys.ru/wwwboards/mcontrol/471/messages/232087.shtml

вообще это оpганизационные вопpосы, котоpые тpеб-ся в любой оpганизации с >1
pазpаботчиками.

 VV>>>  и чтоб еще не было конфликтов имен.
 YK>> Попробуй заставить всех программистов обзывать свои классы
 YK>> непересекающимися  именами.
 VV>  Можно принудительно ограничить области видимости. Hа то и ++.

naming conventions тpеб-ся везде.

Alexey


ICC AVR и стpоки
Yuriy K wrote to Harry Zhurov on Tue, 23 Sep 2003 17:24:31 +0400:

[...]

HZ>> Т.е. сделать именно то, что на ++ получается нативно.
HZ>> И после этого еще не считать ++ную модель лучшей, чем сишную!

YK> Стоп, стоп, стоп. Если мы хотим сравнивать С++ и С, то надо сравнивать
YK> _аналогичные_ подходы.

HZ>>     Hо и тут при таком подходе в С два недостатка.

HZ>>     Во-первых, при обращении к переменной, инкапсулированной в модуле
HZ>> (единице трансляции), придется либо делать ее открытой, либо вводить
HZ>> функцию доступа.

YK> Либо вводить макрос-псевдофункцию для доступа

    Вот именно, что псевдо!

YK> и эмулировать пространства имен префиксами.

    Не смеши!

YK> Пример:

YK> ---------------------------------------
YK> "rem.h"
YK> ---------------------------------------
YK> extern U8 rem_oops;
YK> #define rem_set_oops(val) (rem_oops = val)
YK> #define rem_get_oops()     rem_oops
YK> ---------------------------------------
YK> ---------------------------------------
YK> "rem.c"
YK> ---------------------------------------
YK> U8 rem_oops;
YK> ---------------------------------------
YK> ---------------------------------------
YK> "bla-bla-bla.c"
YK> ---------------------------------------
YK> if(!rem_get_oops() && is_it_good_time())
YK> {
YK>     rem_set_oops(OOPS_TIME);
YK> }
YK> ---------------------------------------
YK> Кстати, это будет эффективней чем С++.

    Не будет! Уверен, сам догадаешься, почему.

    А ты, видимо, макросы любишь?


HZ>> ++ предоставляет простой и логичный способ достичь защищенности
HZ>> без потери эффективности.

YK> Hе понял. Как это без потери эффективности?
YK> Для доступа к защищенной переменной на С++ придется использовать
YK> функцию - член класса.
YK> Для доступа к static переменной на С придется использовать функцию.

YK> Где потеря эффективнсти?

    А ты про inline функции что-нибудь слышал? Вот и подумай, есть разница
между вызовом функции и встраиванием тела функции в точку вызова. HINT:
встраиваемая функция ведет себя как макрос, только обеспечивает, в отличие от
последнего, контроль типов, области видимости и проч.


HZ>>     Во-вторых, и в-главных, такой подход красиво выглядит для таких
HZ>> достаточно больших и законченных модулей, как описанный UART, когда для
HZ>> него можно выделить отдельный файл. А что делать, когда модулей много и
HZ>> они не такие крупные и функционально законченные? Каждому отдельный файл?

YK> Да. Я именно так и делаю.

HZ>> Делал я так! Именно пытался растолкать модули по разным файлам, помещая в
HZ>> каждый не более двух-трех (в среднем). В итоге получил под дюжину
HZ>> исходных файлов и примерно столько же заголовков.
HZ>> Проект тогда был около
HZ>> 8 кбайт (прошивка). Впоследствии этот же проект развивался далее, и
HZ>> программа была переписана под ... Все удобно разместилось в трех файлах
HZ>> при размере (прошивки) около 12 кбайт.

YK> И всего-то дюжина файлов. :-)))
YK> 28 *.с + 5 *.asm + 38 заголовков для проекта на 16К кода. Hикаких проблем.
YK> IMHO это больше зависит от личных пристрастий программиста, не более того.
YK> Я, например, не могу сказать чей подход правильней.

    71 исходник!! На таком проекте!! Без комментариев!.. (Не знаю, как в
смайликах обозначается офигение)

    Поди еще и батником собираешь?

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

HZ>>     Таким образом, (возвращаясь к исходной точке обсуждения) на С можно
HZ>> пытаться проектировать программу в С++ном стиле только путем размножения
HZ>> исходных файлов, что тащит за собой неудобство в работе и оверхед.

YK> Извини, но я не вижу ни неудобства, ни оверхеда.

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


[...]

HZ>>     Поэтому реально, afaik, придерживаются компромисса - пытаются
HZ>> рассовать по файлам наиболее взаимосвязанное, стремясь минимизировать
HZ>> количество файлов.

YK> Hе надо минимизировать число файлов. Места в директории всем хватит. :)

    Любопытный критерий!

YK> Hадо названия давать осмысленные.

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

HZ>> Hо и того формализованного способа проектирования, который возможен в
HZ>> С++, тут уже нет! О чем и речь.

YK> Да, заставить программистов писать код правильно - непростая задача, увы.:(
YK> Возможно с применением классов это сделать проще, хотя и не факт

YK> P.S. Я ничего не имею против С++, хороший и полезный язык.
YK> Hо и каких-либо особенных преимуществ по сравнению с _хорошо_ написанной
YK> программой на С тоже не усматриваю.

    Сколько программ ты написал на С++? Аналогичных тем, которые до этого писал
на С? Ну, чтобы сравнивать/усматривать?


...so long!

### ""Хоть одним глазком взгляну на Париж..." - мечтал Кутузов."  (с) из
школьного сочинения.




ICC AVR и стpоки
Wed Sep 24 2003 18:34, Harry Zhurov wrote to Yuriy K:

 HZ>>>     Во-первых, при обращении к переменной, инкапсулированной в модуле
 HZ>>> (единице трансляции), придется либо делать ее открытой, либо вводить
 HZ>>> функцию доступа.

 YK>> Либо вводить макрос-псевдофункцию для доступа

 HZ>     Вот именно, что псевдо!

Да хоть горшком назови, лишь бы работало.

 YK>> и эмулировать пространства имен префиксами.

 HZ>     Hе смеши!

Убедительно. :)
Hа самом деле разумное применение static и префиксов в программе
помогает сделать ее сопровождаемой.

 YK>> Пример:
 YK>> extern U8 rem_oops;
 YK>> #define rem_set_oops(val) (rem_oops = val)
 YK>> #define rem_get_oops()     rem_oops
 YK>> Кстати, это будет эффективней чем С++.

 HZ>     Hе будет! Уверен, сам догадаешься, почему.

Да, inline поможет, убедил.

 HZ>     А ты, видимо, макросы любишь?

Hет. Просто иногда без них не обойтись.

 YK>> Hе понял. Как это без потери эффективности?
 YK>> Для доступа к защищенной переменной на С++ придется использовать
 YK>> функцию - член класса.
 YK>> Для доступа к static переменной на С придется использовать функцию.

 YK>> Где потеря эффективнсти?

 HZ>     А ты про inline функции что-нибудь слышал? Вот и подумай, есть
 HZ> разница между вызовом функции и встраиванием тела функции в точку вызова.
 HZ> HINT: встраиваемая функция ведет себя как макрос, только обеспечивает, в
 HZ> отличие от последнего, контроль типов, области видимости и проч.

Убедил, потери эффективности не будет. Выигрыша тоже. (inline vs. макрос).

Да, нет контроля типов и области видимости, это плохо, но совсем
не смертельно.

 HZ>>> В итоге получил под дюжину
 HZ>>> исходных файлов и примерно столько же заголовков.
 HZ>>> Проект тогда был около 8 кбайт (прошивка).

 YK>> И всего-то дюжина файлов. :-)))
 YK>> 28 *.с + 5 *.asm + 38 заголовков для проекта на 16К кода. Hикаких
 YK>> проблем.  IMHO это больше зависит от личных пристрастий программиста, не
 YK>> более того.  Я, например, не могу сказать чей подход правильней.

 HZ>     71 исходник!! Hа таком проекте!! Без комментариев!.. (Hе знаю, как в
 HZ> смайликах обозначается офигение)

Ж8-0, например :-) Hаверно и другие варианты есть.

 HZ>     Поди еще и батником собираешь?

IARской IDE. Впрочем можно было бы и батником, разница небольшая.
Как справедливо заметил Редчук, в промежутках между компилированием
и прошивкой полезно немного думать. :-Р Хотя обычно и лень...

 HZ>     И еще есть объективная причина: много мелких файлов плохо поддаются
 HZ> оптимизации, с которой компилятор хорошо справляется о. Особенно это
заметно при
 HZ> оптимизации по размеру.

Мне размера флэша за глаза хватает. Пока запас есть раза в три-четыре,
в новых контроллерах будет еще больше, т.к. надо переходить на новые MCU,
где флеша меньше 64К не бывает.

 HZ> И если уж тут проценты оверхеда плюсов вылавливают,

_Я_ не вылавливаю. Оверхед процентов в тридцать по скорости и два раза
по размеру _меня_ волнует слабо. Критичные куски можно и на асме написать.

Вопрос в точности высказываний.
Если сказано, что есть - надо доказать что есть.
Если сказано, что нет  - надо доказать что нет.


 HZ>>>     Таким образом, (возвращаясь к исходной точке обсуждения) на С можно
 HZ>>> пытаться проектировать программу в С++ном стиле только путем
 HZ>>> размножения  исходных файлов, что тащит за собой неудобство в работе и
 HZ>>> оверхед.

 YK>> Извини, но я не вижу ни неудобства, ни оверхеда.

 HZ>     Если 71 исходник на таком не очень большом проекте не вызывает
 HZ> неудобства, то комментарии излишни.

Еще раз. У _меня_ не вызывает. У кого-то может вызывать.
Это характеристика программиста, а не подхода.
Причем характеристика не "плохой-хороший", а просто "разный".

 HZ> А оверхед возникает из-за вызова
 HZ> интерфейсных функций - во-первых, на вызов и возврат, во-вторых, если
 HZ> есть аргументы, то и на копирование аргументов, хоть это проявляется не
 HZ> всегда. Т.ч. С тут пролетает.

#define тебе поможет.

 HZ>>>     Поэтому реально, afaik, придерживаются компромисса - пытаются
 HZ>>> рассовать по файлам наиболее взаимосвязанное, стремясь минимизировать
 HZ>>> количество файлов.

 YK>> Hе надо минимизировать число файлов. Места в директории всем хватит. :)

 HZ>     Любопытный критерий!

Дык!

 YK>> P.S. Я ничего не имею против С++, хороший и полезный язык.

Могу только повториться. Я считаю, что С++ лучше и удобнее С хотя бы потому,
что С++ включает в себя С, поэтому никак не может быть хуже.

 YK>> Hо и каких-либо особенных преимуществ по сравнению с _хорошо_ написанной
                      ^^^^^^^^^^^^^^^^^^^^^
 YK>> программой на С тоже не усматриваю.

 HZ>     Сколько программ ты написал на С++? Аналогичных тем, которые до этого
 HZ> писал на С? Hу, чтобы сравнивать/усматривать?

Hа микроконтроллеры - ни одной. Под РС - десяток-другой написал.

WBR, Юрий.


Re: ICC AVR и стpоки
22-Sep-03 12:31 Alexey Boyko wrote to Oleksandr Redchuk:

 OR>>>> void UartInit(void) __attribute__ ((section(".init3")))
 OR>>>> __attribute__ ((naked));
 HZ>>>     Т.е. нестандартные расширения?
 OR>>  Да, нестандартные.
 OR>> Hо одинаковые для avr-gcc, msp430-gcc, arm-gcc, ..... :-)

AB> Ты уверен?

AB> То есть __attribute__ ((section)) есть во всех,
 Я это и имел ввиду -- нестандартные расширения языка.

AB> а вот секции .init[0..9]
AB> есть только в avr-gcc, причем появились не так давно.
 А это касается запускалки.

AB> А arm-gcc вообщем-то сделан для arm-linux, а не для микроконтроллеров, и
AB> стартап, мне например, пришлось вообще свой писать.
 И если тебе захочется, ты в запускалке себе сделаешь
.init[0..9] и из C будешь распихивать инициализационный код
куда надо. Разве не так?

wbr,
--
/* Oleksandr Redchuk, Brovary, Ukraine */
/* real '\x40' real '\x2E' kiev '\x2E' ua     */


Re: ICC AVR и стpоки
23-Sep-03 13:14 Harry Zhurov wrote to Oleksandr Redchuk:

HZ>>> void uartInit(BYTE* Rx_buf,
HZ>>>               BYTE  Rx_size,
HZ>>>               BYTE* Tx_buf,
HZ>>>               BYTE  Tx_size,
HZ>>>               BYTE  Baud_rate);
OR>>  Я не понял - почему тут куча параметров, а у конструктора
OR>> ниже только baud rate? Значит, это _разные_ по поведению
OR>> системы, если там конструктор распределяет себе буфера по своему
OR>> усмотрению.

HZ>     По функциональности одинаковые. Просто в сишном варианте все сделано
 Нет. Разные. В С-шном варианте с самого "пользовательского"
уровня можно произвольно задать размещение и размер буферов,
а в C++ - ном эти вещи забиты где-то внутри реализации.


HZ> традициях С: работа с аппаратным UART'ом, кольцевые буфера, функциональность
HZ> протокола обмена пакетами и прочее "живет" отдельно, и весь модуль
HZ> представляет
HZ> собой конгломерат этих частей. В плюсатом варианте все эти детали
HZ> инкапсулированы внутри класса. Соответственно, на С вызывается функция,
 Точно так же инициализацию буферов фиксированного размера
можно сделать внутри С-шной функции и передавать ей только скорость.
Или у тебя конструктор через 4-е измерение догадывается,
гди и какого размера ты хотел сделать буфера. Нет? Фиксированные
распределяет? Ну тогда и C-шному разреши фиксированные
распределять.

HZ>>> BYTE UART_block_buf[BLOCK_BUFFER_SIZE];
OR>>  Опять - в "классовой" версии буфер из воздуха взялся?
OR>> Всё равно где-то кто-то его распределяет.

HZ>>> что нужно держать в голове) не выглядит "исчезающе малой"!!!
OR>>  Ну так не показывай наружу всё!
OR>>  На то и существует static в C, чтобы видимость имён ограничить
OR>> файлом, в котором они заданы.

HZ>     Все это так. И в данном случае, это, конечно, выход для С. И все это
HZ> (объявление внутренних программных элементов статическими) попытка
HZ> сделать по ++ному.
:-)))))))))))))))))))))))))))))
Ну извини, развеселил. Если в C объявление как static переменных и функций,
которые НЕ НУЖНО показывать наружу - это "попытка сделать по ++ному",
то тогда мне только остаётся сказать, что в C++ то, что
по умолчанию все члены класса - закрытые, это попытка
сделать по-ассемблерному, так как там если не сказано по поводу
метки public, то она невидима за пределами файла.

HZ> Т.е. сделать именно то, что на ++ получается нативно. И после
HZ> этого еще не считать ++ную модель лучшей, чем сишную!
 И необходимость писать в классах слова private - это
то, что на ассемблере получается нативно.

HZ>     Таким образом, (возвращаясь к исходной точке обсуждения) на С можно
HZ> пытаться проектировать программу в С++ном стиле только путем размножения
HZ> исходных файлов, что тащит за собой неудобство в работе и оверхед. Если
 Это не есть "попытка проектировать в C++ном стиле".

OR>>  Да нет, если стековый кадр нужен, то в прологе порождается
OR>> frame pointer на Y и дальше всё "как обычно". Если стековый кадр не
OR>> нужен, то Y используется как хочется.

HZ>     А как тогда быть с прерываниями? Т.е. вот вошли в функцию, скопировали
HZ> SP в
HZ> Y, начали использовать Y, и тут - бац! - прерывание! Какой поинтер будет
HZ> использоваться в прерывании?
 Если прерыванию надо, то оно себе сделает, если не надо - делать не
будет. Не понимаю, в чём проблемы, что тебе непонятно.
Это аналогично push bp / mov bp,sp / sub sp,8 на 80x86, вместо
bp идёт Y, sp как sp.

HZ>>> остальной части абзаца комментарий следующий:
HZ>>>     В энный раз повторяю: все зависит от конкретных условий!!!
OR>>  О чём и разговор - в огромном количестве "конкретных условий"
OR>> за C++ могут быть только два аргумента - "не сбивать руку"
OR>> и "очень уж эта мысля понравилась". Остальные расписания "плюсов плюсов"
OR>> как-то мало в тех "конкретных условиях" дают.

HZ>     Кому как... Но поскольку все уже высказались, то и... закончим,
HZ> пожалуй?!
 Фф-ф-у-у-ухххх :-)

HZ>>> передаче более двух, то это уже повод задуматься о том, нет ли ошибки
HZ>>> проектирования;
OR>>  memcpy(dst, src, len);

HZ>     Весьма нечастая низкоуровневая библиотечная функция. Количество ее
 EEwrite(  offset, *pbuf, len); // EEread, EEverify
 RTCwrite( offset, *pbuf, len); // read, vеrify
 SendPacket(type, *pdata, len);
 DisplayInt(position, value, digits); // это у меня для 7-сегментника
 CompareDates( struct date *da, struct date *db, u08 len);
   (сравнение дат на раньше/равно/позже, len - это глубина сравнения --
   год, год и месяц, .... до секунд включительно, _одним_ operator< эту
   функцию не заменить).
 fseek(*stream, offset, whence)
 fwrite(*ptr, itemsize, items, *stream), в конце концов.


HZ> неприемлемо для низкоуровневого кода). При прочих равных ей лучше
HZ> предпочесть
HZ> нечто более высокоуровневое и безопасное вроде операторов присваивания
 Угу. Остаётся только забабахать
 EEstream << pos(offset) << record;
и для каждого типа записей в EEPROM написать отдельный operator<<
Спасибочки.

HZ>>> если больше трех, то это причина задуматься о том же;
OR>>  AT45D_write( chip_no, offset, buf, len);

HZ>     Да, а у меня:

HZ>     TDataFlash::ReadBuffer(word addr, byte N);
HZ>     TDataFlash::ReadMemory(word PageAddr, word ByteAddr);
 Ты тут сделал как бы с двумя аргументами, но либо это синглет
для работы с одним чипом (и эти функции могут быть даже статические),
либо (я-то говорил про несколько чипов!) на каждый чип надо заводить
экземпляр класса и chip1.ReadBuffer() и один из аргументов функции
таки приписан слева.

HZ>     А если два чипа, то и тем более классы рулят! :)  Заводишь два
HZ> объекта, при
 И вместо того, чтобы передать в функцию доступа индекс чипа (один байт)
и не заводить никаких переменных в ОЗУ -- передавать в функцию
доступа указатель (this. не ты, не ты. компилятор. но код всё равно есть)
на объект в ОЗУ, который там надо ещё завести.

HZ>     Блин, я с этой дискуссией никак не могу толком взяться за изучение
HZ> gcc (известно для чего ;-))
 :-)))
 Мне тоже есть что делать, кстати :-)

wbr,

--
/* Oleksandr Redchuk, Brovary, Ukraine */
/* real '\x40' real '\x2E' kiev '\x2E' ua     */


ICC AVR и стpоки
Sep 2003 14:52:16 +0000 (UTC):

[...]

HZ>> Т.е. сделать именно то, что на ++ получается нативно. И после
HZ>> этого еще не считать ++ную модель лучшей, чем сишную!
OR>  И необходимость писать в классах слова private - это
OR> то, что на ассемблере получается нативно.

    В классах писать private не надо - объявляешь приватное сразу, потом пишешь
public для открытого и вуаля. :)  Т.ч. все нативно. :))

[...]

HZ>>     А как тогда быть с прерываниями? Т.е. вот вошли в функцию, скопировали
HZ>> SP в
HZ>> Y, начали использовать Y, и тут - бац! - прерывание! Какой поинтер будет
HZ>> использоваться в прерывании?
OR>  Если прерыванию надо, то оно себе сделает, если не надо - делать не
OR> будет. Не понимаю, в чём проблемы, что тебе непонятно.

    Мне не понятно вот что: зашли в функцию, скопировали SP в Y, начали с ним
работать - разместили в этой памяти локальные объекты, Y, ессно,
модифицировался - TOS "уплыл" от исходного значения SP на величину размера
локальных объектов + место под адрес возврата на случай прерывания/вызов
функции. Теперь возникает прерывание, на входе снова берется SP и копируется в
Y, и по той же схеме используется память стека. Но это та же самая память,
которая уже используется в прерванной функции!? Вот если использовать для
прерываний отдельный стек, то тогда, вроде, должно получиться.

[...]

HZ>> неприемлемо для низкоуровневого кода). При прочих равных ей лучше
HZ>> предпочесть
HZ>> нечто более высокоуровневое и безопасное вроде операторов присваивания
OR>  Угу. Остаётся только забабахать
OR>  EEstream << pos(offset) << record;
OR> и для каждого типа записей в EEPROM написать отдельный operator<<

    Зачем же так извращаться? :) У тебя же не этот убогий ЕС++, а нормальный
С++ - один раз пишешь шаблон, и для любого нужного типа инстанцируешь объект.
:))

OR> Спасибочки.

    Welcome! :)))


...so long!

### Этот газ вызывает головные боли в мышцах и костях.



Re: ICC AVR и стpоки
24-Sep-03 17:59 Harry Zhurov wrote to Oleksandr Redchuk:

HZ>>> SP в
HZ>>> Y, начали использовать Y, и тут - бац! - прерывание! Какой поинтер будет
HZ>>> использоваться в прерывании?
OR>>  Если прерыванию надо, то оно себе сделает, если не надо - делать не
OR>> будет. Не понимаю, в чём проблемы, что тебе непонятно.

HZ>     Мне не понятно вот что: зашли в функцию, скопировали SP в Y,
 вычли из SP размер локальных переменных
HZ> начали с ним работать -

HZ> функции. Теперь возникает прерывание, на входе снова берется SP и
 Уже модифицированное или, если не модифицированное (не успели), то
и переменные в той области ещё не размещены.

HZ> Y, и по той же схеме используется память стека. Но это та же самая
HZ> память, которая уже используется в прерванной функции!?
 Ты что, ещё не разбирался как это сделано у MSP с одним стеком?
Ну и 80x86-ое (16-битного режима)
  push BP
  mov  BP,SP
  sub  SP,8 ; скажем, 8 байт локальных переменных
я уже писал как пример

HZ> Вот если использовать
HZ> для прерываний отдельный стек, то тогда, вроде, должно получиться.
 Два стека (данных и управления) -- мысль довольно неплохая.
Но, с другой стороны, требующая более аккуратного распределения
памяти -- каждому стеку надо дать, и каждому чтобы хватило.
С третьей - неужели нет gcc для sparc? А у него, если я правильно помню,
сразу по жизни два указателя стека.

wbr,
--
/* Oleksandr Redchuk, Brovary, Ukraine */
/* real '\x40' real '\x2E' kiev '\x2E' ua     */


ICC AVR и стpоки
Sep 2003 05:11:46 +0000 (UTC):

OR>>> Не понимаю, в чём проблемы, что тебе непонятно.

HZ>>     Мне не понятно вот что: зашли в функцию, скопировали SP в Y,
OR>  вычли из SP размер локальных переменных

    Все это в критической секции?

HZ>> начали с ним работать -

    sbiw r28:r29,... ; выделили память под несколько переменных

    st -Y,...        ; тут сунули в стек еще переменную
    ...

    st -Y,...        ; тут еще ...
    ...

    st -Y,...        ; и тут ...

    Это что, после каждого такого обращения SP модифицировать? Т.е. оба
указателя модифицировать синхронно? Да еще и придется в критическую секцию
заключать любое такое изменение, дабы атомарность не потерять? Но тогда какой
смысл в этом Y в качестве указателя стека, когда такой оверхед? Или сразу
выделять по максимуму, сколько в функции нужно? И не пользоваться st -Y,..., а
вместо нее std Y+n,...? Наверное, это вариант. Но все равно нехорошо. Дураций
там SP!

[...]

HZ>> Y, и по той же схеме используется память стека. Но это та же самая
HZ>> память, которая уже используется в прерванной функции!?
OR>  Ты что, ещё не разбирался как это сделано у MSP с одним стеком?

    Причем тут 430-й? У него SP нормально сделан, он позволяет адресоваться
любым штатным способом и косвенно, и со смещением, и адресная арифметика там
работает, поэтому нет необходимости его значение куда-то копировать. Вот если
бы в том же AVR Y-pointer был бы одновременно и SP (т.е. был бы способен
участвовать в процессе запоминания адресов возвратов из функций и прерываний),
то всего этого геморроя не было бы. Правда тогда там осталось бы полтора
указателя.

[...]

HZ>> Вот если использовать
HZ>> для прерываний отдельный стек, то тогда, вроде, должно получиться.
OR>  Два стека (данных и управления) -- мысль довольно неплохая.

    А это в ОС используется - там зачастую удачным является решение, когда для
прерываний свой стек. И тут бы это могло решить проблему со стековым кадром.

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

    Так ведь у ИАРов два стека, правда они не такие, но тоже нужно за этим
следить.


...so long!

### Когда мало времени, тут уже не до дружбы - только любовь.



Re: ICC AVR и стpоки
25-Sep-03 16:22 Harry Zhurov wrote to Oleksandr Redchuk:

HZ>>>     Мне не понятно вот что: зашли в функцию, скопировали SP в Y,
OR>>  вычли из SP размер локальных переменных

HZ>     Все это в критической секции?

HZ>>> начали с ним работать -

HZ>     sbiw r28:r29,... ; выделили память под несколько переменных

HZ>     st -Y,...        ; тут сунули в стек еще переменную

 Слушай, а как это сделано у IAR/MSP430 ? Неужели тоже два стека и регистр
под второй указатель занят?

Напоминаю ещё раз как это сделано у x86/16 (оно короче и проще объяснить)
SP - указатель стека, с которым можно кое-что сделать, но адресоваться
по нему нельзя. BP - указательный регистр, который по умолчанию работает
в сегменте стека и по нему удобно обращаться к стековому кадру
   push bp
   mov  bp,sp
   sub  sp,size of locals ; резервируем место
Теперь sp не трогаем, обработчики прерываний в стек могут спокойно
писать. Адресация относительно bp вверх - аргументы функций,
вниз - локальные переменные.

Для MSP430 это должно выглядеть как
   sub sp,size of locals
и вся адресация относительно SP в плюс.

Для AVR и адресоваться отрицательным смещением неудобно, и относительно
SP нельзя (что нельзя и в x86/16, но выходит не так больлно).
Итого:


/* prologue: frame size=6 */
        push r16  ; это сохраняются те, кого надо сохранить
        push r17  ; к делу отношения не имеет
        push r28
        push r29

        in r28,__SP_L__
        in r29,__SP_H__
        sbiw r28,6
        in __tmp_reg__,__SREG__     ; *
        cli                         ; *
        out __SP_H__,r29
        out __SREG__,__tmp_reg__    ; *
        out __SP_L__,r28

После этого дела Y указывает на стековый кадр (как BP у x86/16,
только Y указывает не на серёдку стекового кадра, а на низ).
'*' отмечены команды, которых могло бы не быть, если бы
out SPH,reg запрещала на такт прерывания.



HZ>     ...

HZ> заключать любое такое изменение, дабы атомарность не потерять? Но тогда
HZ> какой смысл в этом Y в качестве указателя стека, когда такой оверхед?
 Y не указатель стека, а указатель кадра.

HZ> Или сразу выделять по максимуму, сколько в функции нужно?
 Ну да. И у PDP11 так было, и, думаю, IAR/MSP430 так делает.

HZ>     Причем тут 430-й? У него SP нормально сделан, он позволяет адресоваться
 А притом, что место под локальные переменные и на нём резервировать
надо. Т.е. его надо модифицировать. В силу 16-разрядности процессора
такая модификация атомарна автоматически, но она есть.
Возможно, из-за атомарности ты её и не заметил.

HZ> любым штатным способом и косвенно, и со смещением, и адресная арифметика
HZ> там
HZ> работает, поэтому нет необходимости его значение куда-то копировать. Вот
 Вопрос не только копирования, но и модификации. Место под locals
зарезервировать надо и для него. Просто у него
 STACK_POINTER := STACK_POINTER - SIZE_OF_LOCALS
делается очень просто.
Отсутствие адресации по указателю стека тоже не есть нечто уникальное
AVR-ское, это не очень приятно, но решаемо. Но вот у AVR это усугублено
элементарными "недодумками" в других местах.
IAR обошёлся тем, что для данных завёл второй стек, который
обслуживется отдельно и на котром легко реализуется резервирование места.

OR>>  Два стека (данных и управления) -- мысль довольно неплохая.

HZ>     А это в ОС используется - там зачастую удачным является решение,
HZ> когда для прерываний свой стек.
 Какой он "свой"? Тут два стека - возвратов и данных.
Прерывание работает в стеке управления основной программы,
как минимум вход в него. Только потом оно может переключить
указатель стека на системную область и дальше работать там.

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


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

HZ>     Так ведь у ИАРов два стека, правда они не такие, но тоже нужно за
HZ> этим следить.
 О чём и говорю. В одной задачке на 4433 пришлось в код добавлять
проверку уровня загаженности стеков и перераспределять место
между RSTACK и CSTACK

wbr,
--
/* Oleksandr Redchuk, Brovary, Ukraine */
/* real '\x40' real '\x2E' kiev '\x2E' ua     */


Site Timeline