Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: Ошибка IAR или чтото еще?
Форум разработчиков электроники ELECTRONIX.ru > Микроконтроллеры (MCs) > AVR
Страницы: 1, 2
Oldring
Цитата(prottoss @ Dec 20 2006, 20:04) *
В первом случае я возвращаю результат из функции и он правильный, во втором случае я возвращаю результат в указатель и результат, в итоге, не правильный


Ключевое слово - "в итоге". Так найдите то место, в котором результат в конце концов портится. Судя по тому, что, как Вы пишете, код вычисления выражения одинаковый - и результат сразу после вычисления выражения одинаковый. Так что ищите глюк где-то в другом месте.
prottoss
Цитата(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. Перед вызовом данной функции прерывание запрещается, после - разрешается.
Oldring
Пожалуйста, приведите два варианта кода отдельно - когда работает и когда не работает. Сейчас сложно понять, какой именно вариант не работает.
prottoss
Цитата(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);

}




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


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

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



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

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

А глубина стека по умолчанию ничего не значит, так как кроме прерываний существуют вложенные функции, printfы и прочие мелкие радости ЯВУ. Как вообще можно оставлять 0x20, не представляю. unsure.gif
prottoss
Цитата(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, ну и, естественно, отладчиком.
Dog Pawlowa
Цитата(prottoss @ Dec 21 2006, 18:04) *
А вот представьте, мил человек, никада в своей работе с АВРами не пользовался printf и прочими радостями ЯВУ (честно говря, я даже не знаю как это расшифровывается). Пользуюсь, обычно парой светодиодов, USART, ну и, естественно, отладчиком.

ЯВУ - это язык высокого уровня. "С", например.
А так выглядит средний проект. Точнее, одна из его частей.
Пары светодиодов, увы, бывает недостаточно...
Нажмите для просмотра прикрепленного файла
prottoss
Цитата(Dog Pawlowa @ Dec 21 2006, 22:44) *
Цитата(prottoss @ Dec 21 2006, 18:04) *

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

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

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

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

Насчет того, что вы printf'ом не пользуетесь и насколько помнится и JTAG'ом тоже.. Дык это сугубо ваше дело. Несомневаюсь, что некоторым удобнее отлаживать программы на бумаге или с помощью одного светодиода, что в итоге приводит к таким вот глюкам как рассматриваемые в этой ветке. А на что грешить с такой отладкой - на компилятор естессно, это все он - редиска - неправильно считает, не то сохраняет и т.п...
WHALE
[/quote]
В начале программы забивайте весь отведенный стек какой-нибудь сигнатурой
ну а дальше контролите сколько затерли, или ручками приотладке или програмно(как удобнее)
[/quote]
зачем весь стек-то забивать?В CV есть удобная фича-ставится в старт-апе маркер конца стека и в случае глюков я его первым делом проверяю.Если на месте,родимый,значит дело не в обьеме стека.
singlskv
Цитата(WHALE @ Dec 21 2006, 22:05) *
Цитата

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

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

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

Вот и Я о том же.
С момента изобретения языка 'C' в 1970 году прошло уже столько времени, что его синтаксический анализатор стал отшлифованным как брилиант. И грешить на него, покрайней мере, просто глупо.
prottoss
Цитата(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 - у меня их, обычно, две - для чисел и для собсвенно строковых сообщений
defunct
Цитата(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 не поможет никогда)))

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

Сималятор и JTAG, ИМХО, это две разные вещи.
Симулятор нужен для отладки кусков програмы даже без железа. А JTAG это инструмент отладки готового устройства. Умение использовать их в своей работе, в нужный момент, это и есть професионализм "програмиста-элекроника" к коим мы причисляем себя smile.gif .
prottoss
Цитата(defunct @ Dec 22 2006, 20:20) *
Цитата(prottoss @ Dec 22 2006, 14:57) *

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

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

И, ИМХО, не JTAG залог написания "хорошей" программы, а умение "правильно" составить алгоритм работы и структуру программы
defunct
Цитата(prottoss @ Dec 22 2006, 17:05) *
Читайте внимательней посты, я говорил именно JTAG для МК AVR

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

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

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

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

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

Необходимо также как минимум:
3. Правильное всестороннее тестирование.
4. Правильная отладка (а вот тут нужны все возможные инструменты - в т.ч. и консоль, и отладчик)
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.