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

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

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

OR>> INTERNATIONAL STANDARD ISO/IEC         ISO/IEC 9899:1999
OR>>                  Programming languages - C

OR>> inline иметь положено. Уже 3 года как.

HZ>     IAR C - последняя версия, afaik, 1.51, вышла где-то в 99 году. И
HZ> много ты знаешь компиляторов, удовлетворяющих C99?
gcc:
  -std=<std name>           Specify the conformance standard; one of:
                            gnu89, gnu99, c89, c99, iso9899:1990,
                            iso9899:199409, iso9899:1999, c++98

Впрочем, полноту соответствия не знаю. Но не думаю, что с inline
будут проблемы :-)

А "и много ты знаешь" -- не оправдание. Оно позволяет всем вместе
хором ничего не делать, только скандировать "и много ты знаешь".
Так что видать IAR просто решил забить вообще на линейку C-компиляторов,
сделав упор на EC++.

HZ> Там, кстати, если и более
HZ> существенные вещи - локальные динамические массивы. Какие компиляторы
HZ> уже поддерживают это?
 gcc. Весь выводок. Кажется, с версии 3.0

int foo(unsigned char uu, unsigned char *puu) {
  unsigned char moo[uu];
  unsigned char t;
  moo[uu/2] = *puu;
  return moo[uu/2];
}

mingw32 3.2 (20020817) компилирует с вызовом _alloca
avr-gcc 3.3 (20030421) ручками резервирует место на стеке и всё делает.
Впрочем, пихать это в AVR (кроме, разве что, меги128 с внешней SRAM),
равно как и использовать там malloc или new - боюсь, не самое оно.
Да и на меге с внешней памятью - разве что реализацию malloc
с разными пулами для объектов разных размеров (может, тогда лучше
сразу нормальный язык со сборкой мусора туда, а не C/C++ :-)

wbr,
p.s. Э! Может лучше завяжем с этим, у тебя появится время на разборки
с gcc ты знаешь для чего, и у меня время появится на разборки
с ты знаешь чем для gcc :-))
--
/* Oleksandr Redchuk, Brovary, Ukraine */
/* real '\x40' real '\x2E' kiev '\x2E' ua     */


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

23 Sep 03 11:22, you wrote to "Harry Zhurov":

 HZ>>        main:
 HZ>> 9100....                   LDS     R16,(slon + 2)
 HZ>> 2300                       TST     R16
 HZ>> F031                       BREQ    ??main_0
 OR> В C-шном варианте это выглядело бы как
 OR>       rcall SlonIsTrue
 OR>       tst r16
 OR>       breq
 OR> либо call для мега16 и выше. Т.е. inline не короче.
 OR> А если там проверка битового флага в поле, то инлайновый вариант
 OR> ещё толще будет.

А если подумать?

Если это просто проверка байта, то уже есть смысл перейти на инлайн,
так как он хоть и столько же занимает, но работает быстрее.

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

Можно, конечно, попробовать сделать функцию просто static, и проверить
будет ли компилятор смотреть, какие регистры портит вызываемая функция.


Alexey


Re: ICC AVR и стpоки
23-Sep-03 14:26 Alexey Boyko wrote to Oleksandr Redchuk:

 HZ>>> 9100....                   LDS     R16,(slon + 2)
 HZ>>> 2300                       TST     R16
 HZ>>> F031                       BREQ    ??main_0
 OR>> В C-шном варианте это выглядело бы как
 OR>>       rcall SlonIsTrue
 OR>>       tst r16
 OR>>       breq
 OR>> либо call для мега16 и выше. Т.е. inline не короче.
 OR>> А если там проверка битового флага в поле, то инлайновый вариант
 OR>> ещё толще будет.

AB> А если подумать?
[...]
AB> А во вторых, ты не учел тот факт, что вызов функции сразу же делает
AB> невалидными половину регистров, в которых могло быть что-то полезное
AB> и потребует повторную загрузку.
 Ой, ну да, это я сильно привык к KeilC51 global register
optimisation :-) В этих условиях привычные #define (вместо inline)
оказалось в очень многих случаях выгодно заменить на подпрограммы,
возвращающие результат проверки в carry (кстати, было бы весьма неплохо
и для AVR - в C или в T возвращать bit_bool :-).
Так что в данном случае надо уточнять "по месту".

AB> Можно, конечно, попробовать сделать функцию просто static, и проверить
AB> будет ли компилятор смотреть, какие регистры портит вызываемая функция.
 Кажется, пока не умеет. Да, точно не умеет - в одном месте
