реклама на сайте
подробности

 
 
> Ошибка IAR или чтото еще?
Sergio66
сообщение Dec 18 2006, 12:47
Сообщение #1


Местный
***

Группа: Свой
Сообщений: 235
Регистрация: 9-02-05
Пользователь №: 2 526



Столкнулся со следующей проблемой:
Использую IAR 4.20А
В программе (в функции) перемножаю два числа типа long int. Одно из них - локальная временная переменная (для упрощения расчетов). Результат умножения получается неверным (просто бред!). АВР СТУДИО показывает, что компиллятор размещает временную переменную в регистрах.
Вылечил данную проблему тем, что правдами - неправдами добился того, чтобы компиллятор разместил данную переменную в памяти. Вот только тогда все и заработало.
Кто нибудь может прокомментировать этот случай?
Go to the top of the page
 
+Quote Post
5 страниц V   1 2 3 > »   
Start new topic
Ответов (1 - 71)
aesok
сообщение Dec 18 2006, 13:06
Сообщение #2


Знающий
****

Группа: Участник
Сообщений: 596
Регистрация: 26-05-06
Из: Москва
Пользователь №: 17 484



Показывайте код.
Go to the top of the page
 
+Quote Post
Sergio66
сообщение Dec 18 2006, 13:15
Сообщение #3


Местный
***

Группа: Свой
Сообщений: 235
Регистрация: 9-02-05
Пользователь №: 2 526



Цитата(aesok @ Dec 18 2006, 13:06) *
Показывайте код.


Вот такой код:
unsigned long int temp = INJ_time * data_temp_struct.FREQ * PRODUCTIVITY / 20000;
тип INJ_time - unsigned long int. Эта переменная локальная.
PRODUCTIVITY - константа
Так вот, переменная temp размещалась компилятором в регистрах и все было плохо

Теперь я переменную temp сделал членом локальной структуры data_temp_struct
Т.о. она стала размещаться в памяти а не в регистрах. Вот с этого все и заработало.
data_temp_struct.temp = INJ_time * data_temp_struct.FREQ * PRODUCTIVITY / 20000;
Go to the top of the page
 
+Quote Post
_Bill
сообщение Dec 18 2006, 14:48
Сообщение #4


Местный
***

Группа: Участник
Сообщений: 416
Регистрация: 18-04-06
Из: Челябинск
Пользователь №: 16 219



Цитата(Sergio66 @ Dec 18 2006, 13:15) *
Вот такой код:
unsigned long int temp = INJ_time * data_temp_struct.FREQ * PRODUCTIVITY / 20000;
тип INJ_time - unsigned long int. Эта переменная локальная.
PRODUCTIVITY - константа
Так вот, переменная temp размещалась компилятором в регистрах и все было плохо

Теперь я переменную temp сделал членом локальной структуры data_temp_struct
Т.о. она стала размещаться в памяти а не в регистрах. Вот с этого все и заработало.
data_temp_struct.temp = INJ_time * data_temp_struct.FREQ * PRODUCTIVITY / 20000;

Ну, так все правильно. Компилятор перед генерацией производит свертку констант, т.е. вычисляет значение PRODUCTIVITY / 20000. Естественно, оно будет вычисленно неточно. Поставьте в выражении скобки в нужных местах. Еще советую объявить константы как long, тогда погрешность в вычислении уменьшится.
Go to the top of the page
 
+Quote Post
Sergio66
сообщение Dec 18 2006, 15:01
Сообщение #5


Местный
***

Группа: Свой
Сообщений: 235
Регистрация: 9-02-05
Пользователь №: 2 526



Цитата(_Bill @ Dec 18 2006, 14:48) *
Цитата(Sergio66 @ Dec 18 2006, 13:15) *

Вот такой код:
unsigned long int temp = INJ_time * data_temp_struct.FREQ * PRODUCTIVITY / 20000;
тип INJ_time - unsigned long int. Эта переменная локальная.
PRODUCTIVITY - константа
Так вот, переменная temp размещалась компилятором в регистрах и все было плохо

Теперь я переменную temp сделал членом локальной структуры data_temp_struct
Т.о. она стала размещаться в памяти а не в регистрах. Вот с этого все и заработало.
data_temp_struct.temp = INJ_time * data_temp_struct.FREQ * PRODUCTIVITY / 20000;

Ну, так все правильно. Компилятор перед генерацией производит свертку констант, т.е. вычисляет значение PRODUCTIVITY / 20000. Естественно, оно будет вычисленно неточно. Поставьте в выражении скобки в нужных местах. Еще советую объявить константы как long, тогда погрешность в вычислении уменьшится.


А что, если переменная размещена не в регистрах, а в памяти, свертка констант не производится? Или это происходит как то иначе?
Я ведт ничего не поменял, просто добился иного размещения в памяти переменной!!! И никаких скобок.И без них все заработало. Нет! Дело не в этом!!!
Go to the top of the page
 
+Quote Post
aesok
сообщение Dec 18 2006, 15:18
Сообщение #6


Знающий
****

Группа: Участник
Сообщений: 596
Регистрация: 26-05-06
Из: Москва
Пользователь №: 17 484



Опишите проблемму полностью:

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


Анатлий.

Сообщение отредактировал aesok - Dec 18 2006, 15:23
Go to the top of the page
 
+Quote Post
Dog Pawlowa
сообщение Dec 18 2006, 15:28
Сообщение #7


Гуру
******

Группа: Свой
Сообщений: 2 702
Регистрация: 14-07-06
Пользователь №: 18 823



Цитата(Sergio66 @ Dec 18 2006, 15:01) *
А что, если переменная размещена не в регистрах, а в памяти, свертка констант не производится? Или это происходит как то иначе?
Я ведт ничего не поменял, просто добился иного размещения в памяти переменной!!! И никаких скобок.И без них все заработало. Нет! Дело не в этом!!!

Послушайте! :-)
Вам предлагают дело - записать формулу ПРАВИЛЬНО.
Разбираться в особенностях компилятора в случае неправильной записи - очень неблагодарное дело.
А еще можно начать разбираться в особенностях различных компиляторов. Путь в никуда.
Меня такие вещи давно не беспокоят - побольше скобок и преобразования типов.
И ффсе! smile.gif


--------------------
Уходя, оставьте свет...
Go to the top of the page
 
+Quote Post
Sergio66
сообщение Dec 18 2006, 15:44
Сообщение #8


Местный
***

Группа: Свой
Сообщений: 235
Регистрация: 9-02-05
Пользователь №: 2 526



Цитата(Dog Pawlowa @ Dec 18 2006, 15:28) *
Цитата(Sergio66 @ Dec 18 2006, 15:01) *

А что, если переменная размещена не в регистрах, а в памяти, свертка констант не производится? Или это происходит как то иначе?
Я ведт ничего не поменял, просто добился иного размещения в памяти переменной!!! И никаких скобок.И без них все заработало. Нет! Дело не в этом!!!

Послушайте! :-)
Вам предлагают дело - записать формулу ПРАВИЛЬНО.
Разбираться в особенностях компилятора в случае неправильной записи - очень неблагодарное дело.
А еще можно начать разбираться в особенностях различных компиляторов. Путь в никуда.
Меня такие вещи давно не беспокоят - побольше скобок и преобразования типов.
И ффсе! smile.gif

Скобки расставлял. Это ни к чему не привело. Проблема исчезла повторяю только после того, как переменная была размещена в памяти а не в регистрах!!!
Go to the top of the page
 
+Quote Post
prottoss
сообщение Dec 18 2006, 15:45
Сообщение #9


Гуру
******

Группа: Свой
Сообщений: 2 720
Регистрация: 24-03-05
Пользователь №: 3 659



Цитата(Dog Pawlowa @ Dec 18 2006, 19:28) *
Послушайте! :-)
Вам предлагают дело - записать формулу ПРАВИЛЬНО.
Разбираться в особенностях компилятора в случае неправильной записи - очень неблагодарное дело.
А еще можно начать разбираться в особенностях различных компиляторов. Путь в никуда.
Меня такие вещи давно не беспокоят - побольше скобок и преобразования типов.
И ффсе! smile.gif
Сказанно, если размещать переменную локально, не вычисляется, если глобально - вычислятся - при чем тут скобки???


--------------------
Go to the top of the page
 
+Quote Post
singlskv
сообщение Dec 18 2006, 16:11
Сообщение #10


дятел
*****

Группа: Свой
Сообщений: 1 681
Регистрация: 13-05-06
Из: Питер
Пользователь №: 17 065



Цитата(Sergio66 @ Dec 18 2006, 12:47) *
Столкнулся со следующей проблемой:
Использую IAR 4.20А
В программе (в функции) перемножаю два числа типа long int. Одно из них - локальная временная переменная (для упрощения расчетов). Результат умножения получается неверным (просто бред!). АВР СТУДИО показывает, что компиллятор размещает временную переменную в регистрах.
Вылечил данную проблему тем, что правдами - неправдами добился того, чтобы компиллятор разместил данную переменную в памяти. Вот только тогда все и заработало.
Кто нибудь может прокомментировать этот случай?

Если Вы смотрите на получаемое значение в окошке Watch AVR Studio, то тогда у Вас
все в порядке. Смотрите на результат в регистрах он там правильный.

AVR Studio НЕ гарантирует что локальные переменные соптимизированные компилятором
(хранящиеся в регистрах) будут правильно показываться в Watch.

А скобочки все-таки поставьте
конечно если у Вас PRODUCTIVITY / 20000 - целое, тады не надо smile.gif
Go to the top of the page
 
+Quote Post
Dog Pawlowa
сообщение Dec 18 2006, 16:46
Сообщение #11


Гуру
******

Группа: Свой
Сообщений: 2 702
Регистрация: 14-07-06
Пользователь №: 18 823



Цитата(prottoss @ Dec 18 2006, 15:45) *
Сказанно, если размещать переменную локально, не вычисляется, если глобально - вычислятся - при чем тут скобки???

1. Было сказано так "побольше скобок И ПРЕОБРАЗОВАНИЯ ТИПОВ".
2. Ообще-тоавтор он мог бы разместить здесь ассемблерный текст и гадание на гуще не состоялось бы.
2. Видел подобный случай - я работал под IAR, клиент стал компилировать под ICC. Результат усреднения значений АЦП считался по разному. Именно из-за особенностей работы компилятора в случае некорректного написания программы. И что? И ничего.


--------------------
Уходя, оставьте свет...
Go to the top of the page
 
