Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: Хочу попробовать ARM, подскажите, что для этого нужно?
Форум разработчиков электроники ELECTRONIX.ru > Сайт и форум > В помощь начинающему > ARM, 32bit
Страницы: 1, 2, 3, 4, 5, 6
Alex_inventor
Добавлю ещё пару строк о PROTEUS. Прошивки можно загонять как в .hex так и в объектном виде. Во втором случае можно по-шагоао ходить по С программе делать точки остановки. Причём в любой момент можно посмотреть внутреннее состояние любого программного элемента. Это всякая там память, а в контроллеры вообще на изнанку вывернуть. На тебе и память и периферия, и РОН и что хочешь. По инету ходят слухи, что скоро выйдет 10 версия. То там наверное вообще можно тушить свет, и блаженствовать. Кстати если очень хочется какой-нибудь элемент, а его нет в библиотеке, то есть возможность сделать его самому. Макро блоки вообще проще пареной репы, напихал уже готовых элементов, соединил по нужному, сделал выводы, нажал кнопочку. Инна тебе микросхема суррогатного производства. Да много элементов нет, но практически у каждого есть двойник. Эту среду не надо использовать как точную копию действительности, как некоторые делают и разочаровываются. В ней надо испытывать общие алгоритмы, принципы, куски прошивок, частей схем, как аналогового вида так и цифрового. А затем всё долизать в железе, причём 90% работы уже сделана.
Abakt
Цитата(Alex_inventor @ Jan 28 2007, 05:16) *
А у тебя proteus есть? Ты им когда-нибудь пользовался? Если нет, то не видел счастья в жизни!!! Хотя я тебя не виню, если это так. Сам случайно начал им пользоваться.


я тоже случайно наткнулся на - [skipped] - скачал 6.9 sp 5 и очень полюбил эту штуку.
Andy Great
Цитата(Alex_inventor @ Jan 27 2007, 16:48) *
2Andy Great
Компилятор я качал с keil.com. Он лежит на одной странице, где и сам uVision. Файл является установщиком (gccARM331.exe). Я ничего не настраивал, он сам установил себя в папку с:\ Cygnus и ещё некоторые манипуляции с реестром, по-моему, проделал. На диске есть готовые проекты. В каждом проекте в настройках указан GCC. Так вот, если я нажимаю компиляцию, то выскакивает ошибка. Проекты необходимы только для использования при прочтении книги, и всё! В чём причина разбирается, не хочу (осваиваю RealViwe). Повторяюсь, это не отдельные файлы, а целые проекты, с настройками компилятора и т.д. По этому всё сразу должно заработать. Сей факт пусть остаётся на совести автора.
P.S. В некоторых проектах настолько очевидные ошибки, что становится понятно, что автор их никогда и не компилировал. Например использование putchar(), а #include<stdio.h> и в помине нету.

"выскакивает ошибка" - неинформативно. Какая ошибка? Почему у меня (на том же компилере, пример Blinky для AT91SAM7S) не выскакивает? Не поленюсь повторить: ну не устанавливайте программы в каталоги с пробелами, если не уверены. "По этому всё сразу должно заработать." - у меня и работает, все не проверял, но то, что проверил - работает, даже в плату загружал - и там моргает.
P.S.: В "некоторых проектах", если читать внимательно, putchar реализуется, а не импортируется из библиотеки, да если доку читать, там так и написано: реализуйте свой putchar. Видно, что Вы пришли в программирование МК с программирования ПК, где putchar реализован в библиотеках (хотя и его можно переопределить).
Сергей Борщ
Цитата(sonycman @ Jan 28 2007, 02:37) *
Сколько у ARMов регистров управления портами ввода-вывода ! Штук двадцать, наверное! Для каждой функции один для установки битов, другой для снятия, третий для статуса. Пока все аббревиатуры запомнишь ! smile.gif
Причем практически все заполняются только один раз - при старте программы, а в дальнейшем используются три, как и в AVR. Или в дальнейшем пользуются макросы (например такие) и вообще забываешь как называются эти регистры до написания кода инициализации в следующем проекте.


Цитата(sonycman @ Jan 28 2007, 02:37) *
Разъясните, плиз, по прерываниям:
при возникновении какого-либо прерывания (FIQ или IRQ),
Процессор переходит на адрес 0x1С или 0x18 (ARM DDI 0210C, стр 2-21). В момент перехода регистр статуса CPSR (ARM DDI 0210C стр. 2-13), который определяет состояние (THUMB/ARM), режим (User, Svc, Irq..), разрешение прерываний сохраняется в специальном регистре (SPSR_xxxx). В регистр статуса автоматически заносится значение, переключающее процессор в нужный режим (ARM DDI 0210C стр. 2-17). Дальше он предоставлен программисту - тут может стоять ветвление по вектору из контроллера прерываний или процедура обработки, которая где-то внутри себя осуществляет ветвление на обработчики конкретных источников прерываний. Как вариант - тупая проверка флагов (у ADuC70xx контроллера прерываний нет).
При выходе из прерывания регистр статуса восстанавливается из SPSR_xxxx, таким образом процессор попадает в то же состояние и режим в котором он находился до прерывания.
Цитата(sonycman @ Jan 28 2007, 02:37) *
Имею ввиду, заложены ли эти механизмы аппаратно в ядро, или это всё надо делать ручками перед выходом из обработчика прерывания?
Заложено в ядро. Если писать на С, то достаточно объявить функцию обработчика с соответствующим квалификатором (тут обсуждалось). А на ассемблере есть специальная команда, которая одновременно с переходом (возвратом из прерывания) восстанавливает регистр статуса.
sonycman
Цитата
А у тебя proteus есть? Ты им когда-нибудь пользовался? Если нет, то не видел счастья в жизни!!!

Протеус есть, пару раз запускал на 10 минут. Пока не особо он мне нужен. Но вещь полезная, наслышан. Может, и воспользуюсь когда smile.gif

2Сергей Борщ
Спасибо, всё понял! smile.gif
Сергей Борщ
Цитата(Alex_inventor @ Jan 28 2007, 03:40) *
Объясните мне в чём такая принципиальная разница? Хотябы небольшая?
Между const и volatile? В том что const запрещает запись в пременную (и при попытке такой записи компилятор выдаст ошибку) а volatile не запрещает.
Цитата(Alex_inventor @ Jan 28 2007, 03:40) *
Зачем это делать? Какое сохранение времени, тиков? Чтение из flash одна инструкция процессора
Во-первых флеш (и ОЗУ) бывает медленной, и одна инструкция с доступом в память может занимать далеко не один такт процессора.
Во-вторых не забывайте, что ширина инструкции 32 бита, ширина адреса тоже 32 бита, поэтому одной командой можно обратиться лишь к ячейке, находящейся сравнительно недалеко от адреса, из которого берется инструкция (куда указывает PC). Для доступа к остальным ячейкам используется косвенная адресация, их адрес надо сначала загрузить в регистр из ячейки, в которую можно "дотянуться" в регистр, а уже потом косвенно по содержимому регистра считать значение. В режиме THUMB ширина инструкции 16 бит, развивать мысль?

Цитата(Alex_inventor @ Jan 28 2007, 03:40) *
Цитата
а не использовать сохраненное где-то считанное ранее значение.

Как это понимать? Если мы присвоим x=*adr, то что компилятор будет наивно полагать что переменная х никогда не изменится и будет использовать её как источник адреса?
"Ппереведи!" smile.gif Наоборот, он будет вполне резонно полагать что *adr не изменится и использовать вместо него x.
Вот смотри пример:
Код
int z = 7;
int *adr = &z;
int x = *adr;
int y = *adr;  //(1)
z = x + y;
В данном случае компилятор имеет право в точке (1) не считывать в y содержимое памяти *adr а использовать для инициализации y значение х. Даже более того, он может вообще не создавать addr, а сразу использовать значение 7. И вообще весь этот код превратить в z = 14. А вот в случае
Код
int z = 7;
int volatile *adr = &z;
int x = *adr;  //(1)
int y = *adr;  //(2)
z = x + y;
мы его заставляем в точках (1) и (2) сгенерировать чтения ячейки z. Ведь если z это, например, таймер, то между точками (1) и (2) его значение могло измениться.
Цитата(Alex_inventor @ Jan 28 2007, 03:40) *
Извините, если кому-то покажется агрессивным стиль написание, так получилось. smile.gif
Еще не все потеряно - стиль можно изменить.

Цитата(Alex_inventor @ Jan 28 2007, 03:40) *
Ну если быть точным, насколко я понял, то выражение полностью выглядит так:
#define VICIRQStatus (*((volatile unsigned long *) 0xFFFFF000))
Что ж, разберем его "по косточкам":
0xFFFFF000 - константа.
(unsigned long *)0xFFFFF000 - указатель на unsigned long, содержащий (указатель содержит, а не unsigned long) адрес 0xFFFFF000
(volatile unsigned long *) 0xFFFFF000 - указатель на unsigned long, содержащий адрес 0xFFFFF000, при этом содержимое ячейки, куда он указывает, может изменитья в любой момент. Поэтому каждый раз, когда в программе встречается обращение по этому указателю, надо считывать эту ячейку (пример см. выше).
((volatile unsigned long *) 0xFFFFF000) - то же самое.
*((volatile unsigned long *) 0xFFFFF000) - содержимое ячейки, на которую указывает вышеописанный указатель.
(*((volatile unsigned long *) 0xFFFFF000)) - то же самое.

Цитата(Alex_inventor @ Jan 28 2007, 03:40) *
область памяти с константой u long имеющую значение 0xFFFFF000
Нет. это не константа имеет значение 0xFFFFF000, а область памяти имеет фиксированное расположение по адресу 0xFFFFF000. И содержимое области памяти константой не является. Причем заметьте, с точки зрения языка С квалификатор const вместе с volatile не говорит о том, что переменная не может измениться, а говорит лишь о том, что в эту переменную запрещена запись. И в вашем определении VICIRQStatus присутствует ошибка - в VICIRQStatus запись запрещена, определение должно выглядеть так:
Код
#define VICIRQStatus   (*((volatile unsigned long const *) 0xFFFFF000))
И еще раз обращу внимание, что тут описан не константный указатель, а указатель на константу (на ячейку в которую запрещена запись).

Цитата(Alex_inventor @ Jan 28 2007, 03:40) *
Дело в том, что компилятор не может недавно прочитать значение по ссылке . Ссылка это переменная. Недавно прочитать может только работающая программа. Когда компилятор уже давно сделал сваи дела и гордо удалился. biggrin.gif
Ну не придирайтесь к словам. Пусть будет "Компилятор может со 100% вероятностью рассчитать какое значение будет иметь переменная в этой точке не считывая ее в этом месте".

Цитата(Alex_inventor @ Jan 28 2007, 03:40) *
В общем, подвожу итог: структура define VICIRQStatus (*((volatile unsigned long *) 0xFFFFF000)) разложена по полочкам, стала понятна, появилась осмысленная возможность её использование. Хотя некоторые аспекты так и не объяснены (например, расположение звезды справа). smile.gif
У меня сложилось впечатление что разложена она не по тем полочкам. Постарался изложить макимально подробно. Если "звезда справа" все еще смущает - читайте все доступные материалы про указатели.
Alex_inventor
[/quote]"выскакивает ошибка" - неинформативно. Какая ошибка? Почему у меня (на том же компилере, пример Blinky для AT91SAM7S) не выскакивает?[quote]
Во первых я выше достаточно информативно описал ситуацию. Пример blinky, это пример из uVision, а я обсуждал примеры из книги. Blinky тоже попробовал, та же ошибка. Специально для вас повторю:
[quote]Build target 'LPC2106'
assembling Startup.s...
Assembler messages:
Error: Error: can't open Files\Keil\ARM\INC\Philips\ for reading
Files\Keil\ARM\INC\Philips\: No error
compiling Blinky.c...
arm-uclibc-gcc: cannot specify -o with -c or -S and multiple compilations
Target not created[/quote]
Я не сомневаюсь, что подшаманив, всё будет в порядке. Дальнейшее обсуждение данного вопроса считаю БЕСМЫСЛЕННЫМ, ибо я изучаю RealViwe, а все сторонние коды беру в виде алгоритмических идей. Имхо, хоть и медленный, но лучший способ для осваения.
По поводу:
[quote]Например, использование putchar(), а #include<stdio.h> и в помине нет.[/quote]
Я знаю, что может быть и своя putchar. Как мне не знать, если я как раз своим и пользуюсь. Пересмотрел все проекты примеров, и действительно не нашёл подобного случая, показалось наверное. Извиняюсь за дезинформацию. blush.gif
Возник вопрос. Есть такой регистр LSR. В нём 5 бит сигнализирует FIF0 пуст, 6 SHIFT регистр пуст. Хочется реализовать следующую конструкцию. Есть функция puts(выводит байты в UART). Кидаешь, например функции 10 байт, она сразу заполняет буфер FIFO и возвращается в программу, пока байты отправляются, мы делаем полезную работу. Далее мы опять вызываем функцию puts. Как ей определить заполненность FIFO? Ведь нет бита FIFO полн, или придётся впустую ждать пока он опустеет, чтоб конкретно знать 16 байт можно загнать. Кто нибудь реализовывал подобную конструкцию? smile.gif
sonycman
Цитата
Возник вопрос. Есть такой регистр LSR. В нём 5 бит сигнализирует FIF0 пуст, 6 SHIFT регистр пуст. Хочется реализовать следующую конструкцию. Есть функция puts(выводит байты в UART). Кидаешь, например функции 10 байт, она сразу заполняет буфер FIFO и возвращается в программу, пока байты отправляются, мы делаем полезную работу. Далее мы опять вызываем функцию puts. Как ей определить заполненность FIFO? Ведь нет бита FIFO полн, или придётся впустую ждать пока он опустеет, чтоб конкретно знать 16 байт можно загнать. Кто нибудь реализовывал подобную конструкцию?