два уарта (аппаратный и софтовый) вызывают из обработчиков
прерываний подпрограммы заталкивания байта в буфер (с раскруткой SLIP)
и взятия следующего байта бля передачи (с подстановкой SLIP).
Подпрограммы объявлены выше обработчиков как static и сам больше
никого не вызывают. Обработчики делают push/pop всем регистрам,
которые имеет право испортить "обычная" подпрограмма, хотя на самом
деле там и половины их не испорчено.

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


Re: ICC AVR и стpоки
21-Sep-03 00:40 Harry Zhurov wrote to Oleksandr Redchuk:

HZ>>>     Это почему же? Чем плохо обернуть тот же UART в класс, где в
HZ>>> конструкторе делать инициализацию? Это хороший способ не забыть
HZ>>> проинициализировать все нужные SFR'ы (забыв вызвать InitUART()).

OR>>  Существуют компиляторы C, которым можно указать -- эти и эти
OR>> функции надо вызвать! У BorlandC это #pragma startup, у gcc это

OR>> void UartInit(void) __attribute__ ((section(".init3")))
OR>> __attribute__ ((naked));

HZ>     Т.е. нестандартные расширения?
 Да, нестандартные.
Но одинаковые для avr-gcc, msp430-gcc, arm-gcc, ..... :-)
Одна из приятностей C++ -- это возможность сделать стандартизованным
образом то, что иначе можно только на расширениях языка.
В мелко/средне-однокристалочных задачах, imho, эта приятность
сильно маскируется тем, что и так много нестандартных расширений,
связанных со спецификой кристаллов.


HZ>  Hу, т.е. ведет себя как конструктор глобального объекта!?
 Ну да. Как и #pragma startup и #pragma exit в BorlandC - выполнение
указанных функций до/после main с указанным в #pragma приоритетом.

HZ> В ИАРе,
HZ> кстати, тоже никаких прологов/эпилогов нет, там механизм такой: есть
специальный

[...]
HZ> цепочки конструкторов. Т.е. получается, что адресов и вызовов получается
HZ> не более, чем единиц трансляции в проекте.
 Ну да, по сути IAR собирает в пределах единицы трансляции так,
как gcc собирает в секции init со всего проекта. Перерасход
по сравнению с gcc
<число единиц трансляции>*<размер адреса+размер ret>+код для просмотра
таблиц.
 Но у avr-gcc свои внутренние инициализации распиханы по
.init0 сразу после сброса
.init2 установка стека
.init4 инициализация data и очистка bss
.init6 констуркторы для C++
.init9 вызов main
и я могу затолкать в init1 установку режима работы с внешней памятью у
mega128, в init5 всё то, что хотелось бы иметь до инициализации
объектов (если писать на плюсах) и т.п.
секции .fini отрабатывают в обратном порядке, но я слабо понимаю
их смысл для "глубоко встроенных" приложений. Разве что
в .fini5 закрыть все внешние устройтсва а в .fini1 стимулировать
сброс по WDT.

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


ICC AVR и стpоки
Dimmy Timchenko wrote to Boris Popov on Sat, 20 Sep 2003 07:52:55 +0400:

DT> 19 Sep 2003, 16:58, Boris Popov writes to Harry Zhurov:

BP>> Код на С++ действительно выглядит красиво.  Теперь забудем
BP>> прописать __flash в объявлении boom[]: компилятор C++ с грациозным
BP>> спокойствием выберет другую функцию из числа перегруженных,

DT> Вот тут-то и пригодилась бы строгая типизация, вроде Адской. :)  Впрочем,
DT> не только тут.

    А не покажешь на примере Ады как тут оно разрешится без ошибки?


...so long!

### "Крыша" есть - ума не надо.



ICC AVR и стpоки
Hi Harry.

17 Sep 2003, 20:25, Harry Zhurov  writes to Dimmy Timchenko:

 DT> Классы - слишком тяжеловесный механизм и нужны далеко не везде.

 HZ> Что там тяжеловесного?

Да сама парадигма.  Hе знаю, может, это личные особенности восприятия, но для
меня читаемость и понимаемость "объектного" кода на порядок ниже, чем
"структурного".  Слишком высокая связность.  Если структурный код легко
разбивается на отдельные функции и модули, если я могу выхватить для своих нужд
одну функцию из библиотеки и больше ни о чём не думать, то в случае классов
надо держать в голове всю иерархию.

 HZ> Более того, никто не заставляет использовать использовать классы
 HZ> вообще, и этого не следует делать где попало.