+Quote Post
prottoss
сообщение Dec 18 2006, 17:08
Сообщение #12


Гуру
******

Группа: Свой
Сообщений: 2 720
Регистрация: 24-03-05
Пользователь №: 3 659



Цитата(Dog Pawlowa @ Dec 18 2006, 20:46) *
Цитата(prottoss @ Dec 18 2006, 15:45) *

Сказанно, если размещать переменную локально, не вычисляется, если глобально - вычислятся - при чем тут скобки???

1. Было сказано так "побольше скобок И ПРЕОБРАЗОВАНИЯ ТИПОВ".
Это было сказанно, вернее посоветованна, Вами, и товарищем aesok. Смысл же вопроса автора топика был именно в том, что сказал я - если размещать переменную локально, не вычисляется, если глобально - вычислятся , при чем здесь cкобки, позвольте? У меня, в данный момент, есть тоже подобный фокус в программе, которой сейчас занимаюсь. Если обсуждаемая сдесь проблема не решится, поделюсь своей...


--------------------
Go to the top of the page
 
+Quote Post
Oldring
сообщение Dec 18 2006, 17:27
Сообщение #13


Гуру
******

Группа: Свой
Сообщений: 3 041
Регистрация: 10-01-05
Из: Москва
Пользователь №: 1 874



Цитата(_Bill @ Dec 18 2006, 14:48) *
Ну, так все правильно. Компилятор перед генерацией производит свертку констант, т.е. вычисляет значение PRODUCTIVITY / 20000. Естественно, оно будет вычисленно неточно. Поставьте в выражении скобки в нужных местах. Еще советую объявить константы как long, тогда погрешность в вычислении уменьшится.


Не имеет права. Ассоциативность этих операций фиксирована - слева направа.

Нужно сравнивать листинг того, как получается неправильно, и того, как получается правильно. Иначе можно много фантазировать.

Цитата(Dog Pawlowa @ Dec 18 2006, 15:28) *
Вам предлагают дело - записать формулу ПРАВИЛЬНО.


Все записано правильно.

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


--------------------
Пишите в личку.
Go to the top of the page
 
+Quote Post
Dog Pawlowa
сообщение Dec 18 2006, 18:48
Сообщение #14


Гуру
******

Группа: Свой
Сообщений: 2 702
Регистрация: 14-07-06
Пользователь №: 18 823



Цитата(prottoss @ Dec 18 2006, 17:08) *
Цитата(Dog Pawlowa @ Dec 18 2006, 20:46) *
Цитата(prottoss @ Dec 18 2006, 15:45) *

Сказанно, если размещать переменную локально, не вычисляется, если глобально - вычислятся - при чем тут скобки???

1. Было сказано так "побольше скобок И ПРЕОБРАЗОВАНИЯ ТИПОВ".
Это было сказанно, вернее посоветованна, Вами, и товарищем aesok. Смысл же вопроса автора топика был именно в том, что сказал я - если размещать переменную локально, не вычисляется, если глобально - вычислятся , при чем здесь cкобки, позвольте? У меня, в данный момент, есть тоже подобный фокус в программе, которой сейчас занимаюсь. Если обсуждаемая сдесь проблема не решится, поделюсь своей...
Видимо, Вы не поняли смысла того, что хотел сказать я. wink.gif Если есть малейшая возможность, что компилятор "спровоцирован" некорректным текстом, то лучше эту возможность исключить.

Цитата(Oldring @ Dec 18 2006, 17:27) *
Цитата(Dog Pawlowa @ Dec 18 2006, 15:28) *

Вам предлагают дело - записать формулу ПРАВИЛЬНО.

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


--------------------
Уходя, оставьте свет...
Go to the top of the page
 
+Quote Post
Oldring
сообщение Dec 18 2006, 19:08
Сообщение #15


Гуру
******

Группа: Свой
Сообщений: 3 041
Регистрация: 10-01-05
Из: Москва
Пользователь №: 1 874



Цитата(Dog Pawlowa @ Dec 18 2006, 18:48) *
Тогда мы по разному понимает слово "правильно". Я включал в это понятие учет возможности переполнения и максимальной независимости от констант. А Вы - нет? smile.gif


Дело в том, что Билл написал просто чепуху про "естественную" свертку целочисленных констант перед вычислением выражения, а Вашего предложения я вообще почему-то не вижу в истории переписки. Так как так и не была озвучена информация про диапазоны операндов, хотелось бы все-таки увидеть, что именно Вы считаете "правильной" записью данного выражения, если это понятие "правильности" отличется от формальной правильности. Хотелось бы также узнать Ваше мнение по следующему вопросу: существует ли с точки зрения стандарта языка программирования С какая-либо разница между выражениями

Код
a * b * c / d


и

Код
((a * b) * c)  / d


?

И, кстати, считаете ли Вы что компилятор имеет право выражение

Код
a = b * 2 / 3;


заменить на

Код
a = 0;


?


--------------------
Пишите в личку.
Go to the top of the page
 
+Quote Post
singlskv
сообщение Dec 18 2006, 19:31
Сообщение #16


дятел
*****

Группа: Свой
Сообщений: 1 681
Регистрация: 13-05-06
Из: Питер
Пользователь №: 17 065



Цитата(Oldring @ Dec 18 2006, 19:08) *
Дело в том, что Билл написал просто чепуху про "естественную" свертку целочисленных констант перед вычислением выражения, а Вашего предложения я вообще почему-то не вижу в истории переписки. Так как так и не была озвучена информация про диапазоны операндов, хотелось бы все-таки увидеть, что именно Вы считаете "правильной" записью данного выражения, если это понятие "правильности" отличется от формальной правильности. Хотелось бы также узнать Ваше мнение по следующему вопросу: существует ли с точки зрения стандарта языка программирования С какая-либо разница между выражениями

Код
a * b * c / d


и

Код
((a * b) * c)  / d


?

Попробую с Вами не согласиться.
Предположим у нас есть такой код
Код
  tmp=a+153+b-35

позволим компилятору преобразовать это в
Код

tmp=a+118+b

?
или нет ?

Замечу что + и - имеет один уровень приоритета

* и / тоже один уровень
Go to the top of the page
 
+Quote Post
Oldring
сообщение Dec 18 2006, 19:38
Сообщение #17


Гуру
******

Группа: Свой
Сообщений: 3 041
Регистрация: 10-01-05
Из: Москва
Пользователь №: 1 874



Ответ прост. До тех пор, пока результат вычисления всего целочисленного выражения не отличается от стандартного способа вычисления с учетом того, что при переполнении промежуточных результатов возможно undefined поведение, компилятор может делать все, что угодно. Но только пока не отличается. Более того, важен даже не результат вычисления одного выражения, а последовательность записи значений в volatile переменные и вызовов системных функций. Все оптимизации программы, которые сохраняют запись в volatile переменные и ызовы системных функций - законные, все, которые приводят к изменению внешнего поведения программы - незаконны.


--------------------
Пишите в личку.
Go to the top of the page
 
+Quote Post
singlskv
сообщение Dec 18 2006, 19:53
Сообщение #18


дятел
*****

Группа: Свой
Сообщений: 1 681
Регистрация: 13-05-06
Из: Питер
Пользователь №: 17 065



Цитата(Oldring @ Dec 18 2006, 19:38) *
Ответ прост. До тех пор, пока результат вычисления всего целочисленного выражения не отличается от стандартного способа вычисления с учетом того, что при переполнении промежуточных результатов возможно undefined поведение, компилятор может делать все, что угодно. Но только пока не отличается. Более того, важен даже не результат вычисления одного выражения, а последовательность записи значений в volatile переменные и вызовов системных функций. Все оптимизации программы, которые сохраняют запись в volatile переменные и ызовы системных функций - законные, все, которые приводят к изменению внешнего поведения программы - незаконны.

Наверное все-таки так:
- если мы отключаем оптимизацию полностью
- если мы отключаем все расширения компилятора отличные от стандарта
- если мы все переменные объявляем как volatile
то тогда да, компилятор обязан сделать все как ему написали.

А вот если мы все выше перечисленное включили, то
Добро пожаловать в Manual для выяснения всех подробностей как и что
себе думает компилятор при оптимизации (если конечно авторы не забыли это указать smile.gif )
Go to the top of the page
 
+Quote Post
Oldring
сообщение Dec 18 2006, 20:08
Сообщение #19


Гуру
******

Группа: Свой
Сообщений: 3 041
Регистрация: 10-01-05
Из: Москва
Пользователь №: 1 874



Не совсем.

1. Включение оптимизации самой по себе не отменяет требования соблюдения компилятором стандарта языка.
2. Расширения компилятора учитывать стоит - но их обычно немного и они описаны в описании компилятора. Расширения для 8-битников могут затрагивать аривметику с 8-битными числами - не расширять до int например - но я в первый раз слышу чтобы расширения затрагивали вычисления unsigned long.
3. Нет. Компилятор обязан сделать чтобы снаружи выглядело как ему написали в любом случае.


--------------------
Пишите в личку.
Go to the top of the page
 
+Quote Post
Dog Pawlowa
сообщение Dec 18 2006, 20:31
Сообщение #20


Гуру
******

Группа: Свой
Сообщений: 2 702
Регистрация: 14-07-06
Пользователь №: 18 823



Цитата(Oldring @ Dec 18 2006, 19:38) *
Ответ прост. До тех пор, пока результат вычисления всего целочисленного выражения не отличается от стандартного способа вычисления с учетом того, что при переполнении промежуточных результатов возможно undefined поведение, компилятор может делать все, что угодно. Но только пока не отличается. Более того, важен даже не результат вычисления одного выражения, а последовательность записи значений в volatile переменные и вызовов системных функций. Все оптимизации программы, которые сохраняют запись в volatile переменные и ызовы системных функций - законные, все, которые приводят к изменению внешнего поведения программы - незаконны.