А что там в даташите написано про этот регистр?
Наверняка, можно определить конец передачи или по прерыванию, или (если нет соотв. бита) 5 бит LSR будет сигнализировать, что буфер пуст smile.gif
Тебе бы надо User Manual скачать на твой чип, там должно быть подробно описано.
Alex_inventor
2Сергей Борщ
Спасибо за продуктивную дискуссию smile.gif . Стала понятна звезда справа, это инициализация указателя. В некоторых местах вы меня неправильно поняли, но не буду заострять на этом внимание. Главное совместными усилиями найти истину. smile.gif
Alex_inventor
2sonycman
Так я этот регистр из Datasheеt и брал. (LPC210X). Я же писал, что как раз, конец передачи определить можно. Цель использовать FIFO передатчика на все 100%. Ну, смотри, к примеру, есть такой код:
x=1;
x++;
puts("Hello word"); Инструкция возвратится сразу после заполнения буфера, дальше буфер сам аппаратно опустошается.
x++;
x+=y;
puts("Hello word"); Вот здесь и запара. Если puts, будет знать размер заполненного буфера, то она дополнит его, и сразу возвратится. И мы не потеряем ни одного такта впустую.(а при скорости 9600 это огромное время!) Хотя бы бит заполнения был, тогда она работала бы так, скинул байт, проверил бит, всё OK? Скинула следующий байт, не OK, ждём OK.
sonycman
А разрядность Shift регистра какая?

В принципе, ты и так не потеряешь время зря.
Задействуй прерывания.
Как только передача из FIFO закончится - произойдёт прерывание.
Там ты снова заполнишь буффер следующими данными.
А основная программа в это время пусть занимается своими делами.
Сергей Борщ
Цитата(Alex_inventor @ Jan 28 2007, 14:50) *
Ведь нет бита FIFO полн, или придётся впустую ждать пока он опустеет, чтоб конкретно знать 16 байт можно загнать. Кто нибудь реализовывал подобную конструкцию? smile.gif
Да, это им удалось. Хотя zltigo утверждает что UART просто чудесный. Я обошелся так - завел счетчик и считаю в нем сколько бит послал в FIFO. Если перед отправкой очередного байта обнаружил флаг FIFO пуст - счетчик обнуляю. Если насчитал в счетчике 16 байт - жду флага. Тоже не самый красивый вариант, но лучше ничего пока не придумал.

Тоже интересно было бы посмотреть другие варианты.
sonycman
2Сергей Борщ
Сергей, просвятите меня, пожалуйста, насчёт понятия HEAP.

В файле Startup.s почти любого проекта под uVision RV имеются такие строки:

IMPORT __use_two_region_memory
EXPORT __user_initial_stackheap
__user_initial_stackheap

LDR R0, = Heap_Mem
LDR R1, =(Stack_Mem + USR_Stack_Size)
LDR R2, = (Heap_Mem + Heap_Size)
LDR R3, = Stack_Mem
BX LR

Я это понимаю так: объявляется модель памяти как две области. Какие именно это области мне не понятно sad.gif
Дальше идёт инициализация (заполнение нулями) стёка и данных пользователя.
Затем инициализация регистров значениями адресов и размеров стёка и этой самой кучи (HEAP). Причём это делается вручную, а ведь есть системная функция для этого. Почему?

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

Тогда получается, что куча - это область свободной памяти, из которой происходит выделение кусков при использовании функций запроса памяти?
Сергей Борщ
Цитата(sonycman @ Jan 28 2007, 16:14) *
Так вот, куча в этом стартовом коде всегда имеет размер 0 байт.
А я где-то прочитал, что в этом случае невозможно использовать функции выделения памяти библиотеки С - malloc и подобные.

Тогда получается, что куча - это область свободной памяти, из которой происходит выделение кусков при использовании функций запроса памяти?
Да, в С понятие "куча" - это область для динамического выделения памяти. Скорее всего ее размер задается где-то в настройках проекта.
Не работал с RV, поэтому подробнее не скажу.
Alex_inventor
Куча явно задаётся в Configuration wizard (Startup.s).
sonycman
Да, да - или в визарде, или ручками в тексте:

Heap_Size EQU 0x00000000
AREA HEAP, NOINIT, READWRITE, ALIGN=3
Heap_Mem SPACE Heap_Size

Значит, если я захочу пользоваться malloc() и другими подобными функциями - я должен буду задать размер HEAP, отличный от нуля.
zltigo
Цитата(Сергей Борщ @ Jan 28 2007, 15:52) *
Да, это им удалось. Хотя zltigo утверждает что UART просто чудесный.

Я никогда не утверждал, что 550 - "чудесный". Он индустриальный стандарт разработанный МНОГО лет назад и ВПОЛНЕ сбалансированый. На таких оптимальных решениях учиться надо.
Чудесным вообще ни один UART не называл а максимально лучшим называл имеющийся у AMD186.
Что-то у Сергея с памятью sad.gif
Оптимальное использование Tx FIFO 550 совместимых чипов - после прерывания по опустошению FIFO
забить его 16 байтами (или сколько есть).
Относительные "проблемы" возникают при попытке "чуть-чуть" улучшить с помощью Tx FIFO небуферизированный вывод. Причем именно чуть-чуть улучшить, ибо все рассуждения по улучшению небуферизированного вывода сводятся к тому, что если захочется напечатать "ля!", то эти три символа быстренько влезут в FIFO и время сэкономим. А если печатаем "Привет морякам Балтики от грода-Героя Севастополя!" - упретесь и тупо будете ждать теряя офигенное время? sad.gif
Либо задача позволяет терять время - тогда просто по байтику пихайте и заморачивайтесь. A если нет, то буфер должен быть по любому и "проблемы" в общем-то и нет.







Цитата(sonycman @ Jan 28 2007, 18:01) *
Значит, если я захочу пользоваться malloc() и другими подобными функциями - я должен буду задать размер HEAP, отличный от нуля.

Да. А правильный путь для контролллеров - вместо штатного тупого менеджера памяти использовать свой (или переписать штатный), который под Heap будет использовать всю оставшуюся память контроллера.
sonycman
Блин, вот пока вижу только два недостатка у AT91SAM7S серии:
1. нет собственного PLL для USB, поэтому, при использовании последнего, придётся ограничить частоту CPU на 48 Мгц.
2. Нет DMA для USB. Для всей остальной периферии есть, а вот для USB почему-то нет. sad.gif
Alex_inventor
Цитата
2. Нет DMA для USB. Для всей остальной периферии есть, а вот для USB почему-то нет.