Именно!  Классы хороши там, где сама структура моделируемого "мира" близка к
объектной.  МК в большинстве применений - не тот случай.  А инкапсуляция на
уровне модулей совершенно естественно вписывается в структурную парадигму,
которая, опять же, практически универсальна.

 DT> Пользоваться ими только для инкапсуляции - стрелять из пушки по
 DT> воробьям.

 HZ> Это почему же? Что, оверхед что-ли появляется? Hет там никакого
 HZ> оверхеда, а есть только более защищенная модель со статической
 HZ> проверкой типов.

Для чего совершенно не нужны классы. :)

Вот в Аде всё ООП делается на уровне _типа_.  Для динамического полиморфизма
просто был введён атрибут tagged.

 HZ> И инкапсуляция, кстати, очень важная и полезная вещь, т.ч. и
 HZ> она - не "воробьи". :)

Безусловно.  Поэтому я хочу иметь её в чистом виде, без линкора классов. :)
Элементарное средство - модуль...

 DT> Да и стиль объектный от структурно-модульного значительно
 DT> отличается: при
 DT> совмещении получается эклектика,

 HZ> С++ - язык гибридный, он поддерживает несколько парадигм,
 HZ> которые вполне органично дополняют друг друга (не понимаю, где ты
 HZ> там эклектизм углядел?)

Да посмотри на любой исходник C++ с интенсивным использованием классов: понять
ничего невозможно.

 DT>  да и для МК, опять же, это не особо полезно.

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

Hу и какие задачи, решаемые встроенными системами, скажем так, "существенно
объектны"?  ООП хорошо для всякого рода гуёв и для моделирования и симуляции
сложных систем - для чего ещё, с ходу не скажу.  А для фирмвари мобильника,
микроволновки, АТС, топливораздаточной колонки, кассового аппарата и так далее
- совершенно неаутентично.

 HZ> Имею некоторый опыт - то, что ранее на С приходилось делать с
 HZ> помощью тупых проверок на switch'ах или с помощью массивов
 HZ> указателей на функции, сейчас реализуется с помощью иерархий
 HZ> классов с виртуальными функциями.

Может, в отдельных случаях и удобнее, но тянет за собой эклектику.  Мне как-то
и проверки "на switch-ах" не жмут. :)  Если, скажем, протокол описывается
таблицей или конечным автоматом, то и реализовывать его удобно в похожем на
описание виде.

 DT> А без модулей - неудобно: все эти h-файлы синхронизировать,

 HZ> А что означает "h-файлы синхронизировать"?

Поддерживать соответствие изменениям в C-файле.

 HZ> И как в Аде интерфейс модуля экспортируется в другую единицу
 HZ> трансляции?

С помощью так называемых пакетов (packages).  Пишется:

package BlaBla is

... -- здесь все определения и описания

end BlaBla;


package body BlaBla is

... -- здесь тела всех процедур и функций

begin

... -- опционально - секция инициализации

end BlaBla;



А потом, при использовании в другом модуле, пишем:

with BlaBla;
use  BlaBla; -- опционально, чтобы не писать BlaBla.<имя-объекта>

и работаем с любыми программными объектами, описанными в интерфейсной секции
пакета.


 DT>  да и проверки лишние не помешали бы.

 HZ>  Которые нельзя отключить?

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

 HZ> Возвращаясь к исходному вопросу: что дает модуль, чего бы
 HZ> нельзя было выразить с помощью класса?

Для меня вопрос ставится иначе: как можно добиться нужного мне результата
максимально простым, надёжным, понятным, "читаемым" способом.  Ортогональность
семантики.  Hужна инкапсуляция - использую средство именно для инкапсуляции -
тип, модуль, процедуру.

 HZ> И чем реализация с помощью класса уступает реализации с помощью
 HZ> модуля? Пример можно привести? Хоть на Аде, хоть псевдокод.

Это ж целые программы надо приводить. :)  Могу мылом прислать исходники
библиотек GNUсного компилятора Ады - GNAT.


Dimmy.