Меня "правильность" компилятора мало интересует, я не д-р Туамосец.
Я рассматриваю правильность как максимально близкий результат к результату при перемножении в столбик smile.gif
И получается такая незадача, что правильность зависит от значения переменных.
int a,b,c;
a*b/c при a=100, b=100, c=3 правильно будет (a*cool.gif/c,
а при a=1000, b=1000, c=100 правильно будет a*(b/c).
Поэтому весь этот дискуссион не имеет смысла, тем более что автор не указал даже с какими числами он работал и предусмотрен ли запас по диапазону. Потому и залег на дно, видимо, предоставив нам возможность друг друга за чубы тягать smile.gif




Цитата(Oldring @ Dec 18 2006, 20:08) *
3. Нет. Компилятор обязан сделать чтобы снаружи выглядело как ему написали в любом случае.

Хм... Например, оптимизатор IAR самостоятельно заменяет switch (a) {case ....} на vector[a] и создает массив функций при большом числе a.
Такое решение выглядит, как написали, или не выглядит?


--------------------
Уходя, оставьте свет...
Go to the top of the page
 
+Quote Post
Oldring
сообщение Dec 18 2006, 20:37
Сообщение #21


Гуру
******

Группа: Свой
Сообщений: 3 041
Регистрация: 10-01-05
Из: Москва
Пользователь №: 1 874



Цитата(Dog Pawlowa @ Dec 18 2006, 20:23) *
Меня "правильность" компилятора мало интересует, я не д-р Туамосец.


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


Цитата(Dog Pawlowa @ Dec 18 2006, 20:31) *
Хм... Например, оптимизатор IAR самостоятельно заменяет switch (a) {case ....} на vector[a] и создает массив функций при большом числе a.
Такое решение выглядит, как написали, или не выглядит?


Раз такое преобразование не изменяет порядок вызова системных функций и обращений к volatile переменным - это совершенно законное преобразование программы.


--------------------
Пишите в личку.
Go to the top of the page
 
+Quote Post
prottoss
сообщение Dec 18 2006, 20:43
Сообщение #22


Гуру
******

Группа: Свой
Сообщений: 2 720
Регистрация: 24-03-05
Пользователь №: 3 659



Цитата(Dog Pawlowa @ Dec 19 2006, 00:31) *
И получается такая незадача, что правильность зависит от значения переменных.
int a,b,c;
a*b/c при a=100, b=100, c=3 правильно будет (a* cool.gif /c,
а при a=1000, b=1000, c=100 правильно будет a*(b/c).
Поэтому весь этот дискуссион не имеет смысла, тем более что автор не указал даже с какими числами он работал и предусмотрен ли запас по диапазону. Потому и залег на дно, видимо, предоставив нам возможность друг друга за чубы тягать smile.gif
Вы специально со скобками дуру гоните, али как? Выражаясь Вашими формулами вопрос задаем так - ПОЧЕМУ:



Global_Value = a * b / c отличается от Local_Value = a * b / c;



Скобки и привидения к типам в обоих равенствах можете расставить по собственному усмотрению и вкусу, НО одинаково



Цитата(Dog Pawlowa @ Dec 19 2006, 00:31) *
Цитата(Oldring @ Dec 18 2006, 20:08) *

3. Нет. Компилятор обязан сделать чтобы снаружи выглядело как ему написали в любом случае.

Хм... Например, оптимизатор IAR самостоятельно заменяет switch (a) {case ....} на vector[a] и создает массив функций при большом числе a.
Такое решение выглядит, как написали, или не выглядит?
Как раз подходит под то, что говорит Oldring - снаружи функции и со switch (a) {case ....} и с vector[a] будет выглядеть одинаково, здесь же мы наблюдаем "не одинаково"


--------------------
Go to the top of the page
 
+Quote Post
Oldring
сообщение Dec 18 2006, 21:14
Сообщение #23


Гуру
******

Группа: Свой
Сообщений: 3 041
Регистрация: 10-01-05
Из: Москва
Пользователь №: 1 874



Цитата(prottoss @ Dec 18 2006, 20:43) *
Выражаясь Вашими формулами вопрос задаем так - ПОЧЕМУ:



Global_Value = a * b / c отличается от Local_Value = a * b / c;



Скобки и привидения к типам в обоих равенствах можете расставить по собственному усмотрению и вкусу, НО одинаково


Да все что угодно может быть. Например из-за переполнения при вычислении выражения поведение оказалось неопределенным. Или результат используется каким-то специальным образом, компилятор это заметил - и соптимизировал. Листинг нужно смотреть, что там получается реально.


--------------------
Пишите в личку.
Go to the top of the page
 
+Quote Post
singlskv
сообщение Dec 18 2006, 21:18
Сообщение #24


дятел
*****

Группа: Свой
Сообщений: 1 681
Регистрация: 13-05-06
Из: Питер
Пользователь №: 17 065



Цитата(prottoss @ Dec 18 2006, 20:43) *
Выражаясь Вашими формулами вопрос задаем так - ПОЧЕМУ:

Global_Value = a * b / c отличается от Local_Value = a * b / c;

Автор топика так и не сказал, эта ошибка в "железе" или в симуляторе AVR Studio
Если в AVR Studio по Watch, то тогда надо пробовать так:
Global_Value1 = a * b / c;
Local_Value = a * b / c;
Global_Value2 = Local_Value;

и вот если не совпадут Global_Value1 и Global_Value2 то, тогда да, проблемма компиляции,
а если совпадут, то тогда все в порядке, оптимизатор поработал blink.gif
Go to the top of the page
 
+Quote Post
Dog Pawlowa
сообщение Dec 19 2006, 09:49
Сообщение #25


Гуру
******

Группа: Свой
Сообщений: 2 702
Регистрация: 14-07-06
Пользователь №: 18 823



Цитата(prottoss @ Dec 18 2006, 20:43) *
Вы специально со скобками дуру гоните, али как? Выражаясь Вашими формулами вопрос задаем так - ПОЧЕМУ:
Global_Value = a * b / c отличается от Local_Value = a * b / c;
Скобки и привидения к типам в обоих равенствах можете расставить по собственному усмотрению и вкусу, НО одинаково

Дуру? Отчасти smile.gif
А на конкретный вопрос - конкретный ответ :

Да, сравнивать Global_Value = a * b / c и Local_Value = a * b / c при int a,b,c считаю некорректным.

Но можно сравнивать Global_Value = a * (b / c) и Local_Value = a *( b / c)
Или Global_Value = (long) a * (long) b / c и Local_Value = (long)a *(long) b / c, а еще лучше
Global_Value = ((long) a * (long) b ) / c и Local_Value = ((long)a *(long) b ) / c
И только после этого может появиться предположение об "ошибке".
У меня один и тот же проект постоянно портируется с MS VC на IAR AVR и обратно, да, было пару выбрыков у ИАРа, но в целом это вполне нормальный инструмент. За приемлемую цену wink.gif

Все, пока автор не появится - ни строчки.

Сообщение отредактировал Dog Pawlowa - Dec 19 2006, 09:54


--------------------
Уходя, оставьте свет...
Go to the top of the page
 
+Quote Post
Sergio66
сообщение Dec 19 2006, 11:57
Сообщение #26


Местный
***

Группа: Свой
Сообщений: 235
Регистрация: 9-02-05
Пользователь №: 2 526



[/quote]
Дуру? Отчасти smile.gif
А на конкретный вопрос - конкретный ответ :

Да, сравнивать Global_Value = a * b / c и Local_Value = a * b / c при int a,b,c считаю некорректным.

Но можно сравнивать Global_Value = a * (b / c) и Local_Value = a *( b / c)
Или Global_Value = (long) a * (long) b / c и Local_Value = (long)a *(long) b / c, а еще лучше
Global_Value = ((long) a * (long) b ) / c и Local_Value = ((long)a *(long) b ) / c
И только после этого может появиться предположение об "ошибке".
У меня один и тот же проект постоянно портируется с MS VC на IAR AVR и обратно, да, было пару выбрыков у ИАРа, но в целом это вполне нормальный инструмент. За приемлемую цену wink.gif

Все, пока автор не появится - ни строчки.
[/quote]

Вот и автор.
Итак, что касается значения переменных. В приведенном случае:
data_temp_struct.temp = INJ_time * data_temp_struct.FREQ * PRODUCTIVITY / 20000;
long int INJ_time = от 74 000 до 75 000
unsigned int data_temp_struct.FREQ = 1000 (задается в процессе эксперимента)
PRODUCTIVITY = 5 (в данном случае)
long int Local_Value temp = INJ_time * data_temp_struct.FREQ * PRODUCTIVITY / 20000;
где long int Local_Value размещена в регистрах
в результате дает непонятное случайное число
заменив переменную temp на data_temp_struct.temp я добился того, что она теперь размещена в памяти. При этом все вычисления пошли верно.
Теперь о свертывании констант - как вы можете видеть, PRODUCTIVITY (=5)/ 20000 корректно никак свернуто быть не может (при данных значениях)

Был проделан сл эксперимент - формула была упрощена до вида:
long int Local_Value temp = INJ_time * PRODUCTIVITY;
И только...
Результат был неверным! Только размещение в памяти результирующей переменной дало эффект!!!
Т.о. у меня есть 2 подозрения -
1. глюк компиллятора
2. Коллизия с распределением памяти. Возможно стек возвратов, возможно стек данных.
Многие глюки у меня решались именно изменением этих параметров. Правда, в данном случае мне не удалось подобрать ничего правильного.
Дело в том, что проект очень большой порядка 10 000 строк. Большой расход памяти, задействованы почти все мыслимые и немыслимые аппаратные ресурсы и прерывания.
Возможно, компиллятор столкнулся с какими то внутренними проблемами при обработке такого сложного проекта.
Кстати, оптимизацию я полностью отключал. На это грешить не приходится.

Вот такие дела!
Go to the top of the page
 
+Quote Post
GDI
сообщение Dec 19 2006, 13:32
Сообщение #27


Профессионал
*****

Группа: Свой
Сообщений: 1 235
Регистрация: 14-05-05
Из: Санкт-Петербург
Пользователь №: 5 008



Была у меня похожая проблема, правда, у меня портилась переменная типа char, которая была счетчиком внутри функции, при пошаговом выполнении программы в АВР-Студио выяснилось, что эта переменная размешена в регистре и при вызове вложенной подпрограммы этот регистр портился внутри этой подпрограммы, соответственно при возврате из подпрограммы мой счетчик приобретал не правильное значение.. в моем случае проблема была решена путем объявления переменной как static char, после этого она была размещена в памяти данных, а не в регистре и проблемы больше не возникало.


--------------------
http://www.embedders.org Блоги разработчиков электроники.
Go to the top of the page
 
+Quote Post
Oldring
сообщение Dec 19 2006, 14:44
Сообщение #28


Гуру
******

Группа: Свой
Сообщений: 3 041
Регистрация: 10-01-05
Из: Москва
Пользователь №: 1 874



Цитата(Sergio66 @ Dec 19 2006, 11:57) *
Результат был неверным! Только размещение в памяти результирующей переменной дало эффект!!!


Так сразу после вычисленя выражения в регистрах результат правильный?

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


--------------------
Пишите в личку.
Go to the top of the page
 
+Quote Post
Sergio66
сообщение Dec 19 2006, 15:15
Сообщение #29


Местный
***

Группа: Свой
Сообщений: 235
Регистрация: 9-02-05
Пользователь №: 2 526



Цитата(Oldring @ Dec 19 2006, 15:44) *
Цитата(Sergio66 @ Dec 19 2006, 11:57) *

Результат был неверным! Только размещение в памяти результирующей переменной дало эффект!!!


Так сразу после вычисленя выражения в регистрах результат правильный?

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


Да нет же! Пока я не переразместил переменную, все считалось неверно. И в регистрах был неверный результат.
Go to the top of the page
 
+Quote Post
Dog Pawlowa
сообщение Dec 19 2006, 19:10
Сообщение #30


Гуру
******

Группа: Свой
Сообщений: 2 702
Регистрация: 14-07-06
Пользователь №: 18 823



Цитата(Sergio66 @ Dec 19 2006, 15:15) *
Да нет же! Пока я не переразместил переменную, все считалось неверно. И в регистрах был неверный результат.

Тот самый случай, когда лучше один раз увидеть, чем сто раз услышать.
А еще лучше совсем не видеть :-)
Я вот недавно буфер для sprintf малый сделал, и пол-дня искал причину затирания переменной, все ошибки в компиляторе искал и стек считал...
Нет? biggrin.gif


--------------------
Уходя, оставьте свет...
Go to the top of the page
 
+Quote Post
singlskv
сообщение Dec 19 2006, 19:18
Сообщение #31


дятел
*****

Группа: Свой
Сообщений: 1 681
Регистрация: 13-05-06
Из: Питер
Пользователь №: 17 065



автар
продемонстрируйте свое искуство, так сказать в "малой форме"
Напишите и выложите сюда тестовый исходник и что получаеться в дизассемблере
попробуем разобраться ...
Go to the top of the page
 
+Quote Post
Dog Pawlowa
сообщение Dec 19 2006, 19:24
Сообщение #32


Гуру
******

Группа: Свой
Сообщений: 2 702
Регистрация: 14-07-06
Пользователь №: 18 823



Цитата(Sergio66 @ Dec 19 2006, 11:57) *
Был проделан сл эксперимент - формула была упрощена до вида:
long int Local_Value temp = INJ_time * PRODUCTIVITY;
И только...
Результат был неверным! Только размещение в памяти результирующей переменной дало эффект!!!

А говорит ANSI в этом случае? long= long * int.


--------------------
Уходя, оставьте свет...
Go to the top of the page
 
+Quote Post
Oldring
сообщение Dec 19 2006, 19:50
Сообщение #33


Гуру
******

Группа: Свой
Сообщений: 3 041
Регистрация: 10-01-05
Из: Москва
Пользователь №: 1 874



int расширяется до long до умножения. Потом должна вызываться стандартная библиотеченая функция перемножения длинных целых. Потом код самой функции должен скопировать результат из регистров в глобальную переменную. Или не скопировать. Моя уверенность, что это проблема не рассчета, а интерпретации результата, укрепляется. Пожалуй, автору пора научиться разбираться в листингах, порождаемых компилятором.


--------------------
Пишите в личку.
Go to the top of the page
 
+Quote Post
Sergio66
сообщение Dec 20 2006, 13:33
Сообщение #34


Местный
***

Группа: Свой
Сообщений: 235
Регистрация: 9-02-05
Пользователь №: 2 526



Цитата(Oldring @ Dec 19 2006, 19:50) *
int расширяется до long до умножения. Потом должна вызываться стандартная библиотеченая функция перемножения длинных целых. Потом код самой функции должен скопировать результат из регистров в глобальную переменную. Или не скопировать. Моя уверенность, что это проблема не рассчета, а интерпретации результата, укрепляется. Пожалуй, автору пора научиться разбираться в листингах, порождаемых компилятором.

1. Для тех кто умеет разбираться в листингах - подскажите пожалуйста, как правильно интерпретировать неправильный результат? Если в результате вычислений у меня получается неверное значение, оно же выводится на дисплей, мне придется объяснить пользователям как правильно интерпретировать такой результат который должен быть в пределах от 0,7 до 20, а его зашкаливает за 50 000!!!
2. К сожалению, я не могу выложить всеь код, т.к. это больше 10 000 строк. Одно могу сказать, что данный блок вычислений работал нормально, пока вычисления производились с глобальной переменной. Потом, для экономии памяти я сделал вычисления с локальной. Вот тут то все и началось. Когда компиллятор поместил эту локальную переменную в регистры. Как только я заставил разместить ее в памяти, все заработало.
Go to the top of the page
 
+Quote Post
Oldring
сообщение Dec 20 2006, 14:13
Сообщение #35


Гуру
******

Группа: Свой
Сообщений: 3 041
Регистрация: 10-01-05
Из: Москва
Пользователь №: 1 874



Цитата(Sergio66 @ Dec 20 2006, 13:33) *
1. Для тех кто умеет разбираться в листингах - подскажите пожалуйста, как правильно интерпретировать неправильный результат? Если в результате вычислений у меня получается неверное значение, оно же выводится на дисплей, мне придется объяснить пользователям как правильно интерпретировать такой результат который должен быть в пределах от 0,7 до 20, а его зашкаливает за 50 000!!!


Как какую-то Вашу собственную ошибку, например.

В настройках проекта для ICCAVR включаете на странице List опцию Output list File и отмечаете дополнительные пункты. Компилируете. В листинге находите сбойную функцию, вырезаете кусок текста и публикуете в двух вариантах. Что можно не уметь?


--------------------
Пишите в личку.
Go to the top of the page
 
+Quote Post
_Bill
сообщение Dec 20 2006, 15:06
Сообщение #36


Местный
***

Группа: Участник
Сообщений: 416
Регистрация: 18-04-06
Из: Челябинск
Пользователь №: 16 219



Цитата(Oldring @ Dec 18 2006, 19:08) *
Цитата(Dog Pawlowa @ Dec 18 2006, 18:48) *

Тогда мы по разному понимает слово "правильно". Я включал в это понятие учет возможности переполнения и максимальной независимости от констант. А Вы - нет? smile.gif


Дело в том, что Билл написал просто чепуху про "естественную" свертку целочисленных констант перед вычислением выражения, а Вашего предложения я вообще почему-то не вижу в истории переписки. Так как так и не была озвучена информация про диапазоны операндов, хотелось бы все-таки увидеть, что именно Вы считаете "правильной" записью данного выражения, если это понятие "правильности" отличется от формальной правильности. Хотелось бы также узнать Ваше мнение по следующему вопросу: существует ли с точки зрения стандарта языка программирования С какая-либо разница между выражениями

Код
a * b * c / d


и

Код
((a * b) * c)  / d


?

И, кстати, считаете ли Вы что компилятор имеет право выражение

Код
a = b * 2 / 3;


заменить на

Код
a = 0;


?

Ну, я не думаю, что я написал чепуху. Дело в том, что операция умножения коммутативная операция, а операции умножения и деления имеют одинаковый уровень приоритета. Если взять Ваш пример, то в общем случае совершенно не важно в каком порядке производить вычисления, результат будет один и тот же. То есть
Код
b * c * d / e = (b * c * d) / e = b * c * (d / e)
Проблема возникает именно потому, что появляются типы данных. Компилятор всегда производит перегруппировку выражения таким образом, чтобы код, вычисляющий данное выражения, был минимальным. Если в выражении имеются константы, то компилятор непременно выполнит все возможные вычисления с константами в соответствии с правилами арифметики. По умолчанию все константы имеют тип int, и если их тип не указан особо, то результат также будет иметь тип int. Естественно, что результат вычисления константного выражения может быть неверным, если программист специально об этом не позаботится. В данном случае, операнды d и e будут целыми константами и компилятор обязательно вычислит результат d/e, хотя он в общем случае будет некорректным.
Если мы хотим получить корректный результат, то мы должны задать требуемый порядок вычислений явным образом с помощью скобок. Можно также изменить тип констант по умочанию с использованием соответствующих суффиксов.
Go to the top of the page
 
+Quote Post
Guest_Serg79_*
сообщение Dec 20 2006, 15:22
Сообщение #37





Guests






Sergio66 Ты сдесь воду то не баламуть а приведи нормальный пример своей функции которая у тебя не правельно считает. Что то типа токого:
Код
int my_bad_func(int a, int b, int c)
{
    return a * b / c;
}

А то несешь какую то ахинею типа:
Цитата
Вот такой код:
unsigned long int temp = INJ_time * data_temp_struct.FREQ * PRODUCTIVITY / 20000;
тип INJ_time - unsigned long int. Эта переменная локальная.
PRODUCTIVITY - константа
Так вот, переменная temp размещалась компилятором в регистрах и все было плохо

Теперь я переменную temp сделал членом локальной структуры data_temp_struct
Т.о. она стала размещаться в памяти а не в регистрах. Вот с этого все и заработало.
data_temp_struct.temp = INJ_time * data_temp_struct.FREQ * PRODUCTIVITY / 20000;

Если нашел ошибку то локалезуй ее. И напиши маленькую функцию которая позваляет ее воспроизвести.

А разговоры типа: в регистре не правильно а в памяти правельно, бред сивой кабылы.
Может у Тебя там полнейший бред написан, а Ты пытаешся все на компилятор свалить.
Go to the top of the page
 
+Quote Post
prottoss
сообщение Dec 20 2006, 16:15
Сообщение #38


Гуру
******

Группа: Свой
Сообщений: 2 720
Регистрация: 24-03-05
Пользователь №: 3 659



Пока Sergio66 молчит, задам я свой вопрос, потому как проблема аналогичная. Имеем вот такой код:
Код
.....................

/* время возникновения импульса */
typedef struct
{
   UINT32 Time;  /* время возникновения импульса  */
   UCHAR TIFR_reg; /* сохраненные значения регистра флагов TIFR */

} Pulse_Time_t;
...................................

/*****************************************************************************
Коррекция значения времени
Корректирует время в зависимости от значения TIFR и младшего слова (ТС1)
******************************************************************************/
UINT32 PULSE_SENS_CorrectTime(Pulse_Time_t *Pulse)
{
UINT32 time = Pulse->Time;
  
   /* корректируем результат по состоянию флага OCF1A
    на момент считывания значений времени */
    if(Pulse->TIFR_reg & (1 << OCF1A))
    {
       time += 0x00010000; /* если флаг установлен, инкрементируем значение милисекунд */
       if(SYSTIMER_COMPARE_VAL == LOWORD(time))
        
           /* если значение счетчика равно константе в регистре сравнения, то мы это
           значение должны обнулить */
           time &= 0xffff0000;
    }

    /* преобразуем в мкс (закомментированный код НЕ РАБОТАЕТ )*/
    /* Pulse->Time = ((UINT32)(LOWORD(time) >> 1) + (UINT32)(HIWORD(time)) * 1000); return 0; */
    

    

    return ((UINT32)(LOWORD(time) >> 1) + (UINT32)(HIWORD(time)) * 1000);
}


Кто нибудь может объяснить, почему, когда я возвращаю результат преобразования в микросекунды в структуру Pulse_Time_t, результат в итоге НЕ правильный. Если возвращаю результа из функции - результат Правильный???



2 Serg79 - научитесь изъясняться по-русски, а то Ваше чревовещание больше всего подходит под термин "Бред сивой кобылы" как по грамматическим ошибкам, так и по смыслу…

Бесплатный совет – пишите сообщения сначала в
MS Word – по крайней мере, можно будет подумать, что Вы учили чего-то в школе хотя бы с соседом по парте, а свой букварь курили дома…


--------------------
Go to the top of the page
 
+Quote Post
Oldring
сообщение Dec 20 2006, 16:30
Сообщение #39


Гуру
******

Группа: Свой
Сообщений: 3 041
Регистрация: 10-01-05
Из: Москва
Пользователь №: 1 874



Цитата(_Bill @ Dec 20 2006, 15:06) *
Код
b * c * d / e = (b * c * d) / e = b * c * (d / e)
Естественно, что результат вычисления константного выражения может быть неверным, если программист специально об этом не позаботится. В данном случае, операнды d и e будут целыми константами и компилятор обязательно вычислит результат d/e, хотя он в общем случае будет некорректным.


Чушь. Домыслы.

P.S. Хотел приложить текст стандарта - почему-то не добавился...

Цитата(prottoss @ Dec 20 2006, 16:15) *
НЕ правильный.

Бесплатный совет – пишите сообщения сначала в [/b]MS Word – по крайней мере, можно будет подумать, что Вы учили чего-то в школе хотя бы с соседом по парте, а свой букварь курили дома…


wink.gif


--------------------
Пишите в личку.
Go to the top of the page
 
+Quote Post
prottoss
сообщение Dec 20 2006, 17:32
Сообщение #40


Гуру
******

Группа: Свой
Сообщений: 2 720
Регистрация: 24-03-05
Пользователь №: 3 659



Мда... Умные речи о значимости скобок не помогли...
Финал - стоны зрителей, аншлаг, занавес закрывается


--------------------
Go to the top of the page
 
+Quote Post
Dog Pawlowa
сообщение Dec 20 2006, 17:54
Сообщение #41


Гуру
******

Группа: Свой
Сообщений: 2 702
Регистрация: 14-07-06
Пользователь №: 18 823



Цитата(prottoss @ Dec 20 2006, 17:32) *
Мда... Умные речи о значимости скобок не помогли...
Финал - стоны зрителей, аншлаг, занавес закрывается

Уличили tongue.gif
А дизассемблер привести сложно? Или мы должны все бросить и посвятить вечер изучению ?
Сами то смотрели?


--------------------
Уходя, оставьте свет...
Go to the top of the page
 
+Quote Post
prottoss
сообщение Dec 20 2006, 18:05
Сообщение #42


Гуру
******

Группа: Свой
Сообщений: 2 720
Регистрация: 24-03-05
Пользователь №: 3 659



Цитата(Dog Pawlowa @ Dec 20 2006, 21:54) *
А дизассемблер привести сложно? Или мы должны все бросить и посвятить вечер изучению ? Сами то смотрели?
Я смотрел, и не раз, пожалуйста, c чуйством глубокохо удовлетворения привожу листинг, смотрите:

Код
218          /*****************************************************************************
    219          Коррекция значения времени
    220          Корректирует время в зависимости от значения TIFR и младшего слова (ТС1)
    221          ***************************************************************************
***/
    222          //UINT32 PULSE_SENS_CorrectTime(Pulse_Time_t *Pulse)

   \                                 In segment CODE, align 2, keep-with-next
    223          void PULSE_SENS_CorrectTime(Pulse_Time_t *Pulse)
   \                     PULSE_SENS_CorrectTime:
    224          {
   \   00000000   2F79               MOV     R23, R25
   \   00000002   2E28               MOV     R2, R24
   \   00000004   01F8               MOVW    R31:R30, R17:R16
    225           UINT32 time = Pulse->Time;
   \   00000006   8100               LD      R16, Z
   \   00000008   8111               LDD     R17, Z+1
   \   0000000A   8122               LDD     R18, Z+2
   \   0000000C   8133               LDD     R19, Z+3
    226            
    227             /* корректируем результат по состоянию флага OCF1A
    228              на момент считывания значений времени */
    229              if(Pulse->TIFR_reg & (1 << OCF1A))
   \   0000000E   8144               LDD     R20, Z+4
   \   00000010   FF44               SBRS    R20, 4
   \   00000012   C00A               RJMP    ??PULSE_SENS_CorrectTime_0
    230              {
    231                 time += 0x00010000; /* если флаг установлен, инкрементируем значение милисекунд */
   \   00000014   5000               SUBI    R16, 0
   \   00000016   4010               SBCI    R17, 0
   \   00000018   4F2F               SBCI    R18, 255
   \   0000001A   4F3F               SBCI    R19, 255
    232                 if(SYSTIMER_COMPARE_VAL == LOWORD(time))
   \   0000001C   2F51               MOV     R21, R17
   \   0000001E   3C0F               CPI     R16, 207
   \   00000020   4057               SBCI    R21, 7
   \   00000022   F411               BRNE    ??PULSE_SENS_CorrectTime_0
    233                  
    234                     /* если значение счетчика равно константе в регистре сравнения, то мы это
    235                     значение должны обнулить */
    236                     time &= 0xffff0000;
   \   00000024   E000               LDI     R16, 0
   \   00000026   E010               LDI     R17, 0
    237              }
    238          
    239              /* преобразуем в мкс */
    240              Pulse->Time = ((UINT32)(LOWORD(time) >> 1) + (UINT32)(HIWORD(time)) * 1000);
   \                     ??PULSE_SENS_CorrectTime_0:
   \   00000028   01A8               MOVW    R21:R20, R17:R16
   \   0000002A   9556               LSR     R21
   \   0000002C   9547               ROR     R20
   \   0000002E   E060               LDI     R22, 0
   \   00000030   0189               MOVW    R17:R16, R19:R18
   \   00000032   01C8               MOVW    R25:R24, R17:R16
   \   00000034   EE08               LDI     R16, 232
   \   00000036   E013               LDI     R17, 3
   \   00000038   E020               LDI     R18, 0
   \   0000003A   E030               LDI     R19, 0
   \   0000003C   9F19               MUL     R17, R25
   \   0000003E   0D20               ADD     R18, R0
   \   00000040   1D31               ADC     R19, R1
   \   00000042   9F18               MUL     R17, R24
   \   00000044   2D10               MOV     R17, R0
   \   00000046   0D21               ADD     R18, R1
   \   00000048   1F36               ADC     R19, R22
   \   0000004A   9F09               MUL     R16, R25
   \   0000004C   0D10               ADD     R17, R0
   \   0000004E   1D21               ADC     R18, R1
   \   00000050   1F36               ADC     R19, R22
   \   00000052   9F08               MUL     R16, R24
   \   00000054   2D00               MOV     R16, R0
   \   00000056   0D11               ADD     R17, R1
   \   00000058   1F26               ADC     R18, R22
   \   0000005A   1F36               ADC     R19, R22
   \   0000005C   0F04               ADD     R16, R20
   \   0000005E   1F15               ADC     R17, R21
   \   00000060   1F26               ADC     R18, R22
   \   00000062   1F36               ADC     R19, R22
   \   00000064   8300               ST      Z, R16
   \   00000066   8311               STD     Z+1, R17
   \   00000068   8322               STD     Z+2, R18
   \   0000006A   8333               STD     Z+3, R19
    241              //return ((UINT32)(LOWORD(time) >> 1) + (UINT32)(HIWORD(time)) * 1000);
    242          }
   \   0000006C   2D82               MOV     R24, R2
   \   0000006E   2F97               MOV     R25, R23
   \   00000070   9508               RET




Что бы не напрягать попусту Ваши глаза и мозговые извилины, сделаю два замечания:

В начале кода компилятор послушно берет адрес и формирует переменную time из регистров r16-19
Код
00000000   2F79               MOV     R23, R25
   \   00000002   2E28               MOV     R2, R24
   \   00000004   01F8               MOVW    R31:R30, R17:R16
    225           UINT32 time = Pulse->Time;
   \   00000006   8100               LD      R16, Z
   \   00000008   8111               LDD     R17, Z+1
   \   0000000A   8122               LDD     R18, Z+2
   \   0000000C   8133               LDD     R19, Z+3


В конце, так же послушно запихивает то, что пережевал обратно:

Код
   \   00000064   8300               ST      Z, R16
   \   00000066   8311               STD     Z+1, R17
   \   00000068   8322               STD     Z+2, R18
   \   0000006A   8333               STD     Z+3, R19


Что и как он там насчитал, меня мало интересует, но факт остается фактом, насчитал он не правильно


--------------------
Go to the top of the page
 
+Quote Post
Oldring
сообщение Dec 20 2006, 18:57
Сообщение #43


Гуру
******

Группа: Свой
Сообщений: 3 041
Регистрация: 10-01-05
Из: Москва
Пользователь №: 1 874



Чтобы не напрягать попусту наши извилины скомпилируйте теперь второй вариант и найдите отличия.

И, кстати, это так ведь задумано - при каждом вызове функции портить Pulse->Time?


--------------------
Пишите в личку.
Go to the top of the page
 
+Quote Post
prottoss
сообщение Dec 20 2006, 19:12
Сообщение #44


Гуру
******

Группа: Свой
Сообщений: 2 720
Регистрация: 24-03-05
Пользователь №: 3 659



Цитата(Oldring @ Dec 20 2006, 22:57) *
Чтобы не напрягать попусту наши извилины скомпилируйте теперь второй вариант и найдите отличия.
И, кстати, это так ведь задумано - при каждом вызове функции портить Pulse->Time?
Именно так и задуманно, с целью сэконмить несколько десятков байт памяти программ и несколько сотен наносекунд процессорного времени. Винигрет из команд MUL, MOV, ADD, ADC абсолютно одинаковый, за исключением того, что поменены функции регистровых пар R21:20 и R25:24 в "правильно работающем варианте". Возможно ошибка в этом, а возможно еще в чем то. НО, простите, нахрена я пишу на Си, чтобы потом перелопачивать этот же код на ассемблере?

Думаю, что у Sergio66 аналогичная проблема. Возможно, это связанно именно с типом LONG... Кстати, я пользуюсь IAR v.4.10B а Sergio66 IAR v.4.20.


--------------------
Go to the top of the page
 
+Quote Post
Oldring
сообщение Dec 20 2006, 19:19
Сообщение #45


Гуру
******

Группа: Свой
Сообщений: 3 041
Регистрация: 10-01-05
Из: Москва
Пользователь №: 1 874



Замечательно, где еще прописывается значение Pulse->Time и как часто вызывается эта функция?

И уж выложите пожалуйста "правильный" вариант.


--------------------
Пишите в личку.
Go to the top of the page
 
+Quote Post
prottoss
сообщение Dec 20 2006, 19:26
Сообщение #46


Гуру
******

Группа: Свой
Сообщений: 2 720
Регистрация: 24-03-05
Пользователь №: 3 659



Цитата(Oldring @ Dec 20 2006, 23:19) *
Замечательно, где еще прописывается значение Pulse->Time и как часто вызывается эта функция?

И уж выложите пожалуйста "правильный" вариант.
А правильный вариант выложен выше в моем первом посте с исходником. "Неправильная" строчка закомментирована, и в комментариях указанна. Структура меняется в прерывании, но на момент вызова обсуждаемой функции прерывание, которое обслуживает структуру, запрещается. Структуру (их несколько) отсылает в РС основной цикл.


--------------------
Go to the top of the page
 
+Quote Post
Oldring
сообщение Dec 20 2006, 19:28
Сообщение #47


Гуру
******

Группа: Свой
Сообщений: 3 041
Регистрация: 10-01-05
Из: Москва
Пользователь №: 1 874



Я конечно имел в виду дизассемблер, в котором изменилось распределение регистров.


--------------------
Пишите в личку.
Go to the top of the page
 
+Quote Post
singlskv
сообщение Dec 20 2006, 19:29
Сообщение #48


дятел
*****

Группа: Свой
Сообщений: 1 681
Регистрация: 13-05-06
Из: Питер
Пользователь №: 17 065



Цитата(prottoss @ Dec 20 2006, 18:05) *
Я смотрел, и не раз, пожалуйста, c чуйством глубокохо удовлетворения привожу листинг, смотрите:
Код
   \                     ??PULSE_SENS_CorrectTime_0:
   \   00000028   01A8               MOVW    R21:R20, R17:R16
   \   0000002A   9556               LSR     R21
   \   0000002C   9547               ROR     R20
   \   0000002E   E060               LDI     R22, 0
   \   00000030   0189               MOVW    R17:R16, R19:R18
   \   00000032   01C8               MOVW    R25:R24, R17:R16
   \   00000034   EE08               LDI     R16, 232
   \   00000036   E013               LDI     R17, 3
   \   00000038   E020               LDI     R18, 0
   \   0000003A   E030               LDI     R19, 0
   \   0000003C   9F19               MUL     R17, R25
   \   0000003E   0D20               ADD     R18, R0
   \   00000040   1D31               ADC     R19, R1
   \   00000042   9F18               MUL     R17, R24
   \   00000044   2D10               MOV     R17, R0
   \   00000046   0D21               ADD     R18, R1
   \   00000048   1F36               ADC     R19, R22
   \   0000004A   9F09               MUL     R16, R25
   \   0000004C   0D10                       ADD     R17, R0
   \   0000004E   1D21               ADC     R18, R1
   \   00000050   1F36               ADC     R19, R22
   \   00000052   9F08               MUL     R16, R24
   \   00000054   2D00               MOV     R16, R0
   \   00000056   0D11               ADD     R17, R1
   \   00000058   1F26               ADC     R18, R22
   \   0000005A   1F36               ADC     R19, R22
   \   0000005C   0F04               ADD     R16, R20
   \   0000005E   1F15               ADC     R17, R21
   \   00000060   1F26               ADC     R18, R22
   \   00000062   1F36               ADC     R19, R22

Prottoss
Не поленился, проверил Ваш код
сначала в голове, затем на симуляторе
Так вот: Компилятор сделал РОВНО ТО, ЧТО ВЫ У НЕГО ПОПРОСИЛИ !!!

Так что исчите апщибку в логике работы программы.

Да, кстати, присоединяюсь к
Цитата
И, кстати, это так ведь задумано - при каждом вызове функции портить Pulse->Time?

скорее всего именно здесь собака порылась
Go to the top of the page
 
+Quote Post
Oldring
сообщение Dec 20 2006, 19:34
Сообщение #49


Гуру
******

Группа: Свой
Сообщений: 3 041
Регистрация: 10-01-05
Из: Москва
Пользователь №: 1 874



Да, не забудьте убедиться, что функция после прерывания вызывается ровно один раз, и что прерывание действительно запрещено все время после вызова функции и до чтения результата.

Цитата(prottoss @ Dec 20 2006, 19:12) *
Думаю, что у Sergio66 аналогичная проблема.


Вероятнее всего.


--------------------
Пишите в личку.
Go to the top of the page
 
+Quote Post
prottoss
сообщение Dec 20 2006, 20:04
Сообщение #50


Гуру
******

Группа: Свой
Сообщений: 2 720
Регистрация: 24-03-05
Пользователь №: 3 659



Цитата(singlskv @ Dec 20 2006, 23:29) *
Prottoss
Не поленился, проверил Ваш код
сначала в голове, затем на симуляторе
Так вот: Компилятор сделал РОВНО ТО, ЧТО ВЫ У НЕГО ПОПРОСИЛИ !!!
Так что исчите апщибку в логике работы программы.
Да, кстати, присоединяюсь к
Цитата

И, кстати, это так ведь задумано - при каждом вызове функции портить Pulse->Time?

скорее всего именно здесь собака порылась
Какая все же ошибка? Объясните не разумному?



2 Oldring - функция вызывается после того, как прерывания запрещены. После всех вычислений прерывания разрешаются.



В первом случае я возвращаю результат из функции и он правильный, во втором случае я возвращаю результат в указатель и результат, в итоге, не правильный


--------------------
Go to the top of the page
 
+Quote Post
Oldring
сообщение Dec 20 2006, 20:09
Сообщение #51


Гуру
******

Группа: Свой
Сообщений: 3 041
Регистрация: 10-01-05
Из: Москва
Пользователь №: 1 874



Цитата(prottoss @ Dec 20 2006, 20:04) *
В первом случае я возвращаю результат из функции и он правильный, во втором случае я возвращаю результат в указатель и результат, в итоге, не правильный


Ключевое слово - "в итоге". Так найдите то место, в котором результат в конце концов портится. Судя по тому, что, как Вы пишете, код вычисления выражения одинаковый - и результат сразу после вычисления выражения одинаковый. Так что ищите глюк где-то в другом месте.


--------------------
Пишите в личку.
Go to the top of the page
 
+Quote Post
prottoss
сообщение Dec 20 2006, 20:23
Сообщение #52


Гуру
******

Группа: Свой
Сообщений: 2 720
Регистрация: 24-03-05
Пользователь №: 3 659



Цитата(Oldring @ Dec 21 2006, 00:09) *
Ключевое слово - "в итоге". Так найдите то место, в котором результат в конце концов портится. Судя по тому, что, как Вы пишете, код вычисления выражения одинаковый - и результат сразу после вычисления выражения одинаковый. Так что ищите глюк где-то в другом месте.
А в итоге вызывающая функция вот такая (закомментированная строчка не работает для функции, которая возвращает результат вычислений с структуру):

Код


UINT16 PULSE_SENS_GetState(Pulse_Time_t *Pulse)
{
   /* корректируем время и преобразуем период в герцы*/
    return (UINT16)(1000000 / /* stop_time - start_time */
             (PULSE_SENS_CorrectTime(&Pulse[1]) -PULSE_SENS_CorrectTime(&Pulse[0])));
              //(Pulse[1].Time - Pulse[0].Time)); -----ЭТО НЕ РАБОТАЕТ
}


Pulse - массив двух структур Pulse_Time_t, которые изменяет внешнее прерывание INT. Перед вызовом данной функции прерывание запрещается, после - разрешается.


--------------------
Go to the top of the page
 
+Quote Post
Oldring
сообщение Dec 20 2006, 20:28
Сообщение #53


Гуру
******

Группа: Свой
Сообщений: 3 041
Регистрация: 10-01-05
Из: Москва
Пользователь №: 1 874



Пожалуйста, приведите два варианта кода отдельно - когда работает и когда не работает. Сейчас сложно понять, какой именно вариант не работает.


--------------------
Пишите в личку.
Go to the top of the page
 
+Quote Post
prottoss
сообщение Dec 20 2006, 20:43
Сообщение #54


Гуру
******

Группа: Свой
Сообщений: 2 720
Регистрация: 24-03-05
Пользователь №: 3 659



Цитата(Oldring @ Dec 21 2006, 00:28) *
Пожалуйста, приведите два варианта кода отдельно - когда работает и когда не работает. Сейчас сложно понять, какой именно вариант не работает.
ОК



Вот рабочий вариант:

Код


/*****************************************************************************
******************************************************************************/
UINT16 PULSE_SENS_GetState(Pulse_Time_t *Pulse)
{
   /* корректируем время и преобразуем период в герцы*/
    return (UINT16)(1000000 / /* stop_time - start_time */
             (PULSE_SENS_CorrectTime(&Pulse[1]) -
                 PULSE_SENS_CorrectTime(&Pulse[0])));
}

............................................................................

/*****************************************************************************
******************************************************************************/
UINT32 PULSE_SENS_CorrectTime(Pulse_Time_t *Pulse)
{
    UINT32 time = Pulse->Time;
  
   /* корректируем результат по состоянию флага OCF1A
    на момент считывания значений времени */
    if(Pulse->TIFR_reg & (1 << OCF1A))
    {
       time += 0x00010000; /* если флаг установлен, инкрементируем значение милисекунд */
       if(SYSTIMER_COMPARE_VAL == LOWORD(time))
        
           /* если значение счетчика равно константе в регистре сравнения, то мы это
           значение должны обнулить */
           time &= 0xffff0000;
    }

    /* преобразуем в мкс */
    return ((UINT32)(LOWORD(time) >> 1) + (UINT32)(HIWORD(time)) * 1000);
}




Вот НЕ рабочий вариант



Код
/*****************************************************************************
******************************************************************************/
UINT16 PULSE_SENS_GetState(Pulse_Time_t *Pulse)
{
   /* корректируем время и преобразуем период в герцы*/

   PULSE_SENS_CorrectTime(&Pulse[1])
   PULSE_SENS_CorrectTime(&Pulse[0])
   return (UINT16)(1000000 /                                     /* stop_time - start_time */
             (Pulse[1].Time - Pulse[0].Time));

}

/*****************************************************************************
Коррекция значения времени
Корректирует время в зависимости от значения TIFR и младшего слова (ТС1)
******************************************************************************/
void PULSE_SENS_CorrectTime(Pulse_Time_t *Pulse)
{
    UINT32 time = Pulse->Time;
  
   /* корректируем результат по состоянию флага OCF1A
    на момент считывания значений времени */
    if(Pulse->TIFR_reg & (1 << OCF1A))
    {
       time += 0x00010000; /* если флаг установлен, инкрементируем значение милисекунд */
       if(SYSTIMER_COMPARE_VAL == LOWORD(time))
        
           /* если значение счетчика равно константе в регистре сравнения, то мы это
           значение должны обнулить */
           time &= 0xffff0000;
    }

    /* преобразуем в мкс */
    Pulse->Time = ((UINT32)(LOWORD(time) >> 1) + (UINT32)(HIWORD(time)) * 1000);

}




А теперь найдите отличия в смысле первого и второго, я вот что то не могу....


--------------------
Go to the top of the page
 
+Quote Post
Oldring
сообщение Dec 20 2006, 20:45
Сообщение #55


Гуру
******

Группа: Свой
Сообщений: 3 041
Регистрация: 10-01-05
Из: Москва
Пользователь №: 1 874



Ну так а когда в нерабочем варианте вызывается функция PULSE_SENS_CorrectTime?


--------------------
Пишите в личку.
Go to the top of the page
 
+Quote Post
prottoss
сообщение Dec 20 2006, 20:53
Сообщение #56


Гуру
******

Группа: Свой
Сообщений: 2 720
Регистрация: 24-03-05
Пользователь №: 3 659



Цитата(Oldring @ Dec 21 2006, 00:45) *
Ну так а когда в нерабочем варианте вызывается функция PULSE_SENS_CorrectTime?
Забыл их записать, они выше, счас исправлю


--------------------
Go to the top of the page
 
+Quote Post
Oldring
сообщение Dec 20 2006, 21:02
Сообщение #57


Гуру
******

Группа: Свой
Сообщений: 3 041
Регистрация: 10-01-05
Из: Москва
Пользователь №: 1 874



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


--------------------
Пишите в личку.
Go to the top of the page
 
+Quote Post
prottoss
сообщение Dec 21 2006, 17:09
Сообщение #58


Гуру
******

Группа: Свой
Сообщений: 2 720
Регистрация: 24-03-05
Пользователь №: 3 659



Цитата(Oldring @ Dec 21 2006, 01:02) *
Только этот вариант все равно не должен компилироваться. Теперь компилируйте, проверяйте, что он все еще не работает - и вываливайте дизассемблер.


Все, заработало!!!

Ошибка была не "компиляторовская". Просто, из-за относительной сложности вычислений для 8-и битника в "главной" процедуре, вызывающей CorrectTime использовался стек данных, а так как его глубина у меня по умолчанию была определена как 0х20 то стек данных затирался... Странным образом программа хромала дальше. Мало того, данные с ADC и GPIO, работающие тоже, кстати, по прерываниям не портились и выдавались хосту нормально, портились только частотомеры... Увеличил стек до 0х40 - все ОК! Я так понимаю по умолчанию глубина стоит 0х20 - это именно для прерываний? То бишь, что бы можно было, при случае, сохранить все 32 регистра? Вот я его еще в два раза и увеличил...Хотя со всеми вычислениями в программе я уже справился, но мало ли.



Тем не менее, всем огромное спасибо, особо отмечу идейную помощь singlskv, (кстати, не впервой)особый респект Вам! a14.gif


--------------------
Go to the top of the page
 
+Quote Post
Dog Pawlowa
сообщение Dec 21 2006, 17:39
Сообщение #59


Гуру
******

Группа: Свой
Сообщений: 2 702
Регистрация: 14-07-06
Пользователь №: 18 823



Цитата(prottoss @ Dec 21 2006, 17:09) *
Все, заработало!!!
Увеличил стек до 0х40 - все ОК! Я так понимаю по умолчанию глубина стоит 0х20 - это именно для прерываний? То бишь, что бы можно было, при случае, сохранить все 32 регистра?

Поздравляю. cheers.gif

А глубина стека по умолчанию ничего не значит, так как кроме прерываний существуют вложенные функции, printfы и прочие мелкие радости ЯВУ. Как вообще можно оставлять 0x20, не представляю. unsure.gif


--------------------
Уходя, оставьте свет...
Go to the top of the page
 
+Quote Post
prottoss
сообщение Dec 21 2006, 18:04
Сообщение #60


Гуру
******

Группа: Свой
Сообщений: 2 720
Регистрация: 24-03-05
Пользователь №: 3 659



Цитата(Dog Pawlowa @ Dec 21 2006, 21:39) *
Цитата(prottoss @ Dec 21 2006, 17:09) *

Все, заработало!!!
Увеличил стек до 0х40 - все ОК! Я так понимаю по умолчанию глубина стоит 0х20 - это именно для прерываний? То бишь, что бы можно было, при случае, сохранить все 32 регистра?

Поздравляю. cheers.gif

А глубина стека по умолчанию ничего не значит, так как кроме прерываний существуют вложенные функции, printfы и прочие мелкие радости ЯВУ. Как вообще можно оставлять 0x20, не представляю. unsure.gif
А вот представьте, мил человек, никада в своей работе с АВРами не пользовался printf и прочими радостями ЯВУ (честно говря, я даже не знаю как это расшифровывается). Пользуюсь, обычно парой светодиодов, USART, ну и, естественно, отладчиком.


--------------------
Go to the top of the page
 
+Quote Post
Dog Pawlowa
сообщение Dec 21 2006, 18:44
Сообщение #61


Гуру
******

Группа: Свой
Сообщений: 2 702
Регистрация: 14-07-06
Пользователь №: 18 823



Цитата(prottoss @ Dec 21 2006, 18:04) *
А вот представьте, мил человек, никада в своей работе с АВРами не пользовался printf и прочими радостями ЯВУ (честно говря, я даже не знаю как это расшифровывается). Пользуюсь, обычно парой светодиодов, USART, ну и, естественно, отладчиком.

ЯВУ - это язык высокого уровня. "С", например.
А так выглядит средний проект. Точнее, одна из его частей.
Пары светодиодов, увы, бывает недостаточно...

Прикрепленное изображение


--------------------
Уходя, оставьте свет...
Go to the top of the page
 
+Quote Post
prottoss
сообщение Dec 21 2006, 19:02
Сообщение #62


Гуру
******

Группа: Свой
Сообщений: 2 720
Регистрация: 24-03-05
Пользователь №: 3 659



Цитата(Dog Pawlowa @ Dec 21 2006, 22:44) *
Цитата(prottoss @ Dec 21 2006, 18:04) *

А вот представьте, мил человек, никада в своей работе с АВРами не пользовался printf и прочими радостями ЯВУ (честно говря, я даже не знаю как это расшифровывается). Пользуюсь, обычно парой светодиодов, USART, ну и, естественно, отладчиком.

ЯВУ - это язык высокого уровня. "С", например.
А так выглядит средний проект. Точнее, одна из его частей.
Пары светодиодов, увы, бывает недостаточно...

Прикрепленное изображение

Да хоть тыщща файлов в проекте - каждый модуль, ИМХО, должен быть законченной частью программы, и уметь функционировать отдельно...


--------------------
Go to the top of the page
 
+Quote Post
singlskv
сообщение Dec 21 2006, 19:47
Сообщение #63


дятел
*****

Группа: Свой
Сообщений: 1 681
Регистрация: 13-05-06
Из: Питер
Пользователь №: 17 065



Цитата(prottoss @ Dec 21 2006, 17:09) *
Увеличил стек до 0х40 - все ОК! Я так понимаю по умолчанию глубина стоит 0х20 - это именно для прерываний? То бишь, что бы можно было, при случае, сохранить все 32 регистра? Вот я его еще в два раза и увеличил...Хотя со всеми вычислениями в программе я уже справился, но мало ли.

В начале программы забивайте весь отведенный стек какой-нибудь сигнатурой
ну а дальше контролите сколько затерли, или ручками приотладке или програмно(как удобнее)
Go to the top of the page
 
+Quote Post
defunct
сообщение Dec 21 2006, 20:33
Сообщение #64


кекс
******

Группа: Свой
Сообщений: 3 825
Регистрация: 17-12-05
Из: Киев
Пользователь №: 12 326



Цитата(prottoss @ Dec 21 2006, 19:02) *
Да хоть тыщща файлов в проекте - каждый модуль, ИМХО, должен быть законченной частью программы, и уметь функционировать отдельно...

В приведенной вами цитате объем стека обведен вообще-то.

Насчет того, что вы printf'ом не пользуетесь и насколько помнится и JTAG'ом тоже.. Дык это сугубо ваше дело. Несомневаюсь, что некоторым удобнее отлаживать программы на бумаге или с помощью одного светодиода, что в итоге приводит к таким вот глюкам как рассматриваемые в этой ветке. А на что грешить с такой отладкой - на компилятор естессно, это все он - редиска - неправильно считает, не то сохраняет и т.п...
Go to the top of the page
 
+Quote Post
WHALE
сообщение Dec 21 2006, 22:05
Сообщение #65


Знающий
****

Группа: Свой
Сообщений: 902
Регистрация: 2-01-06
Из: Краснодар
Пользователь №: 12 768



[/quote]
В начале программы забивайте весь отведенный стек какой-нибудь сигнатурой
ну а дальше контролите сколько затерли, или ручками приотладке или програмно(как удобнее)
[/quote]
зачем весь стек-то забивать?В CV есть удобная фича-ставится в старт-апе маркер конца стека и в случае глюков я его первым делом проверяю.Если на месте,родимый,значит дело не в обьеме стека.


--------------------
"Hello, word!" - 17 errors 56 warnings
Go to the top of the page
 
+Quote Post
singlskv
сообщение Dec 21 2006, 22:14
Сообщение #66


дятел
*****

Группа: Свой
Сообщений: 1 681
Регистрация: 13-05-06
Из: Питер
Пользователь №: 17 065



Цитата(WHALE @ Dec 21 2006, 22:05) *
Цитата

В начале программы забивайте весь отведенный стек какой-нибудь сигнатурой
ну а дальше контролите сколько затерли, или ручками приотладке или програмно(как удобнее)

зачем весь стек-то забивать?В CV есть удобная фича-ставится в старт-апе маркер конца стека и в случае глюков я его первым делом проверяю.Если на месте,родимый,значит дело не в обьеме стека.

при отладке удобнее весь стек, сразу же видно, даже визуально чего там с ним творится
ну и еще можно написать код который будет в реалтайме в глобальной переменной
показывать максимальный размер стека за время работы, для отладки опять же
очень удобно
Go to the top of the page
 
+Quote Post
Guest_Serg79_*
сообщение Dec 22 2006, 13:29
Сообщение #67





Guests






Цитата(defunct @ Dec 21 2006, 20:33) *
Насчет того, что вы printf'ом не пользуетесь и насколько помнится и JTAG'ом тоже.. Дык это сугубо ваше дело. Несомневаюсь, что некоторым удобнее отлаживать программы на бумаге или с помощью одного светодиода, что в итоге приводит к таким вот глюкам как рассматриваемые в этой ветке. А на что грешить с такой отладкой - на компилятор естессно, это все он - редиска - неправильно считает, не то сохраняет и т.п...

Вот и Я о том же.
С момента изобретения языка 'C' в 1970 году прошло уже столько времени, что его синтаксический анализатор стал отшлифованным как брилиант. И грешить на него, покрайней мере, просто глупо.
Go to the top of the page
 
+Quote Post
prottoss
сообщение Dec 22 2006, 14:57
Сообщение #68


Гуру
******

Группа: Свой
Сообщений: 2 720
Регистрация: 24-03-05
Пользователь №: 3 659



Цитата(defunct @ Dec 22 2006, 00:33) *
Цитата(prottoss @ Dec 21 2006, 19:02) *

Да хоть тыщща файлов в проекте - каждый модуль, ИМХО, должен быть законченной частью программы, и уметь функционировать отдельно...

В приведенной вами цитате объем стека обведен вообще-то.

Насчет того, что вы printf'ом не пользуетесь и насколько помнится и JTAG'ом тоже.. Дык это сугубо ваше дело. Несомневаюсь, что некоторым удобнее отлаживать программы на бумаге или с помощью одного светодиода, что в итоге приводит к таким вот глюкам как рассматриваемые в этой ветке. А на что грешить с такой отладкой - на компилятор естессно, это все он - редиска - неправильно считает, не то сохраняет и т.п...
Вообще то, ветку с жалобой на компилятор открыл НЕ Я, это первое. А раз уж у Вас такая хорошая память , наверное заметили, что ветки со своими проблемами я ооччччень редко организую. А свой код выложил так сказать в поддержку всеми забытого Sergio66. Потому как, кроме малоумного совета расставить правильно скобки, ни хто толком не ему совета дельног не дал. Может быть отчасти из-за того, что он сам на эту ветку забил - похоже нашел проблему, и похоже она была не по теме ветки))) Я же сам свой код опубликовал, я же его и решил. Второе - к компилятору и тем паче к тем, кто его создал отношусь с уважением, так как до такого самому додуматься умишки не хватает.