Странно, когда читал, форумы, то основная претензия к LPC была наличие UDP только у USB, а у AT91SAM7 UDP была у каждой периферии. Вот вырезка из datasheet:
Доступ к UDP организован через шинный интерфейс APB. Доступ (чтение или запись) к буферу данных FIF
zltigo
Цитата(sonycman @ Jan 28 2007, 21:34) *
2. Нет DMA для USB. Для всей остальной периферии есть, а вот для USB почему-то нет. sad.gif

Если поищете по форуму,
http://electronix.ru/forum/index.php?showt...6057&hl=DMA
найдете (тема еще несколько раз всплывала), что я думаю о пользе пользе DMA у контроллеров без кэша и/или
с одним банком памяти smile.gif. Короче не расстраиваетесь, это не пентиум - ничего особо Вы не потеряли.
sonycman
2zltigo
Почитал, но не совсем понял некоторые моменты:
Цитата
DMA для укладки порций 1-2 байтов, причем сам контроллер DMA обслуживает только работу с линейным буфером. Сильно тоскливо - для более-менее реальной работы все равно обрабатывать
прерывание от каждых 1-2 байтов...

А почему только 1-2 байтов? Что будет мешать зарядить буфер на передачу 32 байтов? Или 64?

Да, понятно, что DMA буде тормозить CPU при доступе к памяти, но всё равно это лучше, чем записывать ручками каждый байт в SPI?

А в SAM7 порт SSP не точно такой-же, как в LPC?
То есть в LPC SSP может работать в точности как обычный SPI, а у SAM7 нет?

Цитата(Alex_inventor @ Jan 29 2007, 00:12) *
Доступ к UDP организован через шинный интерфейс APB. Доступ (чтение или запись) к буферу данных FIF

UDP - это USB Device Port.
APB - это вроде как Advanced Peripheral Bus.
А я говорил про DMA - Direct Memory Access, или по-другому Peripheral DMA Controller (PDC).
Всё это разные вещи.

У LPC2148 DMA имеется только для USB.
А у SAM7 наоборот - для всей периферии, кроме USB.

Я же говорю, что эти два ARMа как два калеки - изъяны есть у обоих, нет идеала...
Alex_inventor
Сделал маленькое исследование по оптимизации (RV)
Cтрока delay:
for (int d=0; d < usec; d+=5);

Код оптимизации О-0:

MOV R1,0x00000000
0x00000498 CMP R1,R0
BCS 0x000004A8
ADD R1,R1,#0x00000005
B 0x00000498
0x000004A8

Код оптимизации О-1:
То же что и O-0


Код оптимизации O-2:

MOV R1,#string(0x00000000)
0x00000498 CMP R1,R0
ADDCC R1,R1,#0x00000005
BCC 0x00000498

Код оптимизации O-3:

То же что и O-2

Если код оптимизации O-3 по времени, то эта строка вообще выкидывается. Видимо компилятор посчитал, что на неё нужно много времени и она не достойна быстрой программы.

Из всего вышесказанного возникают следующие вопросы:
1. Зачем вообще нужно ставить уровни и подуровни оптимизации, если можно оставить три вида максимально по коду, по времени, смешанное. Ну например в примере выше при O-0 и O-1 дополняется лишняя инструкция на пустом месте, в данном случае это 25% проигрыша, нельзя было что ли сразу как при O-2, O-3?
2. Как вообще (по каким критериям) выбирается эта оптимизация. В хелпе uVision ничего не сказано?
3. Какую оптимизацию посоветуете вы (при каких условиях)?
4. Чего стоит опасаться? А то я пока разобрался что это грёбаная оптимизация angry.gif , ни мог понять куда девается моя пауза wacko.gif , думал компилятор глючит.
Alex B._
>> Если код оптимизации O-3 по времени, то эта строка
>> вообще выкидывается.
Сделай так:
for (<b>volatile</b> int d = 0; d < usec; d=+5);
С точки зрения оптимизатора цикл не имеет смысла, так как в теле цикла (и, наверное в дальнейшем) локальная переменная d не используется. Поэтому он этот цикл и выкинул. Если применить к d квалификатор volatile - все будет нормально.

>> Как вообще (по каким критериям) выбирается эта оптимизация
Отлаживаться - без оптимизации, а там смотря по требуемому времени и объему памяти
sonycman
Цитата(Alex_inventor @ Jan 29 2007, 01:37) *
Из всего вышесказанного возникают следующие вопросы:
1. Зачем вообще нужно ставить уровни и подуровни оптимизации, если можно оставить три вида максимально по коду, по времени, смешанное. Ну например в примере выше при O-0 и O-1 дополняется лишняя инструкция на пустом месте, в данном случае это 25% проигрыша, нельзя было что ли сразу как при O-2, O-3?
2. Как вообще (по каким критериям) выбирается эта оптимизация. В хелпе uVision ничего не сказано?
3. Какую оптимизацию посоветуете вы (при каких условиях)?
4. Чего стоит опасаться? А то я пока разобрался что это грёбаная оптимизация angry.gif , ни мог понять куда девается моя пауза wacko.gif , думал компилятор глючит.


Я думаю вот что:
1. При отладке, например, удобнее, чтобы оптимизация была выключена. Иначе сложнее с асмом разбираться. Компилятор такие перлы иногда творит - ты теперь видел smile.gif
2. По критериям разработчика - то есть тебя. В зависимости от того, какой код тебе надо - быстрый или компактный или и то и другое.
4. Интересно, значит, совсем цикл задержки пропал? Вот это оптимизация!! biggrin.gif
Alex_inventor
Спасибо за ответы, но я вообще имел в виду конкретно значения O-0, O-1…
Эти значения где-нибудь описывают, особенности какие-нибудь? Или это всё условность, а особенности знает только кмпиляторописатели(и то может уже забыли, ведь их тысяча может быть) А простому юзеру остаётся, тупа переключать оптимизцию и сравнивать получившийся размер кода или быстродействие, и параллельно следит не рухнут ли отдельные участки кода или прога в целом?
Вы советуете писать вначале прогу без оптимизации. А как вам такое умозаключение:
Если написать огромный проект без оптимизации, он получится большого размера, медленнее, но в принципе будет работать так как написан. Далее включаем оптимизацию, код будет подвергнут жёсткому насилию со стороны компилятора, что наверняка вызовет множественные логические разрушения хаотичного порядка. Вполне возможна неадекватная работа программы, влоть до полного отказа работоспособности. Я имею ввиду алгоритм работы программы. И мы даже не будем знать из за чего, потому, что так как проект написан целиком, то кажущийся нам сбойный блок, может и не быть сбойным, а работать неправильно потому, что получил сбойные данные. Т.е. появляется пирамидальный эффект накопления ошибки smile3046.gif .
Если же сразу включить оптимизацию, логические ошибки компилятора будут устранятся по мере их появления. Локализовать ошибку будет просто. А весь последующий код будет строится на правильно работающем фундаменте.
Если в моих рассуждениях ошибка blink.gif ?
sonycman
Цитата(Alex_inventor @ Jan 29 2007, 02:40) *
А простому юзеру остаётся, тупа переключать оптимизцию и сравнивать получившийся размер кода или быстродействие, и параллельно следит не рухнут ли отдельные участки кода или прога в целом?


