Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: Интересный глюк в CodeVisionAVR
Форум разработчиков электроники ELECTRONIX.ru > Микроконтроллеры (MCs) > AVR
DMD
Обнаружил интересный глюк в CodeVision, целый день вчера просидел - думал во мне дело, оказалось, что нет.
Если мы делаем сдвиг и результирующее число выходит из размера 1 байта, то, почему-то, компилятор не преобразует его к int (хотя обязан по стандарту). То есть вот такой код работает непрявильно:
Код
unisigned char s = 243;
//...
unsigned int d = (unsigned int)(s << 4);  // d != 3888


а надо так делать, что глупо...

Код
unisigned char s = 243;
//...
unsigned int d = (unsigned int)(((unsigned int)s) << 4);  // d = 3888


Интересно, зачем это надо или это просто баг??..
Сергей Борщ
Да, выходит, это еще одно несоответствие стандарту этого компилятора.
Можно написать проще:
Код
unsigned int d = (unsigned int)s << 4;
prottoss
Цитата(DMD @ Apr 17 2008, 16:02) *
Обнаружил интересный глюк в CodeVision, целый день вчера просидел - думал во мне дело, оказалось, что нет.
Код
unisigned char s = 243;
//...
unsigned int d = (unsigned int)(s << 4);  // d != 3888
А по моему - все правилно делает компилятор:

1. Выполняется выражение в скобках - 8-бит переменная сдвигается на четыре бита влево

2. Результат преобразуется к беззнаковому целому.



А вот так:

Код
unisigned char s = 243;
//...
unsigned int d = (unsigned int)(((unsigned int)s) << 4);  // d = 3888


1. Выполняется выражение во внутренних скобках - s преобразуется к беззнаковому целому.

2. Выполняется выражение во внешних скобках - 16-бит беззнаковое целое сдвигается на четыре бита влево

3. Результат преобразуется к беззнаковому целому



Все правильно smile.gif
Сергей Борщ
Цитата(prottoss @ Apr 17 2008, 13:31) *
А по моему - все правилно делает компилятор:
"По-вашему" - вполне вероятно. Но по стандарту должно быть иначе:
Цитата
6.3.1 Arithmetic operands
6.3.1.1 Boolean, characters, and integers

....
2 The following may be used in an expression wherever an int or unsigned int may be used:
— An object or expression with an integer type whose integer conversion rank is less than the rank of int and unsigned int.
— A bit-field of type _Bool, int, signed int,or unsigned int.
If an int can represent all values of the original type, the value is converted to an int; otherwise, it is converted to an unsigned int. These are called the integer promotions. All other types are unchanged by the integer promotions.
И раз есть отличие от стандарта, то оно должно быть явно указано в документации (например, в документации на микрочиповский C18 такое описание есть). А если в документации оно не упомянуто, то, извините, или бага или этот компилятор не может называться "компилятором языка высокого уровня С"
WHALE
Цитата(DMD @ Apr 17 2008, 13:02) *
Обнаружил интересный глюк в CodeVision, целый день вчера просидел - думал во мне дело, оказалось, что нет.
Если мы делаем сдвиг и результирующее число выходит из размера 1 байта, то, почему-то, компилятор не преобразует его к int (хотя обязан по стандарту). То есть вот такой код работает непрявильно:
Код
unisigned char s = 243;
//...
unsigned int d = (unsigned int)(s << 4);  // d != 3888


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

it is important to note that if the Project|Configure|C Compiler|Code Generation|Promote char to int option isn't checked or the #pragma promotechar+ isn't used, the char, respectively unsigned char, type operands are not automatically promoted to int , respectively unsigned int, as in compilers targeted for 16 or 32 bit CPUs.
This helps writing more size and speed efficient code for an 8 bit CPU like the AVR.
To prevent overflow on 8 bit addition or multiplication, casting may be required.
The compiler issues warnings in these situations.