ПО поводу отладки JTAGом - ДЛЯ AVR, как я уже говорил выше, я им не пользуюсь. Да, мне хватает, USART пары светодиодов и и отладчика в AVRStudio. Что такое JTAG - я знаю очень хорошо. И знаю, что средство это очень ограниченное и специфическое и уж тем более не панацея от всех проблем. Если в голове масла нет - JTAG не поможет никогда)))



Цитата(singlskv @ Dec 22 2006, 02:14) *
Цитата(WHALE @ Dec 21 2006, 22:05) *

Цитата

В начале программы забивайте весь отведенный стек какой-нибудь сигнатурой
ну а дальше контролите сколько затерли, или ручками приотладке или програмно(как удобнее)

зачем весь стек-то забивать?В CV есть удобная фича-ставится в старт-апе маркер конца стека и в случае глюков я его первым делом проверяю.Если на месте,родимый,значит дело не в обьеме стека.

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

Цитата(Serg79 @ Dec 22 2006, 17:29) *
Вот и Я о том же.
С момента изобретения языка 'C' в 1970 году прошло уже столько времени, что его синтаксический анализатор стал отшлифованным как брилиант. И грешить на него, покрайней мере, просто глупо.
Ну, во первых, приятно слышать здоровый русский язык wink.gif А по поводу printf, использую его только в под х86 - удобная штука для форматированного вывода, но с того же 1970, скорее всего, такая же охочая до ресурсов как и универсальная - худа без добра не бывает и наоборот... Я в качестве printf использую собственные функции вывода строк в USART - у меня их, обычно, две - для чисел и для собсвенно строковых сообщений