Это ты верно заметил biggrin.gif
Вот что написано в хелпе:

Optimization - Control compiler code optimization for the generated code:
Default: Use the compiler default or the setting of a higher Target or Group level.
Level 0 (-O0): Turn off all optimization, except some simple source transformations.
Level 1 (-O1): Turn off optimizations that seriously degrade the debug view.
Level 2 (-O2): High optimization (default level). The debug view might be less satisfactory because the mapping of object code to source code is not always clear.
Level 3 (-O3): Maximum optimization. Note that Level 3 in combination with Optimize for Time may generate more code that Level 2 since it may unroll loops.
Optimize for Time - Reduce execution time at the possible expense of a larger code size.

Так ведь никто не заставляет тебя включать эти оптимизации. Не трогай их и всё smile.gif
Можешь сам писать код максимально оптимизированно - как умеешь.

А почему бы и сразу не выставить третий уровень оптимизации?
Даже интересно потом будет трассировать smile.gif
Alex_inventor
Выкладываю обещанный, вымученный проект. Проект даёт возможность начать работать с UART, рассчитан на новичков и даёт неплохой старт. Госпада жду от вас подобные проекты с подробнейшими коментариями. smile.gif cheers.gif
zltigo
Цитата(sonycman @ Jan 28 2007, 23:21) *
А почему только 1-2 байтов? Что будет мешать зарядить буфер на передачу 32 байтов? Или 64?

Там обсуждается прием SPI - 8-16 бит а промежуточного FIFO-то и нет. Причем в общем случае передачи без приема в SPI нет. Откуда-куда "заряжать" smile.gif.
Кроме того даже "зарядив" тупо в одну сторону придется задуматься о поведении
SS при передаче этого пакета.
Цитата
Да, понятно, что DMA буде тормозить CPU при доступе к памяти, но всё равно это лучше, чем записывать ручками каждый байт в SPI?

Близко к "один хрен" sad.gif

Цитата
А в SAM7 порт SSP не точно такой-же, как в LPC?
То есть в LPC SSP может работать в точности как обычный SPI, а у SAM7 нет?

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

Цитата
Я же говорю, что эти два ARMа как два калеки - изъяны есть у обоих, нет идеала...

Рассмотрите LPC23xx - как представитель семейства ARM7 он имеет много больше "идеальных" признаков. Подсказываю, что на этом форуме обсуждался smile.gif
Alex_inventor
Вот оно даже как! blink.gif А я думал, что O-0…O-3 по возрастающей идёт. А на самом деле нет. cranky.gif Я использую код O-2. Золотая середина. Асм получается вполне читабельным.
Цитата
Можешь сам писать код максимально оптимизировано - как умеешь.

Писать то можно оптимизировано, но ведь это С. Оптимально только алгоритмы составлять можно, а оптимизация на уровни команд процессора – это исключительна работа компилятора. Совсем без оптимизации нельзя, так как есть ОГРОМНАЯ куча повторяющегося кода в любой программе. Пусть этот код и сваливает в кучу компилятор, и делает туда прыжки. Имхо, это безопасный вид оптимизации, но самый важный и результативный.
zltigo
Цитата(Alex_inventor @ Jan 29 2007, 01:16) *
Проект показывает все аспекты работы с UART

Э.... погорячились sad.gif и сильно....
sonycman
Цитата(zltigo @ Jan 29 2007, 03:30) *
Там обсуждается прием SPI - 8-16 бит а промежуточного FIFO-то и нет. Причем в общем случае передачи без приема в SPI нет. Откуда-куда "заряжать" smile.gif.


Ну, я планирую подключить к SPI порту ЖКИ дисплей от сотового Siemens S65 - 132х176 16 бит.
Поток данных на него может быть большим - кусочек изображения 10 на 10 пикселей весит 200 байт.
Разве не получится сделать так: заряжаю в буфер DMA 200 байт - запускаю SPI на передачу.
Все 200 байт передаются без вмешательства CPU.
Так ведь много лучше, чем по байту/слову "пихать"? smile.gif

Цитата
Рассмотрите LPC23xx

Круто конечно, но TQFP 100 для меня многовато...
Alex_inventor
Цитата
Э.... погорячились и сильно....

Ну prinf, разве что не написал? А что ещё нужно для начала? Показано как инитить, функции отправки свои, не библиотечные, что бы видеть как оно там крутится? Прерывания будут в следуюем релизе, я же говорил что проект постепенно наращивать буду. Чего вам такого принципиально не хватает? Ладно,изменю, чтобы глаза не резало.
sonycman
Цитата(Alex_inventor @ Jan 29 2007, 03:35) *
Писать то можно оптимизировано, но ведь это С. Оптимально только алгоритмы составлять можно, а оптимизация на уровни команд процессора – это исключительна работа компилятора.

Можно делать вставки прямо на асме smile.gif

Цитата
Чего вам такого принципиально не хватает?

Да нормально всё! Для начала-то.
Работает smile.gif w00t.gif
Дерзай дальше.
А мэтры, конечно, только морщиться будут от наших "потуг", это понятно twak.gif
zltigo
Цитата(sonycman @ Jan 29 2007, 01:47) *
Круто конечно, но TQFP 100 для меня многовато...

Ужас smile.gif 64 или 100 в чем проблема? Поскольку альтернатива не в DIP8, то уже все равно.



Цитата(sonycman @ Jan 29 2007, 01:55) *
А мэтры, конечно, только морщиться будут от наших "потуг", это понятно twak.gif

Если это в "мой огород", то я не про потуги а про претензии sad.gif на что-то полезное о которых пока
говорить крайне преждевременно.
sonycman
Цитата(zltigo @ Jan 29 2007, 04:05) *
Если это в "мой огород", то я не про потуги а про претензии sad.gif на что-то полезное о которых пока
говорить крайне преждевременно.

Согласен.