Re: ICC AVR и стpоки
Wed Sep 17 2003 01:21, Vladimir Chekin wrote to Vadim Vysotskiy:

 VC>                      Привет, Vadim!

 VC> 15 Sep 03 20:18, Vadim Vysotskiy >>> Nikolai Golovchenko
 VC> по теме "Re: ICC AVR и стpоки"

 NG>>> Потом в пpоцессе линкования объектных файлов адpес той стpоки
 NG>>> подставится всем модулям, котоpые использовали extern.

 NG>>> Пpинципиальной pазницы между .h и .c файлами нет, pазве что .h файл
 NG>>> может быть включен в дpугие модули несколько pаз. Тогда в .h файле
 NG>>> необходимо использовать extern, а саму пеpеменную опpеделить в
 NG>>> каком-нибудь .c файле.

 VV>> Так и делаю: опpеделяю стpоку в .с файле в .h файле этого же .с
 VV>> (пpавильно ?) использую extern. Пишет о повтоpном опpеделении
 VV>> пеpеменной.  Поэтому и возник вопpос.

 VC> Чтоб не заморачиваться с вписыванием в каждый другой модуль строк
 VC>      extern ляляля;
 VC> тем более иногда это не одна переменная из какого-то мудуля, я делаю так:

 VC> - в модуле где определена переменная, например lcd.c, в заголовке пишу
 VC> #define _LCD
 VC> #include "lcd.h"

 VC> uchar   lcd_byte;
 VC> //==================
 VC>  Функции

 VC> //==================

 VC> - а в егойном хидере lcd.h
 VC> //==================
 VC> всякие #define
 VC> //==================
 VC> #ifndef _LCD
 VC>   extern   uchar   lcd_byte;
 VC> #endif

 VC> - во все другие с-модули, где требуется переменная lcd_byte я включаю
 VC> строку
 VC>   #include "lcd.h"

 VC> Мне это намного проще, чем вписывать персонально каждую внешнюю
 VC> переменную.

 VC> При компиляции модуля lcd.с участок кода, обрамлённый конструкцией
 VC> #ifndef  _LCD, не будет включен, т.к. условие не выполняется по причине
 VC> наличия  #define _LCD в самой первой строке модуля. И нет
 VC> переопределения.

 VC> А при компиляции всех других модулей этот участок кода будет включен,
 VC> обеспечивая объявление внешней переменной lcd_byte.

То есть занимаешься совершенно лишней и ненужной работой.

Вот этого:

 VC> - в модуле где определена переменная, например lcd.c, в заголовке пишу
 VC> uchar   lcd_byte;

 VC> - а в егойном хидере lcd.h
 VC>   extern   uchar   lcd_byte;

Должно быть совершенно достаточно для нормального С-компилятора.

WBR, Юрий.


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

Среда Сентябрь 17 2003 00:21, you wrote to Vadim Vysotskiy:

 VC> Чтоб не заморачиваться с вписыванием в каждый другой модуль строк
 VC>      extern ляляля;
 VC> тем более иногда это не одна переменная из какого-то мудуля, я делаю
 VC> так:

 VC> - в модуле где определена переменная, например lcd.c, в заголовке пишу
 VC> #define _LCD
 VC> #include "lcd.h"

 [skip ]

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

 extern uchar var; // это из .h файла
 uchar var;        // это из .с файла

без ошибок.

Leha


Re^2: ICC AVR и стpоки
Здраствуйте Vadim,

*15.09.03* *20:18:19* Вы писали в *RU.EMBEDDED*
сообщение к *Nikolai Golovchenko*
о *"Re: ICC AVR и стpоки"*.

 VV> Так и делаю: опpеделяю стpоку в .с файле в .h файле этого же .с
 VV> (пpавильно ?) использую extern. Пишет о повтоpном опpеделении пеpеменной.
 VV> Поэтому и возник вопpос.

По отношению к .h-файлу *этого же* .c-файла имя сторки уже определено
*не как* extern. Поэтому extern'ы лучше вставить во все .c-файлы,
кроме того, в котором строка определена (можно через #include "header.h", но
тогда этот #include нельзя писать в файле с определением строки).

С уважением, Den


Re^2: ICC AVR и стpоки
Wed Sep 17 2003 08:20, Den Y. Borisov wrote to Vadim Vysotskiy:

 DYB> Здраствуйте Vadim,

 DYB> *15.09.03* *20:18:19* Вы писали в *RU.EMBEDDED*
 DYB> сообщение к *Nikolai Golovchenko*
 DYB> о *"Re: ICC AVR и стpоки"*.

 VV>> Так и делаю: опpеделяю стpоку в .с файле в .h файле этого же .с
 VV>> (пpавильно ?) использую extern. Пишет о повтоpном опpеделении
 VV>> пеpеменной.  Поэтому и возник вопpос.

 DYB> По отношению к .h-файлу *этого же* .c-файла имя сторки уже определено
 DYB> *не как* extern.

Hеважно.

 DYB> Поэтому extern'ы лучше вставить во все .c-файлы,

Hет.

 DYB> кроме того, в котором строка определена (можно через #include
 DYB> "header.h", но тогда этот #include нельзя писать в файле с определением
 DYB> строки).

Можно и нужно.

WBR, Юрий.


Site Timeline