--------------------
Go to the top of the page
 
+Quote Post
defunct
сообщение Dec 22 2006, 16:20
Сообщение #69


кекс
******

Группа: Свой
Сообщений: 3 825
Регистрация: 17-12-05
Из: Киев
Пользователь №: 12 326



Цитата(prottoss @ Dec 22 2006, 14:57) *
Что такое JTAG - я знаю очень хорошо. И знаю, что средство это очень ограниченное и специфическое и уж тем более не панацея от всех проблем.

Нельзя очень хорошо знать то, что никогда не пробовали на практике.

Через JTAG (AVR) осуществляется полный контроль над МК. В любой момент можно остановить проц, посмотреть состояние памяти, стек-поинтеры, состояние портов, периферии и т.д. Можно прочитать полный дамп памяти, изменить состояние узлов, переменных и запустить проц опять.. Более того, через JTAG можно отлаживать даже программы с включенным WDT. При остановке проца остановится и WDT. Различные Speep режимы и т.д. и т.п.
Работает все это дело прямо из-под любимого вами IAR'a. Т.е. в IAR'е просто собирается проект, одной кнопкой запускается сразу в девайсе.
Если сравнивать AVR'овский JTAG с ARM'овскими, дык AVR'овский на 10 порядков лучше по стабильности. Плюс 4 точки останова это не две... Хватает на все про все.