Ну а насчёт SPI c передачей 200 байт - это реально сделать? Через DMA?
Alex_inventor
2zltigo
O нет ни в коем случае не подумайте, что я не доволен вашей критикой. Я обеими руками за критику! smile.gif Только КОНСТРУКТИВНУЮ критику. Ведь как в поговорке сказано: “В споре выигрывает не тот, кто прав, а оппонент, потому что узнал для себя что-то новое”. Хотелось бы выслушать пару аргументаций, ну например по коду, где лучше сделать, а где переделать. В UART не хвотает функции getchar(), я её позже напишу и выложу.
zltigo
Цитата(Alex_inventor @ Jan 29 2007, 01:50) *
Цитата
Э.... погорячились и сильно....

Ну prinf, разве что не написал?

А Вы ее (полагаю речь идет о printf() ) писать собираетесь?

Цитата
Показано как инитить

Скорее "как не надо" sad.gif совершенно жуткие записи непоименованных констант sad.gif

Цитата
функции отправки свои, не библиотечные

Ага sad.gif putchar() просто умиляет - имя библиотечной, но прототипу зачем-то не соответствует и никто
(тот-же printf() ) ей уже не воспользуется.

puts() просто образчик того, как не надо писать на C
Код
//Отправка строки (UART0)
void puts(uint8 *str)
{
  int x;
  for(x=0;x<100;x++)     //Защита на отсуствие /0
  {
            if( str[x]==0) x=200;
            putchar(str[x]);
  }
}

Защита "на отсутствие" '/0' в строковой переменной - прикольно.
Лишняя переменная и массив вместо естественной работы с указателем.
Ну и x=200 вместо break - это вообще sad.gif

Книжки, банальные книжки по "C" читать от корки до корки (а не "то, что мене сейчас надо"). Надо
обязательно читать.

Код
#define OUTCH( ch ) do{ while( !(U0LSR & LSR_THRE) );    \
                    U0THR = ch;                \
                    } while( 0 )

int putchar( int ch )
{
    OUTCH( ch );
    return( ch );
}

void puts( uint8 *str )
{
    while( *str != '\0' )
        OUTCH( *str++ );
}




Цитата(sonycman @ Jan 29 2007, 02:07) *
Ну а насчёт SPI c передачей 200 байт - это реально сделать? Через DMA?

А при этом "нарезка" SS на порции по 8-16 бит нужна? Короче нужно конкретно с поведением SPI
при передаче "пачки" надо разбираться.
sonycman
Цитата(zltigo @ Jan 29 2007, 04:42) *
А при этом "нарезка" SS на порции по 8-16 бит нужна? Короче нужно конкретно с поведением SPI
при передаче "пачки" надо разбираться.

Там просто идёт заголовок (8 байт), а потом можно потоком.
Передача только в сторону дисплея.
Скорость - 10Мбит.
Думаю, должно работать.
Достаточно подготовить буфер - и DMA его скормит.
Alex_inventor
2zltigo
Вообще я не спорю, что функции написаны на скорую руку и красотой не блещут, главная цель работоспособность Объясню, какими принципами я руководствовался при написание.
Ну и x=200 вместо break - это вообще
Это не воще, а как вы будите тогда по UART 0 отсылать? Никак ?
Ваша функция:
Цитата
void puts( uint8 *str )
{
while( *str != '\0' )
OUTCH( *str++ );
}

тоже не способна 0 отослать

Цитата
Защита "на отсутствие" '/0' в строковой переменной - прикольно.


Этот приём я использовал в старых проектах, как защиту, потому-то существовала возможность отдать функции строку без /0. Тогда бы putchar всю flash в UART вывел бы (ну или половину). Ненравится? Уберите. 1 секунда.

Цитата
Скорее "как не надо" совершенно жуткие записи непоименованных констант


Каму жуткие, а кому и нет. Где надо имена там я имена применяю. Но для инициализации переферии я применяю bin вид. Потому что мне так удобно. В datashetah в каждом регистре каждый бит что-то значит. Легко получается, надо функцию задействовать поставил 1 в bin числе.

Вообщем я никому не навязываю свои труды. Да я повода и не довал? Хотите берите, хотите не берите. Но код работает, по размерам не намного больше вашего, да и для меня понятней. Prinf() писать конечно не буду. И хватит меня в книги тыкать.
Alex_inventor
2zltigo
Критика, критикой, но столь негативное поведение НЕУМЕСТНО! angry.gif Я переделал функции, в соответствии с критическими замечаниями. Теперь putchar(), printf() может использовать:
//Отправка char (UART0)
int putchar( int ch )
{
while( !(U0LSR & LSR_THRE));
U0THR = ch;
return( ch );
}

//отправка строки (UART0)
void puts( uint8 *str )
{
while( *str != '\0' )
putchar( *str++ );
}

Если надо кому 0 передувать, пусть сами переделают. А тоя попытался отступить на шаг от религиозных норм, так меня чуть не “сожрали”! maniac.gif
И кто после этого захочет свои проекты выкладывать? sad.gif Ничего, мы сильные! Повторяюсь, форум называется: “Хочу попробовать ARM, подскажите, что для этого нужно?, Какой проц выбрать, отлад. платку и какой софт?” а не “Не лезь со своим свинячим рылом в наш огород”. Печально госпада. sad.gif
sonycman
2Alex_inventor
Да ты не расстраивайся так. Просто уровень у тебя (и у меня) далеко не профессиональный, поэтому и критика будет такая.
И никто тут не кричит - мол, не лезь в "огород".
Советы верные - надо развиваться, учиться.
Стоит прислушаться.

Но раз проект работает - это хорошо, значит - цель выполнена.
А умение чётко и красиво писать программу придёт со временем.

Скажи, у тебя в практике были законченные проекты - от принципиальной схемы - макетка - плата - программа - готовое устройство?
Просто интересно?
Alex_inventor
Вообще я железячник. Радиоэлектроникой увлекаюсь с 9 лет. Закончил политех с красным (отделение радоаппаратостроение). Могу свободно разработать абсолютно любой проект на железе. Программированием занимаюсь около 2 лет. Полных проектов собрал целую тучу…(в смысе с мк, а чисто железок всяких то вообще не перечесть). Ну , на МК, штук 100 будет наверное. Было пару очень серьёзных проектов. А так по мелочи. Восновном пишу для AVR. Самый первый проект на MK был на PIC, на asm писал. Это был электронный звонок, но необычный. Там был маленький зеркальный шар, который при звонке крутился и на который светило три маленьких прожектора которые каждый раз маргали по разному. В звонок я зашил сотню мелодий от SonyEriksona и каждый раз звучала новая мелодия. Правдо с громкостью пересторался, звонило, так что у соседий слышно было.
А вообще я не расстраиваюсь. Я абсолютно уверен в своих программах. Стиль НИЧЕГО не значит, главное, что бы работало.(как там говорится? имидж ничто ЖАЖДА ВСЁ?) Сейчас вот ARM изучаю. А вообще, если надо, могу заткнуть кого хочешь! angry.gif angry.gif angry.gif Просто сейчас цель другая. И я на рожон не лезу. Веду дипломатичные переговоры.
Andy Great
Цитата(Alex_inventor @ Jan 28 2007, 14:50) *
Во первых я выше достаточно информативно описал ситуацию. Пример blinky, это пример из uVision, а я обсуждал примеры из книги. Blinky тоже попробовал, та же ошибка. Специально для вас повторю:
Цитата
Build target 'LPC2106'
assembling Startup.s...
Assembler messages:
Error: Error: can't open Files\Keil\ARM\INC\Philips\ for reading
Files\Keil\ARM\INC\Philips\: No error
compiling Blinky.c...
arm-uclibc-gcc: cannot specify -o with -c or -S and multiple compilations
Target not created

