rezident 0 June 6, 2008 Posted June 6, 2008 · Report post Изначально там были int. Я char поставил для экономии. Проверил. Не помогло (в смысле, если на int все поменять). Да и логики в этом не вижу...Логика тут простая - ваша экономия мнимая. Компилятор все равно приводит все вычисления к типу int, а временные переменные разместит в регистрах. Quote Share this post Link to post Share on other sites More sharing options...
alux 0 June 6, 2008 Posted June 6, 2008 · Report post Если это хоть как-то наведет на мысли... Глюк проявляется при входе при входе к определенным пунктам меню ("Редактирование параметров"). При этом редактирование и сохранение параметра идет как положено, за исключением того , что вместо кнопки "UP"-смещение на одно знакоместо происходит замена цифрой '6', а вместо "ESC", котороя возвращает в предыдущий п. меню происходит вставка цифры '2'. Некоторые пункты меню работают нормально. Напомню, что все это происходит, если вызвать функцию what_day(); Quote Share this post Link to post Share on other sites More sharing options...
alux 0 June 6, 2008 Posted June 6, 2008 · Report post Это выходит за всякие рамки понимания и попахивает чертовщиной... Написал третью функцию вычисления дня недели: 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: Quote Share this post Link to post Share on other sites More sharing options...
sKWO 0 June 6, 2008 Posted June 6, 2008 · Report post Но по какой-то непонятной причине вызов ее приводит к глюкам программы. В частности, при входе в пункт меню невозможно из него выйти, при этом программа реагирует не так как задумано. Должен сказать, что проект использует ОС (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 Quote Share this post Link to post Share on other sites More sharing options...
Flasher 0 June 6, 2008 Posted June 6, 2008 · Report post Недавно в яре натолкнулся под авр использовал функцию % и прога пошла лесом... как только закоментировал строчку- все заработало. В листинге не разбирался- не было времени. Теперь жалею Quote Share this post Link to post Share on other sites More sharing options...
alux 0 June 6, 2008 Posted June 6, 2008 (edited) · Report post Не помогло, не в этом причина . из Вашего мэп 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; } Сейчас все работает как положено. Хотя неприятный осадок остался... Нет ответов на вопросы - почему такое произошло? Edited June 6, 2008 by alux Quote Share this post Link to post Share on other sites More sharing options...
vet 0 June 7, 2008 Posted June 7, 2008 · Report post Посмотрите, какие регистры использует подпрограмма взятия остатка от деления: возможно, ошибка в несохранении компилятором значения регистра, используемого вызывающим кодом. Quote Share this post Link to post Share on other sites More sharing options...
sKWO 0 June 7, 2008 Posted June 7, 2008 · Report post Не понял. Что Вы имели в виду? использование функциями 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 а нащёт остатка от деления и рассположения в регистрах надо будет всё же подумать, может попробовать намного пошаманить с инлайн ассемблером ? Сообщите о результатах. Сам тоже попробую Quote Share this post Link to post Share on other sites More sharing options...
AlexG_changed 0 June 7, 2008 Posted June 7, 2008 · Report post Если у вас scmRTOS, то размеры каких стеков вы крутите? Там ведь у каждого процесса свои стеки. PS: time.h использовал как-то. плохо совместимая с экономией памяти вещь. Quote Share this post Link to post Share on other sites More sharing options...
Andreas1 1 June 7, 2008 Posted June 7, 2008 · Report post Недавно в яре натолкнулся под авр использовал функцию % и прога пошла лесом... как только закоментировал строчку- все заработало. В листинге не разбирался- не было времени. Теперь жалею Странно... Использовал скопипастленную с сахары функцию 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 по умолчанию, т.е минимальные. Quote Share this post Link to post Share on other sites More sharing options...
GetSmart 0 June 7, 2008 Posted June 7, 2008 · Report post Проблема решилась частично: если вызвать эту функцию из main() , то глюк пропал. Но если вызвать ее из другой функции rtc_set_time(), то глюк имеет место быть...Всё-таки не исключено, что стек. В любой другой функции стека меньше по сравнению с main, т.к. они вызываются после main. Если у вас scmRTOS, то размеры каких стеков вы крутите? Там ведь у каждого процесса свои стеки.Действие происходит ещё до запуска ОС, на этапе инициализаций. PS. Либо дайте уже нормальный листинг, либо этот телепатический сеанс затянется надолго. Нужен листинг этой "злополучной" функции и карту ОЗУ со стеком и рядом с ними. Quote Share this post Link to post Share on other sites More sharing options...
alux 0 June 7, 2008 Posted June 7, 2008 · Report post Нужен листинг этой "злополучной" функции и карту ОЗУ со стеком и рядом с ними. Рано обрадовался... Ночью не доглядел, забыл раскомментировать вызов этой функции. Поэтому решил, что проблема решена. Но только-что обнаружил, если вместо вызова функции вставить ее тело, то проблема исчезает. Выкладываю листинги и мап-файлы обоих вариантов (с вызовом функции и с вставленным телом функции). Вызов функции what_day() происходит из rtc_set_time(), которая в свою очередь вызывается из rtc_Init(). gluk.rar no_gluk.rar Quote Share this post Link to post Share on other sites More sharing options...
GetSmart 0 June 7, 2008 Posted June 7, 2008 · Report post Вызов функции деления до сих пор присутствует. Ещё нужен листинг функций PROLOGUE6_L09, S_EC_MUL_L02, US_DIVMOD_L02. Ищется через поиск слова в директории со всеми листингами. Quote Share this post Link to post Share on other sites More sharing options...
alux 0 June 7, 2008 Posted June 7, 2008 · Report post Вызов функции деления до сих пор присутствует. 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 Я не нашел нигде их определения. Судя по замечанию сверху - их ассемблерные инструкции не доступны. Quote Share this post Link to post Share on other sites More sharing options...
GetSmart 0 June 7, 2008 Posted June 7, 2008 (edited) · Report post Тогда выкладывайте HEX-файл. Функция деления - она общая для деления и остатка, кстати. В MAP-файле с глюком указано, что последний адрес в раме = 087B, что вроде бы выходит за пределы чипа. Под рукой есть только описание mega323, у которого тоже 2 КБ и адреса в раме заканчиваются на 085F. Может файл линковки неправильный. Тоже выложите посмотреть. Edited June 7, 2008 by GetSmart Quote Share this post Link to post Share on other sites More sharing options...