Ограничение же только одно JTAG для AVR не совместим больше ни с чем.

Вы ставите в противовес JTAG'у Симулятор - это как секс по телефону.

Цитата
Если в голове масла нет - JTAG не поможет никогда)))

тут уж ничего не поможет. ;>
Go to the top of the page
 
+Quote Post
Wild007
сообщение Dec 22 2006, 17:02
Сообщение #70


Местный
***

Группа: Свой
Сообщений: 226
Регистрация: 25-03-05
Из: Беларусь
Пользователь №: 3 672



2 defunct
Цитата
Вы ставите в противовес JTAG'у Симулятор - это как секс по телефону.

Сималятор и JTAG, ИМХО, это две разные вещи.
Симулятор нужен для отладки кусков програмы даже без железа. А JTAG это инструмент отладки готового устройства. Умение использовать их в своей работе, в нужный момент, это и есть професионализм "програмиста-элекроника" к коим мы причисляем себя smile.gif .

Сообщение отредактировал Wild007 - Dec 22 2006, 17:03


--------------------
Ничто так не ограничивает полет мысли программиста, как компилятор
Go to the top of the page
 
+Quote Post
prottoss
сообщение Dec 22 2006, 17:05
Сообщение #71


Гуру
******

Группа: Свой
Сообщений: 2 720
Регистрация: 24-03-05
Пользователь №: 3 659