Я не сомневаюсь, что подшаманив, всё будет в порядке. Дальнейшее обсуждение данного вопроса считаю БЕСМЫСЛЕННЫМ, ибо я изучаю RealViwe, а все сторонние коды беру в виде алгоритмических идей. Имхо, хоть и медленный, но лучший способ для осваения.

Не поленюсь повторить в четвертый раз: не устанавливайте программы в каталоги с пробелами. Наверняка установка была в "C:\Program Files\Keil", а потом удивляетесь, что пробел считается разделителем параметров в GCC. Прочитайте внимательно написанное Вами же. Насчет бессмысленности - я не уверен: а вдруг пригодится? Впрочем, умолкаю.
Сергей Борщ
Цитата(Alex_inventor @ Jan 29 2007, 00:40) *
Далее включаем оптимизацию, код будет подвергнут жёсткому насилию со стороны компилятора, что наверняка вызовет множественные логические разрушения хаотичного порядка. Вполне возможна неадекватная работа программы, влоть до полного отказа работоспособности.
Это значит что ваша программа была написана с ошибками. И такой отказ может призойти даже если вы добавите одну лишнюю инструкцию в программу на том уровне оптимизации, где все работало. Грамотно написанная программа работает одинаково (не считая скорости) независимо от уровня оптимизации. Посмотрите на вашу ошибку с циклом и volatile - это типичный пример. Это Ваша ошибка, если бы вы написали правильно (с volatile) все бы работало сразу и независимо от оптимизации, а вы бы не тратили напрасно время пытаясь поймать эту ошибку. Естественно, чем больше вы таких шишек набъете тем больше опыта у вас будет, но внимательно читая книжки по С вы имеете возможность
1) избежать таких ошибок вместо спотыкания о них
2) понять истинную причину, вызывающую ошибку. Ведь весьма вероятно вы найдете способ обойти ошибку самостоятельно, но поскольку вы самостоятельно неправильно поняли причину ошибки ваш способ не будет работать с такой же ошибкой в другом месте или перестанет работать в этом при незначительном изменении программы. Опять же ваш пример с циклом - как к гадалке не ходи ваше решение было "не пользовать уровень оптимизации в котором цикл исчезает". Решение позволяет в этот момент обойти ошибку, но оно в корне неверное.

Цитата(Alex_inventor @ Jan 29 2007, 03:12) *
Каму жуткие, а кому и нет. Где надо имена там я имена применяю. Но для инициализации переферии я применяю bin вид. Потому что мне так удобно. В datashetah в каждом регистре каждый бит что-то значит. Легко получается, надо функцию задействовать поставил 1 в bin числе.
Вот еще один пример. Даже если вы наизусть помните расположение битов в регистре и без напряжения переводите в уме в двоичный вид и обратно - глядя в такой исходник очень легко пропустить ошибку "занес бит не туда или не тот". Или же читая такой исходник приходится держать рядом раскрытый даташит, что сильно отвлекает от собственно алгоритма. Сравните с этим:
Код
    UART->LCR = (1 << UART_DLAB);
    UART->DLM = (baud_code >> 8) & 0xFF;
    UART->DLL = (baud_code >> 0) & 0xFF;
    UART->LCR = ((0 << UART_BC) | (0 << UART_PS) | (0 << UART_PE) | ( 0 << UART_SBS) | (3 << UART_WLS));   // 8,n,1-
    UART->FCR = (1 << UART_RTLS) | (1 << UART_TFR) | (1 << UART_RFR) | (1 << UART_FCRFE);   // enable and reset FIFO, 4-bytes int level
    UART->IER = (1 << UART_RDAIE) | (0 << UART_THREIE);
}
В таком коде большинство комментариев становится ненужными.

Цитата(Alex_inventor @ Jan 29 2007, 04:20) *
Я абсолютно уверен в своих программах. Стиль НИЧЕГО не значит, главное, что бы работало.(как там говорится? имидж ничто ЖАЖДА ВСЁ?)
Вот тут вы сильно ошибаетесь, и, надеюсь, осознание этого у вас постепенно придет с опытом, как пришло ко мне. Если у вас есть ясный и понятный стиль - ваша программа легко читается. Как правило результирующий код при этом получается короче чем у сумбурно написанной. Возможно, это потребует больше писанины в исходнике. Но вероятность допустить ошибку станет меньше именно за счет того, что исходник становится читабельней и проще.

Я пришел к такому выводу - красиво написанная программа работает лучше. Поэтому могу потратить несколько дней на поиск красивого варианта небольшой функции вместо того чтобы сляпать ее абы как, с подпорками и расчалками. И такой подход себя оправдывает.

Успехов! Нет предела совершенству.
SpiritDance
Цитата(Alex_inventor @ Jan 29 2007, 05:20) *
Я абсолютно уверен в своих программах. Стиль НИЧЕГО не значит, главное, что бы работало.(как там говорится? имидж ничто ЖАЖДА ВСЁ?)

Гхм. Мне бы такую же уверенность при таком же подходе. Искренне надеюсь на то, что от стабильности работы ваших приборов не зависят жизни людей.
Позволю заметить есть прекрасная книжка по поводу стиля программирования на С - Ален Голуб "Веревка достаточной длины чтобы... прострелить себе голову"(по-моему так). Больше сказать нечего.
sonycman
Цитата(Alex_inventor @ Jan 29 2007, 06:20) *
Вообще я железячник. Радиоэлектроникой увлекаюсь с 9 лет. Закончил политех с красным (отделение радоаппаратостроение). Могу свободно разработать абсолютно любой проект на железе.

Это круто smile.gif
Значит, ты со схемотехникой "на ты"? В случае чего, можно будет обратиться к тебе за советом?

Цитата(Сергей Борщ @ Jan 29 2007, 12:54) *
UART->LCR = (1 << UART_DLAB);
UART->DLM = (baud_code >> 8) & 0xFF;
UART->DLL = (baud_code >> 0) & 0xFF;
UART->LCR = ((0 << UART_BC) | (0 << UART_PS) | (0 << UART_PE) | ( 0 << UART_SBS) | (3 << UART_WLS)); // 8,n,1-
UART->FCR = (1 << UART_RTLS) | (1 << UART_TFR) | (1 << UART_RFR) | (1 << UART_FCRFE); // enable and reset FIFO, 4-bytes int level
UART->IER = (1 << UART_RDAIE) | (0 << UART_THREIE);

Согласен. Такие выражения можно сделать компактнее, если пропустить подобное: 0 << UART_PS, особенно для неиспользуемых фич.
Alex_inventor
Цитата
Не поленюсь повторить в четвертый раз: не устанавливайте программы в каталоги с пробелами.

Каталог с проектами всегда находился в папке c:/keil
Сам компилятор находится в папке с:\ Cygnus
Цитата
Посмотрите на вашу ошибку с циклом и volatile - это типичный пример.

Volatile я заметил уже после того, как проект был выложен. Не заметил как там его оставил после экспериментов, при поиске пропажи паузы. Ну осталось, и что пауза не работает? Всё работает. Все инструкции процессора правильные и заданное время точно до us. Это не моя инициатива. Выше мне советовали вставить volatile, что бы компилятор не выкидывал паузу. Однако, это никакой роли не сыграл и он всё ровно выкидывал её при оптимизации O-3 time. И что тут неверного? Сказали что переменная может изменятся, и компилятор не должен проводить лишних телодвижений при оптимизации?

Цитата
Это значит что ваша программа была написана с ошибками.

Вы не понимаете сути, поставленного вопроса, или не хотите понимать. Как программа может быть написано неправильно, если я заранее сказал, что задача написана ПРАВИЛЬНО! НЕТ давайте избавимся от терминов правильно, неправильно. А то для одного будет правильно, а для другого неправильно (ну там switch, вместо for для цикла, например). Давайте скажем, что программа – работает (можно добавить ещё - по алгоритму). Т.е независимо от того, как программа выглядит на С, после компиляции программа выдаёт все заложенные в неё характеристики, это и время и размер и алгоритмы. Вопрос состоит в том, каких фокусом можно ожидать от компилятора при оптимизации и как с ними бороться. Ну что неправильного написано в строке for(x=0;x<100;x++)? Знаю, скажете что, по мнению и тому подобное ч нигде ни применяется ну дальше в том же духе. Одного при оптимизациях O-0…O-2 ничего не выкидывается, а при O-3 time уже всё? Там правильно, а здесь уже неправильно? Ошибки бывают двух видов. Синтаксические, и алгоритмические. Первые решаются на этапе компиляции, вторые на этапе отладки. Пройти этот путь и всё. Чего вам не хватает? Причём замете, я ни говорю что надо писать малопонятные запутанные программы. Я пришёл в С из asm, и максимально где можно ставлю коментарии(много времени не займут но потом могут сэкономить так много) и разделяю программу на отдельные логические блоки и файлы, помойму это можно заметить по проекту.
Цитата
И такой отказ может произойти, даже если вы добавите одну лишнюю инструкцию в программу

Извиняюсь за дерзость, но это, мягко говоря, неправдо! Ну, добавил я лишнюю инструкцию? Что произойдёт, добавится лишняя строка на асме? И при этом компилятор решил, что это сигнал для него, и настало время х и перелопатит всю программу? Максимум перелопатит маленький алгоритм, куда входит инструкция. Но это решается про стек отдельная беседа (как правило, он берётся с большим запасом). Я не ставил вопрос, как грамотно писать программы, в конечном счете, судья не вы и не я, а контроллер. Он последняя инстанция и если его будет ”удовлетворять” то что мы ему даём, и выдаст требуемые характеристики то задача решена. Ну и на последок, аргументы типа ”правильно написанная будет работать лучше, чем так называемая неправильная”. Это уже проблемы отладчика. Как он сделает свою работу, так и будет работать. Если есть есть N ситуаций в которых нужно получить M поведений, то надо не ленится а протестировать во всех N ситуациях. Я НЕ ЗАЩИЩАЮ МОИ ТВОРЕНИЯ!!! Я ХОЧУ СКАЗАТЬ ЧТО НЕ СТАВТИ ВАШИ ТВОРЕНИЯ ВЫШЕ ВСЕХ ОСТАЛЬНЫХ ТОЛЬКО ПОТОМУ ЧТО ОНИ ВАШИ! Выкладывайте ваши решения и не поливайте помоями другие, допускается указание на более лучшее решения по вашему мнению. А что лучше решит каждый для себя САМ!!!
Цитата
Я пришел к такому выводу - красиво написанная программа работает лучше.

Это чисто субъективное мнение. Для какждого красота своя. Мне лично больше нравится, и следовательно быстрее работаю, с bin. А ваши (x<<1) ненравятся. Кто же кроме меня покажет и другой стиль если я один такой, а вы все "правильно" пишете в одном стиле. Пусть люди выберают. Если data sheet вас отвлекает, ну тогда я незнаю...(прось ба не вставлять- не знаешь не говори, имелось в виду другое)
Цитата
Поэтому могу потратить несколько дней на поиск красивого варианта небольшой функции вместо того чтобы сляпать ее абы как,

Признаюсь честно, сам страдаю иногда таким подходом. Причём в некоторых случаях красота ставится выше, чем производительность и время на написание. Уверяю вас оптимальное решение и красивое решение РАЗНЫЕ ВЕЩИ!
Цитата
ваших приборов не зависят жизни людей.

Сниму ваше напряжение, нет не зависит. Живите спокойно, пока.
Блин bb-offtopic.gif какойто получается. Искренне надеялся избежать этого. Как правило такие форумы, где идёт взаимное выдёргивание контекста, оправдывания и так далие бысторо тухнут sad.gif
Dr.Craft
Цитата
Позволю заметить есть прекрасная книжка по поводу стиля программирования на С - Ален Голуб "Веревка достаточной длины чтобы... прострелить себе голову"(по-моему так).


Точнее "... чтобы выстрелить себе в ногу" - читать всем "адназначна", вещь стОящая
Andy Great
Цитата(Alex_inventor @ Jan 29 2007, 14:28) *
Цитата
Не поленюсь повторить в четвертый раз: не устанавливайте программы в каталоги с пробелами.

Каталог с проектами всегда находился в папке c:/keil
Сам компилятор находится в папке с:\ Cygnus

А это Вами приведенная ошибка? Не видно, чтоб от корня Кейл рос...
Цитата
Error: Error: can't open Files\Keil\ARM\INC\Philips\ for reading

Такие как Вы, не разобравшись в предмете, портят потом впечатления другим, которые бы потом проскочили эти грабли незаметно.
sonycman
Цитата(Andy Great @ Jan 29 2007, 17:07) *
Error: Error: can't open Files\Keil\ARM\INC\Philips\ for reading

Блин, а у меня по-умолчанию в Program Files Микровижн стоит.
Правда, проблем пока не было - проекты собираются.
Компилятор RealView.
Значит, это только GCC не любит пробелы?
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.