Варнинги то хоть генерились,или они подавлены?
prottoss
Цитата(Сергей Борщ @ Apr 17 2008, 18:20) *
"По-вашему" - вполне вероятно. Но по стандарту должно быть иначе:
И раз есть отличие от стандарта, то оно должно быть явно указано в документации (например, в документации на микрочиповский C18 такое описание есть). А если в документации оно не упомянуто, то, извините, или бага или этот компилятор не может называться "компилятором языка высокого уровня С"
Сорри, ошибся a14.gif
Andrew O. Shadoura
Цитата(Сергей Борщ @ Apr 17 2008, 14:20) *
или этот компилятор не может называться "компилятором языка высокого уровня С"

А он и так не является компилятором C. В C нет возможности писать вещи вроде PORTA.0=1, нет конструкции interrupt[wtf] и ещё много чего. Даже в C99.
Поэтому только avr-gcc.

--
WBR, Andrew
DMD
Ворнинги не генерились, что и странно. А насчет того, чтобы пользоваться опцией Project|Configure|C Compiler|Code Generation|Promote char to int - так это изврат, по-моему.
ReAl
Цитата(DMD @ Apr 17 2008, 12:02) *
Обнаружил интересный глюк в CodeVision, целый день вчера просидел - думал во мне дело, оказалось, что нет.

Уже обсуждалось. "Выбрось каку".
zhevak
Выбрось каку wink.gif

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

Сегодня приспичило меня поднять старые исходники, которые я еще писал в CodeVision в хз каком мохнатом году... Думал, закопипащщу (опять, гы-гы) текст в ИАР, подправлю где надо порты/регистры и вперед! Тема-то изъезженная вдоль и поперек -- подключение текстового LCD. Чего тут думать-то!? Ан, нет! Старые грабли с новыми ручкам...

Короче, IAR обнаружил ошибку на выходе из функции. Стыдно признаться, но это так, -- моя невнимательность. Но меня другое плющит -- Codevision эту ошибку в упор не видит. Пф-ф!

Вот код функции (слегка урезанный):
Код
//
//  Перевод кодировки Win-1251 в LDC-кодировку
//
BYTE _Translate(BYTE data)
{
  switch (data)
  {
  case 'Ё':
    return 0xA2;
  case 'ё':
...
  case '№':
    return 0xCC;
  case '\\':
    return 0xFF;
  }

  if (data >= 0xC0)
    return rus[data - 0xC0];
}


Для молодых поэтов поясняю -- собака порылась в последнем операторе if.

Вопрос: что будет, если data будет меньше 0xC0? Какой код вернет функция? Правльный выход из функции должен быть, разумеется, такой:
Код
...
  if (data >= 0xC0)
    return rus[data - 0xC0];
  else
    return data;
}


(Может кому пригодится. Хех!)
defunct
Цитата(Сергей Борщ @ Apr 17 2008, 11:17) *
Можно написать проще:
Код
unsigned int d = (unsigned int)s << 4;

Можно написать еще проще
Код
unsigned int d = s << 4;

зачем делать приведение типа в правой части, если в левой части и так unsigned int.

к тому же
Цитата
Все операнды типа unsigned char или unsigned short преобразуются в тип unsigned int.



Цитата(zhevak @ Dec 2 2008, 17:52) *
разумеется, такой:

Неочевидно, потому что ваш пример вообще неоткомилируется, неизвестно что такое rus smile.gif

Очень странно как вы использовали этот код и не наткнулись на проблему раньше, ведь 3/4 символов, в т.ч. и цифры, были недоступными!

По теме CV согласен - фтопку этот недоинструмент.
Сергей Борщ
Цитата(defunct @ Dec 3 2008, 02:15) *
Можно написать еще проще
Код
unsigned int d = s << 4;

зачем делать приведение типа в правой части, если в левой части и так unsigned int.
Если опустить integer promotion rules, которые CV не соблюдает, то в остальном в этом выражении он действует по стандарту: сначала вычисляется правая часть, потом ее результат приводится к левой части. То, что вы написали другими словами можно представить примерно так:
Цитата
Код
unsigned int s = 0x1234;
unsigned long d = s << 4;

зачем делать приведение типа в правой части, если в левой части и так unsigned long.


Цитата(zhevak @ Dec 2 2008, 17:52) *
Но меня другое плющит -- Codevision эту ошибку в упор не видит. Пф-ф!
gcc без -Wall тоже пропускает такое. В свое время тоже был удивлен, когда старые проекты, писаные в оболочке Dev-C++ стал собирать со своим рукописным makefile. Тоже решил тогда для себя "нафиг оболочку, теперь makefiles только руками".
А с -Wall gcc выдает не ошибку, а предупреждение.
Nick_Shl
Цитата(zhevak @ Dec 2 2008, 17:52) *
Вопрос: что будет, если data будет меньше 0xC0? Какой код вернет функция?
Все зависит от того, что вы выкинули заменив точечками в switch'e возможно за этот if управление даже не выйдет.
Кстати, насколько я припоминаю, у КодеВижена есть настройка какие варнинги выводить, а какие нет. Надо там глянуть не отключены ли.
delamoure
Цитата(ReAl @ Apr 18 2008, 16:50) *
Уже обсуждалось. "Выбрось каку".


Кака, конечно.
Но если бы в IAR C было также просто вставлять ассемблерный код в текс программы как это сделано в CvAVR... crying.gif
Сергей Борщ
Цитата(delamoure @ Dec 3 2008, 13:48) *
Но если бы в IAR C было также просто вставлять ассемблерный код в текс программы как это сделано в CvAVR... crying.gif
Тогда вам в gcc. Такого шикарного инлайн-асма в других компиляторах не встречалось. Вставленный код не мешает оптимизатору, компилятор сам решает, в каких регистрах удобнее передать параметры в ваш ассемблерный кусок... Конфетка! Не знаю как CV, но ИАР встретив в функции инлайн-асм складывает крылья и выключает оптимизатор (где-то в описании было).
_Pasha
Интересно, какие грабельки еще подкинет 16-битная недо-арифметика lol.gif
zhevak
Цитата
defunct[/b]' date='Dec 3 2008, 05:15' post='510351']
Неочевидно, потому что ваш пример вообще неоткомилируется, неизвестно что такое rus smile.gif (1)

Очень странно как вы использовали этот код и не наткнулись на проблему раньше, ведь 3/4 символов, в т.ч. и цифры, были недоступными! (2)

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

Ладно, попробую ответить на ваш вопрос. Начну с проблемы LCD, поскольку, у человека, который их ни разу не использовал возникают непонятки. У всех символьных LCD имеется встроенный знакогенератор (ну как минимум мне еще не попадались симольные LCD без оного). Младшая половина знакогенератора соответствует кодам ASCII. Проблемы заложены в старшей половине. Если у вас НЕ руссифицированный LCD, то, собственно, проблемы нет, т.к. в знакогенераторе кирилицы -- нет. Если LCD руссифицированный, то возникает проблема кодировки. Дело в том, что эта кодировка не совпадает ни с 866, ни с 1251. Я так понимаю, что производитель экономил память -- там, где изображение кириллических символов совпадает с изображением латинских символов, кириллические символы выкидывались. Например, кириллическая буква Р и латинская P, О и О, Н и Н, ну и т.д. Т.е. половина кириллического алфавита оказалась расположена в латинском. Понятно, что кодировка получилась весьма веселая.

С другой стороны, поскольку мы все пишем свои проги под Виндой, то стринги в исходниках тоже имеют виндовую кодировку. Теперь если прогу откомпилировать и залить в МК, то на LCD русские сообщения исказятся до неузнаваемости. Стало быть нужно произвести перекодировку. Это можно сделать либо до компиляции, либо во время исполнения проги в МК. Поскольку, объем флешь-памяти меня не напрягал, а вывод текстовой инфы на LCD занимает очень незначительное время, я решил незаморачиваться с перекодировкой до компиляции, а выполнять ее во время вывода строк. Тем более, что в проектах могут встретиться задачи, где стринг может прийти извне, например по RS232.

Соответственно во флешь-памяти МК располагалась таблица перекодировок. Имя этой таблицы -- rus. Функция перекодировки называлась translate.

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

2. Вопрос будет посложнее. Если честно, то ахренегознаеттоваришмайор! Я могу только предполагать, что это особенность CV. Т.е. переменная data и результат функции раполагались в одном и том же регистре. Иначе говоря, если "насильственной" перекодировки не происходило, то функция возвращала то, что получала в качестве аргумента.

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


2 Nick_Shl Я обычно поднимаю все флаги на ошибки и предупреждения.
defunct
zhevak
a14.gif за подробнейшие ответы.
SasaVitebsk
Цитата(Сергей Борщ @ Dec 3 2008, 17:35) *
Тогда вам в gcc. Такого шикарного инлайн-асма в других компиляторах не встречалось. Вставленный код не мешает оптимизатору, компилятор сам решает, в каких регистрах удобнее передать параметры в ваш ассемблерный кусок... Конфетка! Не знаю как CV, но ИАР встретив в функции инлайн-асм складывает крылья и выключает оптимизатор (где-то в описании было).

А я не испытал серьёзных неудобств с асмовыми вставками в IARе.
(Дальнейшее к Вам Сергей не относится, так как Вы всё это знаете лучше меня, это больше для delamoure и других, выбирающих инструмент)

Начнём с того, что IAR позволяет использовать inline ассемблер. В том числе и с многострочными конструкциями.
Во-вторых он позволяет писать на ассемблере законченные процедуры и подключать на этапе линковки. Это на мой взгляд намного правильнее и логичнее. Прога получается значительно нагляднее и завершённее. Использование регистров компилятором детально описано, и при таком варианте я не заметил ухудшения работы оптимизатора. (А inline ассемблер не применял, по причине вышеописанной)
Во втором варианте возможно использовать общие символические имена. Причём я работал со структурами, массивами, флагами именно с символьными именами.

Несколько напрягает в IARе перевод всех символьных имён в регистры и константы десятичные. И это перед выдачей листинга.
Ну например исходный текст
int i=1234;
В распечатке асмового листинга мы увидим что-то типа
ldi r26,210
ldi r27,4
Я бы предпочёл увидеть что-нибудь типа
ldi R26,low(1234)
ldi R27,high(1234)
Аналогично и с именами символическими. Хотя наверное это брюзжание. smile.gif
delamoure
Впрочем, IAR для меня не новость smile.gif
"Многострочные конструкции inline ассемблера" вызывают оторопь: "where \n (new line) separates each new assembler instruction". И это удобно?
На этапе линковки свой ассемблерный код не подключал. Коллега мне демонстрировал как это делается еще года 3 назад. Также способ описан в инете, по-моему, кем-то из местных (Сергеем Борщом?). Показалось неудобно, долго. Когда код писать? Тут целый обряд с бубном протанцевать необходимо.
Qwertty
Цитата(SasaVitebsk @ Dec 4 2008, 02:53) *
Во-вторых он позволяет писать на ассемблере законченные процедуры и подключать на этапе линковки. Это на мой взгляд намного правильнее и логичнее.

Это очень спорный момент. Ассемблерные вставки обычно делаются для повышения быстродействия. Использование написанных на ассемблере законченных процедур однозначно порушит стратегию оптимизатора и вместо выигрыша по времени можно получить проигрыш. Особенно если ассемблерная функция маленькая и быстрая. Тут может быть и большой оверхед - регистровые переменные в стек, рабочие копии обычных сохранить по "месту прописки". По выходу из ассемблерной функции все проделать в обратном порядке. А ведь бедный ИАР не знает, что в этой внешней процедуре происходит с регистрами, вот и сохранит по максимуму. У GCC видимо при такой методике включения S файлов должны быть похожие трудности. А вот инлайн ассемблер у GCC выше всяких похвал. Именно его использование и позволяет достичь максимального быстродействия - в этом случае накладных расходов или вообще нет, или они малы. А в отдельных файлах удобно обработчики прерываний делать.
Serj78
Цитата(_Pasha @ Dec 3 2008, 17:22) *
Интересно, какие грабельки еще подкинет 16-битная недо-арифметика lol.gif



А вот я уже привык smile.gif ибо влом перелопачивать старые проекты под gcc... CV всегда под рукой...
просто надо знать в каких случаях если справа у одного из операндов стоит младший тип и производится умножение/сложение/сдвиг что будет с результом ...
например умножать char на int некорректно, а наоборот- можно smile.gif
но вообще-то всегда варнинги генерятся их надо внимательно читать и все будет ок.
Сергей Борщ
Цитата(SasaVitebsk @ Dec 4 2008, 01:53) *
А я не испытал серьёзных неудобств с асмовыми вставками в IARе.
....
(А inline ассемблер не применял, по причине вышеописанной)
smile.gif "Асмовые вставки" == inline assembler. Они, как правильно заметил Qwertty, хороши именно тем, что не надо тратить время на сохранение регистров и вызов функции. При этом gcc позволяет в такой вставке сделать все, что угодно, а ИАР в документации честно пишет:
Цитата
Inline assembler sequences have no well-defined interface with the surrounding code generated from your C or C++ code. This makes the inline assembler code fragile, and will possibly also become a maintenance problem if you upgrade the compiler in the future.
...
Inline assembler is therefore often best avoided. If there is no suitable intrinsic function
available, we recommend the use of modules written in assembler language instead of inline assembler, because the function call to an assembler routine normally causes less performance reduction.
ARV
а как можно преобразовать строки для вывода на LCD на этапе компиляции? так, чтобы в исходном тексте они были в первозданном виде, а в объектном файле - уже перекодированные?
понимаю, что надо как-то влезть в последовательность работы препроцессора, но как?
Сергей Борщ
Цитата(ARV @ Dec 4 2008, 11:51) *
понимаю, что надо как-то влезть в последовательность работы препроцессора, но как?
Написать программу, которая из файла lcd.c делает _lcd.c перекодируя символы между одинарными и двойными кавычками. Компилятору скармливать _lcd.c. В случае gcc такая программа может выдавать результат в поток вывода а компилятор может принимать входные данные через поток ввода.
ARV
Цитата(Сергей Борщ @ Dec 4 2008, 13:16) *
Написать программу, которая из файла lcd.c делает _lcd.c перекодируя символы между одинарными и двойными кавычками. Компилятору скармливать _lcd.c. В случае gcc такая программа может выдавать результат в поток вывода а компилятор может принимать входные данные через поток ввода.

это очевидный способ, просто я почему-то думал, что существует более простой smile.gif типа макросов каких-нибудь или binutils готовых...
zhevak
Цитата(ARV @ Dec 4 2008, 14:51) *
а как можно преобразовать строки для вывода на LCD на этапе компиляции? так, чтобы в исходном тексте они были в первозданном виде, а в объектном файле - уже перекодированные?
понимаю, что надо как-то влезть в последовательность работы препроцессора, но как?

Я не совсем точно выразился. Имел ввиду, что у программы (в общем смыле) имеются несколько этапов жизни (или как это правильно сказать?). Этап разработки, написания теста, компиляция -- это все есть первый этап. Второй этап -- это, собственно, работа бинарного модуля в изделии, ран-тайм. Первый этап я условно назвал -- "на этапе компиляции". Что, видимо, и внесло путаницу в понимание.

На самом деле, вряд-ли кто осмелиться "отхачить" компилятор так чтобы тот "на этапе компиляции" (в буквальном смысле) конвертировал кодировку стрингов.

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

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

ЗЫ
1. Сергей Борщ немного раньше ответил.
2. Еще раз хочу напомнить, что стринги и символы могут приходить из внешнего мира. Т.е. задачу перекодировки удобнее решать на этапе ран-тайм, непосредственно в драйвере LCD. В этом случае вообще никаких проблем не будет. Единственная неудобство -- это незначительное снижение быстродействия при выводе и небольшое увеличение кода программы. Но поскольку, доля времени на перекодировку соизмерима или даже меньше, чем время на дергание лапок у LCD, а поток выводимой на LCD информации вообще никакой, то практически перекодировка в режиме ран-тайм не оказывает никакого торможения.
LordVader
Цитата(zhevak @ Dec 4 2008, 01:26) *
Если LCD руссифицированный, то возникает проблема кодировки. Дело в том, что эта кодировка не совпадает ни с 866, ни с 1251. Я так понимаю, что производитель экономил память -- там, где изображение кириллических символов совпадает с изображением латинских символов, кириллические символы выкидывались. Например, кириллическая буква Р и латинская P, О и О, Н и Н, ну и т.д. Т.е. половина кириллического алфавита оказалась расположена в латинском. Понятно, что кодировка получилась весьма веселая.

Существуют индикаторы с 1251 кодировкой (как одной из возможных). Делает фирма МЭЛТ.


Нажмите для просмотра прикрепленного файла
_Pasha
Цитата(ARV @ Dec 4 2008, 13:51) *
а как можно преобразовать строки для вывода на LCD на этапе компиляции?

utils/bin/sed.exe
Просто научиться готовить - yeah.gif
zhevak
Цитата(LordVader @ Dec 4 2008, 15:26) *
Существуют индикаторы с 1251 кодировкой (как одной из возможных). Делает фирма МЭЛТ.
Нажмите для просмотра прикрепленного файла

да. Спасибо.

Я вам больше скажу -- в мире существуют LCD с SPI интерфейсом... правда я их как-то не видел в продаже. Давайте сойдемся на том, что все это из разряда экзотики. В магазинах в основном продают LCD с "компактной" кодировкой и с традиционным интерфейсом.
LordVader
Цитата(zhevak @ Dec 4 2008, 13:47) *
Я вам больше скажу -- в мире существуют LCD с SPI интерфейсом... правда я их как-то не видел в продаже. Давайте сойдемся на том, что все это из разряда экзотики. В магазинах в основном продают LCD с "компактной" кодировкой и с традиционным интерфейсом.

Ну не знаю. В пределах 'глобуса москвы' купить мэлтовские - не проблема. И даже тут есть http://www.terraelectronica.ru/catalog.php...e=2&PageS=1
У них 2 странички кодировки - одна какая на картинке, другая непойми какая, видимо как раз та, о которой вы говорили. По дефолту включена она же.
zhevak
Цитата(LordVader @ Dec 4 2008, 23:22) *
Ну не знаю. В пределах 'глобуса москвы' купить мэлтовские - не проблема. И даже тут есть http://www.terraelectronica.ru/catalog.php...e=2&PageS=1
У них 2 странички кодировки - одна какая на картинке, другая непойми какая, видимо как раз та, о которой вы говорили. По дефолту включена она же.

все хорошо, но ведь не все живут в пределах Московского глобуса.

Имея большое желание получить себе на стол "экзотику", согласитесь, за ценой и временем можно не следить. Только почему-то в жизни часто получается так, что мы выбираем то, что легче достать, а потом это подгоняем напильниками. Мы рукастые, не ленивые, да и копейку умеем считать.
Поэтому вопрос бы и не возникал, если бы у нас были МЭЛТы в магазинах. А если еще по конкурентноспособной цене, да с кодировкой 1251 ... ха-ха-ха!

Есть реальная жизнь, и есть понятие "как надо жить". Это разные вещи, и очень часто они не совпадают. Поэтому, простите, живем, как умеем!

// Не обижайтесь! :-/ Это правда. (С) С легим паром!
SasaVitebsk
Стоимость LCD от 3.5$ за 2х16 до 11 за 4х20. Думаю экзотика в виде SPI LCD будет на 1$ дороже (За счёт экзотичности). Таким образом применив ATMega8, к примеру, и зашив там свою кодовую таблицу (Или несколько) вы можете получить за теже деньги LCD модуль с любым интерфейсом. SPI,I2C,RS232. Если туда добавить клаву, звук, светодиоды, то вообще такой законченный переферийный модуль будет себя оправдывать. Остаётся вопрос конструкции. smile.gif

По поводу ASM вставок.
Как то не совсем себе представляю ASM текст прямо по тексту Си программы. Если это работа с оборудованием, то как правило IAR её делает не хуже, а если просто прога, то смутно себе представляю. С другой стороны вызов законченной процедуры вполне уместен и не портит картину. Ну или там прерывание полностью на ASMе. Это я понимаю. Это как раз делается легко на IAR и просто.

Какие сложности? Просто берёшь и пишешь отдельным файлом все свои процедуры ASM. Никакого гимора нет. Ну и включаешь в проект общий, да и всё! Никаких дополнительных танцев с бубном не надо.
delamoure
Цитата(SasaVitebsk @ Dec 4 2008, 22:56) *
По поводу ASM вставок.
Как то не совсем себе представляю ASM текст прямо по тексту Си программы. Если это работа с оборудованием, то как правило IAR её делает не хуже, а если просто прога, то смутно себе представляю. С другой стороны вызов законченной процедуры вполне уместен и не портит картину. Ну или там прерывание полностью на ASMе. Это я понимаю. Это как раз делается легко на IAR и просто.

Какие сложности? Просто берёшь и пишешь отдельным файлом все свои процедуры ASM. Никакого гимора нет. Ну и включаешь в проект общий, да и всё! Никаких дополнительных танцев с бубном не надо.


Если действительно "прямо по тексту" я тоже смысла не вижу.
А обработчики прерываний пишу очень часто целиком на асме.
В CodeVision ставишь себе pragma savereg- и - вперед.
В IAR буду разбираться, пробовать. Настал момент смены компилятора. С переходом на CodeVision2 старые проекты без переработок не компилируются.
SasaVitebsk
Цитата(delamoure @ Dec 5 2008, 01:25) *
В CodeVision ставишь себе pragma savereg- и - вперед.
В IAR буду разбираться, пробовать. Настал момент смены компилятора. С переходом на CodeVision2 старые проекты без переработок не компилируются.

А в IAR и pragma никакая не нужна.
Просто создаёшь отдельный файл с расширением ASM, пишешь в нём свою прогу, с синтаксисом ASM, и подключаешь его к проекту.

Ключевые слова ассемблера IAR не критично отличаются от стандартного набора. Я бы даже сказал, что он "более стандартен", чем ассемблер AVR Studio. Есть доки. В том числе и дока по переходу со студии на IAR ASM. К слову сказать документ простой, так как различий практически нет. Если есть какие вопросы - задавай. Много кто ответит.

Вот попытался резануть кусочек для примера: smile.gif
Код
PUBLIC    crc8

#define        crc                r10
#define        data485            r16

        RSEG  CODE

// Расчёт CRC
// r10 - crc485, 16 - data, портятся r17,r18,r19
crc8:
        ldi        r17,8
//        mov        r12,data485
        ldi        r18,0x18
cCRC8:
        mov        r19,crc
        eor        r19,data485
        lsr        r19                                            // Сдвинули бит в С
        brcc    nCRC8
        eor        crc,r18
nCRC8:
        ror        crc
        lsr        data485
        dec        r17
        brne    cCRC8
        ret

END


Соответственно в Си проге я её могу вызвать следующим образом

Код
__regvar  __no_init uint8_t        crc @10;
....


    crc8(ADDR_DEFAULT);                                    // Подсчитать crc


Может это и не характерный пример. Дело в том, что это кусок вырезанный из бутлоадера для меги 8.
Для уменьшения размера кода пришлось запретить компилятору использовать несколько регистров (в том числе R10 как вы видите) и разместить там переменные, обращение к которым является найболее частым.

В результате в 2к влез бутлоадер с WakeUp протоколом с шифрованием 128 битным ключём. С выдачей полной информации по кристаллу, изделию, фирмваре и хардваре. Ну и некоторый другой сервис.

Пришлось дешифрацию и некоторые распространённые процедуры (типа crc) написать на ASM.
Очень доволен результатом.
Сергей Борщ
Цитата(SasaVitebsk @ Dec 4 2008, 22:56) *
По поводу ASM вставок.
Как то не совсем себе представляю ASM текст прямо по тексту Си программы.
Иногда бывает полезно:
Код
//Нету у arm-???-gcc intrinsic-функций для запрета/разрешения прерываний. Пишем inline-функцию доступа к регистру состояния процессора. Точно такие же intinsic-и намертво вшиты в ИАР для ARM :
INLINE inline TStatusReg __get_CPSR()
{
    TStatusReg cpsr;
    asm volatile
    (
    " MRS  %0,CPSR    \r\n"
    :"=r"(cpsr)
    :
    );
    return cpsr;
}
INLINE inline void __set_CPSR_c(TStatusReg cpsr)
{
    asm volatile
    (
    " MSR  CPSR_c, %0    \r\n"
    :
    :"r"(cpsr)
    );
}


// Загрузчик для msp430. Объем критичен. На С короче не получится:
inline uint16_t CRC_XMODEM(uint16_t crc, uint8_t byte)
{
    static const uint16_t CRC_POLYNOME = 0x8408;

    asm volatile(                  "\r\n"
    "   XOR     %1, %0              \r\n"
    "1:                             \r\n"
    "   RRA     %2                  \r\n"
    "   JNC     2f                  \r\n"
    "   XOR     %3, %2              \r\n"
    "2:                             \r\n"
    "   DEC     %4                  \r\n"
    "   JNE     1b                  \r\n"
    :"=r"(crc)
    :"r"(byte), "0"(crc), "i"((uint16_t)CRC_POLYNOME), "r"((uint8_t)8)
    );
/*
    crc ^= byte;
    uint8_t i = 8;
    do
    {
        if (crc & 0x01) { crc >>= 1; crc ^= CRC_POLYNOME; }
        else crc >>= 1;
    }
    while(--i);
*/
    return crc;
}

// Есть у меня в области загрузчика AVR функции, написанные на ИАРе. Они хотят параметр в R16. А gcc передает его в R24. Пишем обертку:
inline static void SynthInit(uint16_t FrequencyCoeff)
{
    register uint16_t Tmp asm("r16");
    Tmp = FrequencyCoeff;
    asm volatile (
    " .extern SynthInit_driver \n\t"
    "  RCALL  SynthInit_driver \n\t"
    :"=r" (Tmp)
    :"r" (Tmp)
    );
}
ReAl
Цитата(ARV @ Dec 4 2008, 12:19) *
это очевидный способ, просто я почему-то думал, что существует более простой smile.gif типа макросов каких-нибудь или binutils готовых...

pyLCDstring
by bialix aka Александр Бельченко
В проект включается файл messages.lcd и правило нужное в makefile - и жизнь прекрасна
Что-то в духе.

Код
PYLCD := c:/bin/pylcdstr/pylcdstr

%.c : %.lcd
    echo ====  Converting $< to source files; \
    $(PYLCD) $<

%.h : %.lcd
    echo ====  Converting $< to source files; \
    $(PYLCD) $<

messages.c : messages.lcd
messages.h : messages.lcd


Широкие возможности по управлению формированием выходных строк и перекодировоками.
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.