Цитата(defunct @ Dec 22 2006, 20:20) *
Цитата(prottoss @ Dec 22 2006, 14:57) *

Что такое JTAG - я знаю очень хорошо. И знаю, что средство это очень ограниченное и специфическое и уж тем более не панацея от всех проблем.

Нельзя очень хорошо знать то, что никогда не пробовали на практике.
С чего вы взяли, что я не использую JTAG??? Или Вы думаете, что он придуман только для AVR))) Читайте внимательней посты, я говорил именно JTAG для МК AVR

И, ИМХО, не JTAG залог написания "хорошей" программы, а умение "правильно" составить алгоритм работы и структуру программы

Сообщение отредактировал prottoss - Dec 22 2006, 17:12


--------------------
Go to the top of the page
 
+Quote Post
defunct
сообщение Dec 22 2006, 17:25
Сообщение #72


кекс
******

Группа: Свой
Сообщений: 3 825
Регистрация: 17-12-05
Из: Киев
Пользователь №: 12 326



Цитата(prottoss @ Dec 22 2006, 17:05) *
Читайте внимательней посты, я говорил именно JTAG для МК AVR

Это и к вам относится. Я тоже говорил о JTAG для AVR и сравнивал его с армовским.
AVR'овский JTAG несколько отличается от других. Но так как вы его не пробовали, то вам и кажется, что он неполноценный и глючный как некоторые реализации для других МК. А на самом деле это не так. Поэтому еще раз повторюсь:

Нельзя очень хорошо знать то, что никогда не пробовали на практике.

Цитата
И, ИМХО, не JTAG залог написания "хорошей" программы, а умение "правильно" составить алгоритм работы и структуру программы

1. Правильные алгоритмы,
2. Правильная структура программы

Это необходимо но не достаточно для получения хорошей программы.

Необходимо также как минимум:
3. Правильное всестороннее тестирование.
4. Правильная отладка (а вот тут нужны все возможные инструменты - в т.ч. и консоль, и отладчик)
Go to the top of the page
 
+Quote Post

5 страниц V   1 2 3 > » 
Reply to this topicStart new topic
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 


RSS Текстовая версия Сейчас: 20th July 2025 - 10:32
Рейтинг@Mail.ru


Страница сгенерированна за 0.02427 секунд с 7
ELECTRONIX ©2004-2016