rezident 0 6 июня, 2008 Опубликовано 6 июня, 2008 · Жалоба Изначально там были int. Я char поставил для экономии. Проверил. Не помогло (в смысле, если на int все поменять). Да и логики в этом не вижу...Логика тут простая - ваша экономия мнимая. Компилятор все равно приводит все вычисления к типу int, а временные переменные разместит в регистрах. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
alux 0 6 июня, 2008 Опубликовано 6 июня, 2008 · Жалоба Если это хоть как-то наведет на мысли... Глюк проявляется при входе при входе к определенным пунктам меню ("Редактирование параметров"). При этом редактирование и сохранение параметра идет как положено, за исключением того , что вместо кнопки "UP"-смещение на одно знакоместо происходит замена цифрой '6', а вместо "ESC", котороя возвращает в предыдущий п. меню происходит вставка цифры '2'. Некоторые пункты меню работают нормально. Напомню, что все это происходит, если вызвать функцию what_day(); Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
alux 0 6 июня, 2008 Опубликовано 6 июня, 2008 · Жалоба Это выходит за всякие рамки понимания и попахивает чертовщиной... Написал третью функцию вычисления дня недели: unsigned char what_day(unsigned int year, unsigned int month, unsigned int day) { unsigned char YEAR[]={0, 2, 3, 4}; unsigned char MONTH[]={0, 3, 3, 6, 1, 4, 6, 2, 5, 0, 3, 5}; unsigned char a, b, c, e, tmp; tmp = year - 1996; a = tmp & 3; b = (tmp >> 2) + (tmp & 0xfc); c = MONTH[month-1]; if((a == 0) && (month > 2)) c++; a = YEAR[a]; e = (a + b + c + day) % 7; return e; } Функцию переписал у Сергея Фролова. В ней нет тяжелых делений. Она работает. Но при вызове все равно приводит к тому глюку! :07: Ради эксперимента попробовал вместо этой функции вызвать какую-нибудь сложную математическую функцию , например решение квадратного уравнения и укруглением результата до 5 знака после запятой. //_____________________________________________________________________________ double quadratic(double a, double b, double c) { double d, x; d=b*b-4.*a*c; // Дискриминант if(d<0.) return 0; // Уравнение не имеет корней if(d==0.) x=-b/(2.*a); // Уравнение имеет один корень else x=(-b+sqrt(d))/(2.*a); // Уравнение имеет два корня, // но нужен только положительный return x; } //############################################################################# // round down a number to the decimal place given by power // e.g round(1.0256,-2) means round to 2nd decimal -> 1.03 //_____________________________________________________________________________ double round_to_pow(double x, int power) { double inc, xnew; inc = pow(10.0, (double)power); xnew = inc * (floor(x/inc + 0.5 + SMALL)); return(xnew); } //--------------------------------------------------------------------------- int main() { volatile unsigned char day; day = (unsigned char)round_to_pow(quadratic(100, 200, 3), -5); Так все нормально. В чем же может быть дело? Какие еще будут предложения? PS. Одна деталь. Если убрать из what_day() (обеих вариантов) операцию % 7, то глюк исчезает. Как это объяснить? В дополнение к функции решения кв. уравнения добавил функцию по расчету давления и температуры цифрового датчика давления. Там точно громоздкие вычисления. И все прошло (глюка не вызвало). А здесь простая операция деления по модулю... :cranky: Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
sKWO 0 6 июня, 2008 Опубликовано 6 июня, 2008 · Жалоба Но по какой-то непонятной причине вызов ее приводит к глюкам программы. В частности, при входе в пункт меню невозможно из него выйти, при этом программа реагирует не так как задумано. Должен сказать, что проект использует ОС (scmRTOS) и ОЗУ использовано на 90%. Контроллер Mega324P (2кБ ОЗУ). Отладочными средствами (JTAG) пользоваться не представляется возможным. Это похоже на переполнение стека. Но. Почему это происходит, если вызов достаточно простой функции вставить в начале функции main (до запуска ОС): int main() { what_day(2008, 6, 6); ..................... Больше нигде в процессах она не используется. Пробовал менять размеры CSTACK (100...200) и RSTACK (32...64). Не помогло, не в этом причина . из Вашего мэп CSTACK DATA 00000100 - 000001FF 100 dse 0 RSTACK DATA 00000200 - 0000023F 40 dse 0 Теперь мысль, может бредовая но всё-же- может Вы запретили компилятору какие-то регистры в которых компилятор хранит остаток от деления? не знаю как ИАР но в код вижине остаток хранится в 26 регистре. Пример для КВ //========================================================= void prog3(char ch) { ch=ch+2; ch=ch/3; ch=ch%3; } void prog4(char ch) { ch=ch/3; ch=ch%3; } ??? Лишние инструкции ??? Оптимальнее было-бы так - _prog3: LD R30,Y SUBI R30,-LOW(2) ST Y,R30 _prog4: LD R26,Y LDI R30,LOW(3) RCALL __DIVB21U ST Y,R30 LD R26,Y LDI R30,LOW(3) RCALL __MODB21U ST Y,R30 ADIW R28,1 RET Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Flasher 0 6 июня, 2008 Опубликовано 6 июня, 2008 · Жалоба Недавно в яре натолкнулся под авр использовал функцию % и прога пошла лесом... как только закоментировал строчку- все заработало. В листинге не разбирался- не было времени. Теперь жалею Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
alux 0 6 июня, 2008 Опубликовано 6 июня, 2008 (изменено) · Жалоба Не помогло, не в этом причина . из Вашего мэп CSTACK DATA 00000100 - 000001FF 100 dse 0 RSTACK DATA 00000200 - 0000023F 40 dse 0 Не понял. Что Вы имели в виду? Теперь мысль, может бредовая но всё-же- может Вы запретили компилятору какие-то регистры в которых компилятор хранит остаток от деления?Регистры я не трогаю. Заменил в функции операцию % 7 на -= 7: day = a + year + c + day;// % 7; while(day >= 7) day -= 7; return day; Проблема решилась частично: если вызвать эту функцию из main() , то глюк пропал. Но если вызвать ее из другой функции rtc_set_time(), то глюк имеет место быть... Не знаю что и думать. Варианты исчерпались. Пойду-ка я спать. PS2. Все! Наконец-то поборол глюк. Переписал в очередной раз функцию. Прям целая коллекция функций получилась :) unsigned char what_day(unsigned int year, unsigned int month, unsigned int date) { signed int c=0; unsigned char day; if((date>=1)&&(date<=31)&&(month>=1)&&(month<=12)&&(year>=1582)&&(year<=4903)) { if(month < 3) { month += 10; // Месяц январь или февраль? year -= 1; } else { month -= 2; // Остальные месяцы while(year >= 100) { c++; // Вычисляем столетие year -= 100; // Находим год в столетии } day = (unsigned char)((26*month-2)/10 + date + (year>>2) + year + (c>>2) - 2*c); while(day >= 7) day -= 7; // Вычисляем день недели } } return day; } Сейчас все работает как положено. Хотя неприятный осадок остался... Нет ответов на вопросы - почему такое произошло? Изменено 6 июня, 2008 пользователем alux Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
vet 0 7 июня, 2008 Опубликовано 7 июня, 2008 · Жалоба Посмотрите, какие регистры использует подпрограмма взятия остатка от деления: возможно, ошибка в несохранении компилятором значения регистра, используемого вызывающим кодом. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
sKWO 0 7 июня, 2008 Опубликовано 7 июня, 2008 · Жалоба Не понял. Что Вы имели в виду? использование функциями CSTACK и RSTACK я всегда смотрю в листинге. файл с расширением .lst. вот отрывок, удобно Maximum stack usage in bytes: Function CSTACK RSTACK -------- ------ ------ lcd_EN_toggle 0 2 lcd_command 1 2 -> lcd_waitcmd 1 2 -> lcd_write 1 2 -> lcd_waitcmd 1 2 а нащёт остатка от деления и рассположения в регистрах надо будет всё же подумать, может попробовать намного пошаманить с инлайн ассемблером ? Сообщите о результатах. Сам тоже попробую Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
AlexG_changed 0 7 июня, 2008 Опубликовано 7 июня, 2008 · Жалоба Если у вас scmRTOS, то размеры каких стеков вы крутите? Там ведь у каждого процесса свои стеки. PS: time.h использовал как-то. плохо совместимая с экономией памяти вещь. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Andreas1 1 7 июня, 2008 Опубликовано 7 июня, 2008 · Жалоба Недавно в яре натолкнулся под авр использовал функцию % и прога пошла лесом... как только закоментировал строчку- все заработало. В листинге не разбирался- не было времени. Теперь жалею Странно... Использовал скопипастленную с сахары функцию unsigned long DateTimeToLong(TDataTime* pdt){ byte month; word year; unsigned long c, ya; unsigned long res; month = BCDtoBin(pdt->Month); year = BCDtoBin(pdt->Year)+2000; if(month > 2){ month -= 3; }/*if*/ else { month += 9; year--; }/*else*/ c = (year / 100L); ya = (year - (100L * c)); res = (146097L * c)/4L + (1461L * ya) /4L + (153L * month + 2L)/5L + BCDtoBin(pdt->Date); pdt->Day=(res+2)%7; return (res - 720000L) * 1440L + (BCDtoBin(pdt->Hour) * 60L + BCDtoBin(pdt->Min)); } Никаких проблем, хотя оптимальности и экономии никакой. IAR AVR 4.30 Значения CSTACK и RSTACK по умолчанию, т.е минимальные. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
GetSmart 0 7 июня, 2008 Опубликовано 7 июня, 2008 · Жалоба Проблема решилась частично: если вызвать эту функцию из main() , то глюк пропал. Но если вызвать ее из другой функции rtc_set_time(), то глюк имеет место быть...Всё-таки не исключено, что стек. В любой другой функции стека меньше по сравнению с main, т.к. они вызываются после main. Если у вас scmRTOS, то размеры каких стеков вы крутите? Там ведь у каждого процесса свои стеки.Действие происходит ещё до запуска ОС, на этапе инициализаций. PS. Либо дайте уже нормальный листинг, либо этот телепатический сеанс затянется надолго. Нужен листинг этой "злополучной" функции и карту ОЗУ со стеком и рядом с ними. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
alux 0 7 июня, 2008 Опубликовано 7 июня, 2008 · Жалоба Нужен листинг этой "злополучной" функции и карту ОЗУ со стеком и рядом с ними. Рано обрадовался... Ночью не доглядел, забыл раскомментировать вызов этой функции. Поэтому решил, что проблема решена. Но только-что обнаружил, если вместо вызова функции вставить ее тело, то проблема исчезает. Выкладываю листинги и мап-файлы обоих вариантов (с вызовом функции и с вставленным телом функции). Вызов функции what_day() происходит из rtc_set_time(), которая в свою очередь вызывается из rtc_Init(). gluk.rar no_gluk.rar Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
GetSmart 0 7 июня, 2008 Опубликовано 7 июня, 2008 · Жалоба Вызов функции деления до сих пор присутствует. Ещё нужен листинг функций PROLOGUE6_L09, S_EC_MUL_L02, US_DIVMOD_L02. Ищется через поиск слова в директории со всеми листингами. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
alux 0 7 июня, 2008 Опубликовано 7 июня, 2008 · Жалоба Вызов функции деления до сих пор присутствует. day = (unsigned char)((26*month-2)/10 + date + (year>>2) + year + (c>>2) - 2*c); Выбросить операцию деления я же не могу - без нее не будет вычислять день. Ещё нужен листинг функций PROLOGUE6_L09, S_EC_MUL_L02, US_DIVMOD_L02. Ищется через поиск слова в директории со всеми листингами.Поиск по этим словам в директории list или проекта дает только вызовы этих функций: //NOTE: This module defines or uses C++ features that are not // accessible from assembler code. Assembling this file will // not produce an equivalent object file to the one produced // by the C++ compiler. EXTERN ?EPILOGUE_B6_L09 EXTERN ?EPILOGUE_B8_L09 EXTERN ?PROLOGUE6_L09 EXTERN ?PROLOGUE8_L09 .................... EXTERN ?US_DIVMOD_L02 .................. CALL ?US_DIVMOD_L02 Я не нашел нигде их определения. Судя по замечанию сверху - их ассемблерные инструкции не доступны. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
GetSmart 0 7 июня, 2008 Опубликовано 7 июня, 2008 (изменено) · Жалоба Тогда выкладывайте HEX-файл. Функция деления - она общая для деления и остатка, кстати. В MAP-файле с глюком указано, что последний адрес в раме = 087B, что вроде бы выходит за пределы чипа. Под рукой есть только описание mega323, у которого тоже 2 КБ и адреса в раме заканчиваются на 085F. Может файл линковки неправильный. Тоже выложите посмотреть. Изменено 7 июня, 2008 пользователем GetSmart Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться