|
Ошибка IAR или чтото еще? |
|
|
|
 |
Ответов
(1 - 71)
|
Dec 18 2006, 13:15
|
Местный
  
Группа: Свой
Сообщений: 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;
|
|
|
|
|
Dec 18 2006, 14:48
|
Местный
  
Группа: Участник
Сообщений: 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, тогда погрешность в вычислении уменьшится.
|
|
|
|
|
Dec 18 2006, 15:01
|
Местный
  
Группа: Свой
Сообщений: 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, тогда погрешность в вычислении уменьшится. А что, если переменная размещена не в регистрах, а в памяти, свертка констант не производится? Или это происходит как то иначе? Я ведт ничего не поменял, просто добился иного размещения в памяти переменной!!! И никаких скобок.И без них все заработало. Нет! Дело не в этом!!!
|
|
|
|
|
Dec 18 2006, 15:28
|
Гуру
     
Группа: Свой
Сообщений: 2 702
Регистрация: 14-07-06
Пользователь №: 18 823

|
Цитата(Sergio66 @ Dec 18 2006, 15:01)  А что, если переменная размещена не в регистрах, а в памяти, свертка констант не производится? Или это происходит как то иначе? Я ведт ничего не поменял, просто добился иного размещения в памяти переменной!!! И никаких скобок.И без них все заработало. Нет! Дело не в этом!!! Послушайте! :-) Вам предлагают дело - записать формулу ПРАВИЛЬНО. Разбираться в особенностях компилятора в случае неправильной записи - очень неблагодарное дело. А еще можно начать разбираться в особенностях различных компиляторов. Путь в никуда. Меня такие вещи давно не беспокоят - побольше скобок и преобразования типов. И ффсе!
--------------------
Уходя, оставьте свет...
|
|
|
|
|
Dec 18 2006, 15:44
|
Местный
  
Группа: Свой
Сообщений: 235
Регистрация: 9-02-05
Пользователь №: 2 526

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

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

|
Цитата(Dog Pawlowa @ Dec 18 2006, 19:28)  Послушайте! :-) Вам предлагают дело - записать формулу ПРАВИЛЬНО. Разбираться в особенностях компилятора в случае неправильной записи - очень неблагодарное дело. А еще можно начать разбираться в особенностях различных компиляторов. Путь в никуда. Меня такие вещи давно не беспокоят - побольше скобок и преобразования типов. И ффсе!  Сказанно, если размещать переменную локально, не вычисляется, если глобально - вычислятся - при чем тут скобки???
--------------------
|
|
|
|
|
Dec 18 2006, 16:11
|
дятел
    
Группа: Свой
Сообщений: 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 - целое, тады не надо
|
|
|
|
|
Dec 18 2006, 16:46
|
Гуру
     
Группа: Свой
Сообщений: 2 702
Регистрация: 14-07-06
Пользователь №: 18 823

|
Цитата(prottoss @ Dec 18 2006, 15:45)  Сказанно, если размещать переменную локально, не вычисляется, если глобально - вычислятся - при чем тут скобки??? 1. Было сказано так "побольше скобок И ПРЕОБРАЗОВАНИЯ ТИПОВ". 2. Ообще-тоавтор он мог бы разместить здесь ассемблерный текст и гадание на гуще не состоялось бы. 2. Видел подобный случай - я работал под IAR, клиент стал компилировать под ICC. Результат усреднения значений АЦП считался по разному. Именно из-за особенностей работы компилятора в случае некорректного написания программы. И что? И ничего.
--------------------
Уходя, оставьте свет...
|
|
|
|
|
Dec 18 2006, 17:08
|

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

|
Цитата(Dog Pawlowa @ Dec 18 2006, 20:46)  Цитата(prottoss @ Dec 18 2006, 15:45)  Сказанно, если размещать переменную локально, не вычисляется, если глобально - вычислятся - при чем тут скобки???
1. Было сказано так "побольше скобок И ПРЕОБРАЗОВАНИЯ ТИПОВ". Это было сказанно, вернее посоветованна, Вами, и товарищем aesok. Смысл же вопроса автора топика был именно в том, что сказал я - если размещать переменную локально, не вычисляется, если глобально - вычислятся , при чем здесь cкобки, позвольте? У меня, в данный момент, есть тоже подобный фокус в программе, которой сейчас занимаюсь. Если обсуждаемая сдесь проблема не решится, поделюсь своей...
--------------------
|
|
|
|
|
Dec 18 2006, 17:27
|

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

|
Цитата(_Bill @ Dec 18 2006, 14:48)  Ну, так все правильно. Компилятор перед генерацией производит свертку констант, т.е. вычисляет значение PRODUCTIVITY / 20000. Естественно, оно будет вычисленно неточно. Поставьте в выражении скобки в нужных местах. Еще советую объявить константы как long, тогда погрешность в вычислении уменьшится. Не имеет права. Ассоциативность этих операций фиксирована - слева направа. Нужно сравнивать листинг того, как получается неправильно, и того, как получается правильно. Иначе можно много фантазировать. Цитата(Dog Pawlowa @ Dec 18 2006, 15:28)  Вам предлагают дело - записать формулу ПРАВИЛЬНО. Все записано правильно. Но нужно бы еще выяснить, какие диапазоны переменных и чему точно равны константы.
--------------------
Пишите в личку.
|
|
|
|
|
Dec 18 2006, 18:48
|
Гуру
     
Группа: Свой
Сообщений: 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кобки, позвольте? У меня, в данный момент, есть тоже подобный фокус в программе, которой сейчас занимаюсь. Если обсуждаемая сдесь проблема не решится, поделюсь своей... Видимо, Вы не поняли смысла того, что хотел сказать я.  Если есть малейшая возможность, что компилятор "спровоцирован" некорректным текстом, то лучше эту возможность исключить. Цитата(Oldring @ Dec 18 2006, 17:27)  Цитата(Dog Pawlowa @ Dec 18 2006, 15:28)  Вам предлагают дело - записать формулу ПРАВИЛЬНО.
Все записано правильно. Но нужно бы еще выяснить, какие диапазоны переменных и чему точно равны константы. Тогда мы по разному понимает слово "правильно". Я включал в это понятие учет возможности переполнения и максимальной независимости от констант. А Вы - нет?
--------------------
Уходя, оставьте свет...
|
|
|
|
|
Dec 18 2006, 19:08
|

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

|
Цитата(Dog Pawlowa @ Dec 18 2006, 18:48)  Тогда мы по разному понимает слово "правильно". Я включал в это понятие учет возможности переполнения и максимальной независимости от констант. А Вы - нет?  Дело в том, что Билл написал просто чепуху про "естественную" свертку целочисленных констант перед вычислением выражения, а Вашего предложения я вообще почему-то не вижу в истории переписки. Так как так и не была озвучена информация про диапазоны операндов, хотелось бы все-таки увидеть, что именно Вы считаете "правильной" записью данного выражения, если это понятие "правильности" отличется от формальной правильности. Хотелось бы также узнать Ваше мнение по следующему вопросу: существует ли с точки зрения стандарта языка программирования С какая-либо разница между выражениями Код a * b * c / d и Код ((a * b) * c) / d ? И, кстати, считаете ли Вы что компилятор имеет право выражение Код a = b * 2 / 3; заменить на Код a = 0; ?
--------------------
Пишите в личку.
|
|
|
|
|
Dec 18 2006, 19:31
|
дятел
    
Группа: Свой
Сообщений: 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 ? или нет ? Замечу что + и - имеет один уровень приоритета * и / тоже один уровень
|
|
|
|
|
Dec 18 2006, 19:38
|

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

|
Ответ прост. До тех пор, пока результат вычисления всего целочисленного выражения не отличается от стандартного способа вычисления с учетом того, что при переполнении промежуточных результатов возможно undefined поведение, компилятор может делать все, что угодно. Но только пока не отличается. Более того, важен даже не результат вычисления одного выражения, а последовательность записи значений в volatile переменные и вызовов системных функций. Все оптимизации программы, которые сохраняют запись в volatile переменные и ызовы системных функций - законные, все, которые приводят к изменению внешнего поведения программы - незаконны.
--------------------
Пишите в личку.
|
|
|
|
|
Dec 18 2006, 19:53
|
дятел
    
Группа: Свой
Сообщений: 1 681
Регистрация: 13-05-06
Из: Питер
Пользователь №: 17 065

|
Цитата(Oldring @ Dec 18 2006, 19:38)  Ответ прост. До тех пор, пока результат вычисления всего целочисленного выражения не отличается от стандартного способа вычисления с учетом того, что при переполнении промежуточных результатов возможно undefined поведение, компилятор может делать все, что угодно. Но только пока не отличается. Более того, важен даже не результат вычисления одного выражения, а последовательность записи значений в volatile переменные и вызовов системных функций. Все оптимизации программы, которые сохраняют запись в volatile переменные и ызовы системных функций - законные, все, которые приводят к изменению внешнего поведения программы - незаконны. Наверное все-таки так: - если мы отключаем оптимизацию полностью - если мы отключаем все расширения компилятора отличные от стандарта - если мы все переменные объявляем как volatile то тогда да, компилятор обязан сделать все как ему написали. А вот если мы все выше перечисленное включили, то Добро пожаловать в Manual для выяснения всех подробностей как и что себе думает компилятор при оптимизации (если конечно авторы не забыли это указать  )
|
|
|
|
|
Dec 18 2006, 20:31
|
Гуру
     
Группа: Свой
Сообщений: 2 702
Регистрация: 14-07-06
Пользователь №: 18 823

|
Цитата(Oldring @ Dec 18 2006, 19:38)  Ответ прост. До тех пор, пока результат вычисления всего целочисленного выражения не отличается от стандартного способа вычисления с учетом того, что при переполнении промежуточных результатов возможно undefined поведение, компилятор может делать все, что угодно. Но только пока не отличается. Более того, важен даже не результат вычисления одного выражения, а последовательность записи значений в volatile переменные и вызовов системных функций. Все оптимизации программы, которые сохраняют запись в volatile переменные и ызовы системных функций - законные, все, которые приводят к изменению внешнего поведения программы - незаконны. Меня "правильность" компилятора мало интересует, я не д-р Туамосец. Я рассматриваю правильность как максимально близкий результат к результату при перемножении в столбик И получается такая незадача, что правильность зависит от значения переменных. int a,b,c; a*b/c при a=100, b=100, c=3 правильно будет (a*  /c, а при a=1000, b=1000, c=100 правильно будет a*(b/c). Поэтому весь этот дискуссион не имеет смысла, тем более что автор не указал даже с какими числами он работал и предусмотрен ли запас по диапазону. Потому и залег на дно, видимо, предоставив нам возможность друг друга за чубы тягать Цитата(Oldring @ Dec 18 2006, 20:08)  3. Нет. Компилятор обязан сделать чтобы снаружи выглядело как ему написали в любом случае. Хм... Например, оптимизатор IAR самостоятельно заменяет switch (a) {case ....} на vector[a] и создает массив функций при большом числе a. Такое решение выглядит, как написали, или не выглядит?
--------------------
Уходя, оставьте свет...
|
|
|
|
|
Dec 18 2006, 20:37
|

Гуру
     
Группа: Свой
Сообщений: 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 переменным - это совершенно законное преобразование программы.
--------------------
Пишите в личку.
|
|
|
|
|
Dec 18 2006, 20:43
|

Гуру
     
Группа: Свой
Сообщений: 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*  /c, а при a=1000, b=1000, c=100 правильно будет a*(b/c). Поэтому весь этот дискуссион не имеет смысла, тем более что автор не указал даже с какими числами он работал и предусмотрен ли запас по диапазону. Потому и залег на дно, видимо, предоставив нам возможность друг друга за чубы тягать  Вы специально со скобками дуру гоните, али как? Выражаясь Вашими формулами вопрос задаем так - ПОЧЕМУ: 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] будет выглядеть одинаково, здесь же мы наблюдаем "не одинаково"
--------------------
|
|
|
|
|
Dec 18 2006, 21:18
|
дятел
    
Группа: Свой
Сообщений: 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 то, тогда да, проблемма компиляции, а если совпадут, то тогда все в порядке, оптимизатор поработал
|
|
|
|
|
Dec 19 2006, 09:49
|
Гуру
     
Группа: Свой
Сообщений: 2 702
Регистрация: 14-07-06
Пользователь №: 18 823

|
Цитата(prottoss @ Dec 18 2006, 20:43)  Вы специально со скобками дуру гоните, али как? Выражаясь Вашими формулами вопрос задаем так - ПОЧЕМУ: Global_Value = a * b / c отличается от Local_Value = a * b / c; Скобки и привидения к типам в обоих равенствах можете расставить по собственному усмотрению и вкусу, НО одинаково Дуру? Отчасти А на конкретный вопрос - конкретный ответ : Да, сравнивать 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 и обратно, да, было пару выбрыков у ИАРа, но в целом это вполне нормальный инструмент. За приемлемую цену Все, пока автор не появится - ни строчки.
Сообщение отредактировал Dog Pawlowa - Dec 19 2006, 09:54
--------------------
Уходя, оставьте свет...
|
|
|
|
|
Dec 19 2006, 11:57
|
Местный
  
Группа: Свой
Сообщений: 235
Регистрация: 9-02-05
Пользователь №: 2 526

|
[/quote] Дуру? Отчасти А на конкретный вопрос - конкретный ответ : Да, сравнивать 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 и обратно, да, было пару выбрыков у ИАРа, но в целом это вполне нормальный инструмент. За приемлемую цену Все, пока автор не появится - ни строчки. [/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 строк. Большой расход памяти, задействованы почти все мыслимые и немыслимые аппаратные ресурсы и прерывания. Возможно, компиллятор столкнулся с какими то внутренними проблемами при обработке такого сложного проекта. Кстати, оптимизацию я полностью отключал. На это грешить не приходится. Вот такие дела!
|
|
|
|
|
Dec 19 2006, 15:15
|
Местный
  
Группа: Свой
Сообщений: 235
Регистрация: 9-02-05
Пользователь №: 2 526

|
Цитата(Oldring @ Dec 19 2006, 15:44)  Цитата(Sergio66 @ Dec 19 2006, 11:57)  Результат был неверным! Только размещение в памяти результирующей переменной дало эффект!!!
Так сразу после вычисленя выражения в регистрах результат правильный? Ошибки компилятора, конечно, встречаются - но в 90% случаев подозрения на ошибки компилятора не оправдываются, оказываясь ошибками программиста. Поэтому утверждение про ошибку компилятора требуют более серьезных аргументов, чем "написал так - не работает, написал иначе - работает". Да нет же! Пока я не переразместил переменную, все считалось неверно. И в регистрах был неверный результат.
|
|
|
|
|
Dec 19 2006, 19:10
|
Гуру
     
Группа: Свой
Сообщений: 2 702
Регистрация: 14-07-06
Пользователь №: 18 823

|
Цитата(Sergio66 @ Dec 19 2006, 15:15)  Да нет же! Пока я не переразместил переменную, все считалось неверно. И в регистрах был неверный результат. Тот самый случай, когда лучше один раз увидеть, чем сто раз услышать. А еще лучше совсем не видеть :-) Я вот недавно буфер для sprintf малый сделал, и пол-дня искал причину затирания переменной, все ошибки в компиляторе искал и стек считал... Нет?
--------------------
Уходя, оставьте свет...
|
|
|
|
|
Dec 20 2006, 13:33
|
Местный
  
Группа: Свой
Сообщений: 235
Регистрация: 9-02-05
Пользователь №: 2 526

|
Цитата(Oldring @ Dec 19 2006, 19:50)  int расширяется до long до умножения. Потом должна вызываться стандартная библиотеченая функция перемножения длинных целых. Потом код самой функции должен скопировать результат из регистров в глобальную переменную. Или не скопировать. Моя уверенность, что это проблема не рассчета, а интерпретации результата, укрепляется. Пожалуй, автору пора научиться разбираться в листингах, порождаемых компилятором. 1. Для тех кто умеет разбираться в листингах - подскажите пожалуйста, как правильно интерпретировать неправильный результат? Если в результате вычислений у меня получается неверное значение, оно же выводится на дисплей, мне придется объяснить пользователям как правильно интерпретировать такой результат который должен быть в пределах от 0,7 до 20, а его зашкаливает за 50 000!!! 2. К сожалению, я не могу выложить всеь код, т.к. это больше 10 000 строк. Одно могу сказать, что данный блок вычислений работал нормально, пока вычисления производились с глобальной переменной. Потом, для экономии памяти я сделал вычисления с локальной. Вот тут то все и началось. Когда компиллятор поместил эту локальную переменную в регистры. Как только я заставил разместить ее в памяти, все заработало.
|
|
|
|
|
Dec 20 2006, 15:06
|
Местный
  
Группа: Участник
Сообщений: 416
Регистрация: 18-04-06
Из: Челябинск
Пользователь №: 16 219

|
Цитата(Oldring @ Dec 18 2006, 19:08)  Цитата(Dog Pawlowa @ Dec 18 2006, 18:48)  Тогда мы по разному понимает слово "правильно". Я включал в это понятие учет возможности переполнения и максимальной независимости от констант. А Вы - нет?  Дело в том, что Билл написал просто чепуху про "естественную" свертку целочисленных констант перед вычислением выражения, а Вашего предложения я вообще почему-то не вижу в истории переписки. Так как так и не была озвучена информация про диапазоны операндов, хотелось бы все-таки увидеть, что именно Вы считаете "правильной" записью данного выражения, если это понятие "правильности" отличется от формальной правильности. Хотелось бы также узнать Ваше мнение по следующему вопросу: существует ли с точки зрения стандарта языка программирования С какая-либо разница между выражениями Код 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, хотя он в общем случае будет некорректным. Если мы хотим получить корректный результат, то мы должны задать требуемый порядок вычислений явным образом с помощью скобок. Можно также изменить тип констант по умочанию с использованием соответствующих суффиксов.
|
|
|
|
Guest_Serg79_*
|
Dec 20 2006, 15:22
|
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; Если нашел ошибку то локалезуй ее. И напиши маленькую функцию которая позваляет ее воспроизвести. А разговоры типа: в регистре не правильно а в памяти правельно, бред сивой кабылы.Может у Тебя там полнейший бред написан, а Ты пытаешся все на компилятор свалить.
|
|
|
|
|
Dec 20 2006, 16:15
|

Гуру
     
Группа: Свой
Сообщений: 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 – по крайней мере, можно будет подумать, что Вы учили чего-то в школе хотя бы с соседом по парте, а свой букварь курили дома…
--------------------
|
|
|
|
|
Dec 20 2006, 16:30
|

Гуру
     
Группа: Свой
Сообщений: 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 – по крайней мере, можно будет подумать, что Вы учили чего-то в школе хотя бы с соседом по парте, а свой букварь курили дома…
--------------------
Пишите в личку.
|
|
|
|
|
Dec 20 2006, 17:54
|
Гуру
     
Группа: Свой
Сообщений: 2 702
Регистрация: 14-07-06
Пользователь №: 18 823

|
Цитата(prottoss @ Dec 20 2006, 17:32)  Мда... Умные речи о значимости скобок не помогли... Финал - стоны зрителей, аншлаг, занавес закрывается Уличили А дизассемблер привести сложно? Или мы должны все бросить и посвятить вечер изучению ? Сами то смотрели?
--------------------
Уходя, оставьте свет...
|
|
|
|
|
Dec 20 2006, 18:05
|

Гуру
     
Группа: Свой
Сообщений: 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 Что и как он там насчитал, меня мало интересует, но факт остается фактом, насчитал он не правильно
--------------------
|
|
|
|
|
Dec 20 2006, 19:12
|

Гуру
     
Группа: Свой
Сообщений: 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.
--------------------
|
|
|
|
|
Dec 20 2006, 19:29
|
дятел
    
Группа: Свой
Сообщений: 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? скорее всего именно здесь собака порылась
|
|
|
|
|
Dec 20 2006, 20:04
|

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

|
Цитата(singlskv @ Dec 20 2006, 23:29)  ProttossНе поленился, проверил Ваш код сначала в голове, затем на симуляторе Так вот: Компилятор сделал РОВНО ТО, ЧТО ВЫ У НЕГО ПОПРОСИЛИ !!! Так что исчите апщибку в логике работы программы. Да, кстати, присоединяюсь к Цитата И, кстати, это так ведь задумано - при каждом вызове функции портить Pulse->Time?
скорее всего именно здесь собака порылась Какая все же ошибка? Объясните не разумному? 2 Oldring - функция вызывается после того, как прерывания запрещены. После всех вычислений прерывания разрешаются. В первом случае я возвращаю результат из функции и он правильный, во втором случае я возвращаю результат в указатель и результат, в итоге, не правильный
--------------------
|
|
|
|
|
Dec 20 2006, 20:23
|

Гуру
     
Группа: Свой
Сообщений: 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. Перед вызовом данной функции прерывание запрещается, после - разрешается.
--------------------
|
|
|
|
|
Dec 20 2006, 20:43
|

Гуру
     
Группа: Свой
Сообщений: 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);
} А теперь найдите отличия в смысле первого и второго, я вот что то не могу....
--------------------
|
|
|
|
|
Dec 21 2006, 17:09
|

Гуру
     
Группа: Свой
Сообщений: 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, (кстати, не впервой)особый респект Вам!
--------------------
|
|
|
|
|
Dec 21 2006, 17:39
|
Гуру
     
Группа: Свой
Сообщений: 2 702
Регистрация: 14-07-06
Пользователь №: 18 823

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

Гуру
     
Группа: Свой
Сообщений: 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 регистра?
Поздравляю. А глубина стека по умолчанию ничего не значит, так как кроме прерываний существуют вложенные функции, printfы и прочие мелкие радости ЯВУ. Как вообще можно оставлять 0x20, не представляю. А вот представьте, мил человек, никада в своей работе с АВРами не пользовался printf и прочими радостями ЯВУ (честно говря, я даже не знаю как это расшифровывается). Пользуюсь, обычно парой светодиодов, USART, ну и, естественно, отладчиком.
--------------------
|
|
|
|
|
Dec 21 2006, 18:44
|
Гуру
     
Группа: Свой
Сообщений: 2 702
Регистрация: 14-07-06
Пользователь №: 18 823

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

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

|
Цитата(Dog Pawlowa @ Dec 21 2006, 22:44)  Цитата(prottoss @ Dec 21 2006, 18:04)  А вот представьте, мил человек, никада в своей работе с АВРами не пользовался printf и прочими радостями ЯВУ (честно говря, я даже не знаю как это расшифровывается). Пользуюсь, обычно парой светодиодов, USART, ну и, естественно, отладчиком.
ЯВУ - это язык высокого уровня. "С", например. А так выглядит средний проект. Точнее, одна из его частей. Пары светодиодов, увы, бывает недостаточно...
Да хоть тыщща файлов в проекте - каждый модуль, ИМХО, должен быть законченной частью программы, и уметь функционировать отдельно...
--------------------
|
|
|
|
|
Dec 21 2006, 20:33
|

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

|
Цитата(prottoss @ Dec 21 2006, 19:02)  Да хоть тыщща файлов в проекте - каждый модуль, ИМХО, должен быть законченной частью программы, и уметь функционировать отдельно... В приведенной вами цитате объем стека обведен вообще-то. Насчет того, что вы printf'ом не пользуетесь и насколько помнится и JTAG'ом тоже.. Дык это сугубо ваше дело. Несомневаюсь, что некоторым удобнее отлаживать программы на бумаге или с помощью одного светодиода, что в итоге приводит к таким вот глюкам как рассматриваемые в этой ветке. А на что грешить с такой отладкой - на компилятор естессно, это все он - редиска - неправильно считает, не то сохраняет и т.п...
|
|
|
|
|
Dec 21 2006, 22:14
|
дятел
    
Группа: Свой
Сообщений: 1 681
Регистрация: 13-05-06
Из: Питер
Пользователь №: 17 065

|
Цитата(WHALE @ Dec 21 2006, 22:05)  Цитата В начале программы забивайте весь отведенный стек какой-нибудь сигнатурой ну а дальше контролите сколько затерли, или ручками приотладке или програмно(как удобнее)
зачем весь стек-то забивать?В CV есть удобная фича-ставится в старт-апе маркер конца стека и в случае глюков я его первым делом проверяю.Если на месте,родимый,значит дело не в обьеме стека. при отладке удобнее весь стек, сразу же видно, даже визуально чего там с ним творится ну и еще можно написать код который будет в реалтайме в глобальной переменной показывать максимальный размер стека за время работы, для отладки опять же очень удобно
|
|
|
|
Guest_Serg79_*
|
Dec 22 2006, 13:29
|
Guests

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

Гуру
     
Группа: Свой
Сообщений: 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 году прошло уже столько времени, что его синтаксический анализатор стал отшлифованным как брилиант. И грешить на него, покрайней мере, просто глупо. Ну, во первых, приятно слышать здоровый русский язык  А по поводу printf, использую его только в под х86 - удобная штука для форматированного вывода, но с того же 1970, скорее всего, такая же охочая до ресурсов как и универсальная - худа без добра не бывает и наоборот... Я в качестве printf использую собственные функции вывода строк в USART - у меня их, обычно, две - для чисел и для собсвенно строковых сообщений
--------------------
|
|
|
|
|
Dec 22 2006, 16:20
|

кекс
     
Группа: Свой
Сообщений: 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 не поможет никогда))) тут уж ничего не поможет. ;>
|
|
|
|
|
Dec 22 2006, 17:02
|

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

|
2 defunct Цитата Вы ставите в противовес JTAG'у Симулятор - это как секс по телефону. Сималятор и JTAG, ИМХО, это две разные вещи. Симулятор нужен для отладки кусков програмы даже без железа. А JTAG это инструмент отладки готового устройства. Умение использовать их в своей работе, в нужный момент, это и есть професионализм "програмиста-элекроника" к коим мы причисляем себя  .
Сообщение отредактировал Wild007 - Dec 22 2006, 17:03
--------------------
Ничто так не ограничивает полет мысли программиста, как компилятор
|
|
|
|
|
Dec 22 2006, 17:05
|

Гуру
     
Группа: Свой
Сообщений: 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
--------------------
|
|
|
|
|
Dec 22 2006, 17:25
|

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

|
Цитата(prottoss @ Dec 22 2006, 17:05)  Читайте внимательней посты, я говорил именно JTAG для МК AVR Это и к вам относится. Я тоже говорил о JTAG для AVR и сравнивал его с армовским. AVR'овский JTAG несколько отличается от других. Но так как вы его не пробовали, то вам и кажется, что он неполноценный и глючный как некоторые реализации для других МК. А на самом деле это не так. Поэтому еще раз повторюсь: Нельзя очень хорошо знать то, что никогда не пробовали на практике. Цитата И, ИМХО, не JTAG залог написания "хорошей" программы, а умение "правильно" составить алгоритм работы и структуру программы 1. Правильные алгоритмы, 2. Правильная структура программы Это необходимо но не достаточно для получения хорошей программы. Необходимо также как минимум: 3. Правильное всестороннее тестирование. 4. Правильная отладка (а вот тут нужны все возможные инструменты - в т.ч. и консоль, и отладчик)
|
|
|
|
|
  |
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|