Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: Стек ряпается
Форум разработчиков электроники ELECTRONIX.ru > Микроконтроллеры (MCs) > ARM
Master
Доброго времени суток!

Не знаю, как грамотно изложить пробему, но факт в том, что при выполнении очередной итерации цикла в функции происходит изменение дерева Call Stack в окне IAR Embedded Workbench (4.31). Соответственно функция, вызванная из main(), по выполнении указанного цикла обратно больше не возвращается, и заканчивается это дело прерыванием Undefined.
Бьюсь весь день, не могу понять, где собака рылась.
Ясно, что много неопределённостей, но может есть у кого мысли?

Железки: AT91SAM7S64, J-Link + RDI.

Добавлю на всякий случай окончание map-файла:
Код
  01  _LitobSmall
      | Stack used (prev) :  00000AC8
      | + function block  :  00000018
  <-Sub-tree of type: Function tree
    | Stack used          :  00000AE0




                ****************************************
                *                                      *
                *      SEGMENTS IN ADDRESS ORDER       *
                *                                      *
                ****************************************


SEGMENT              SPACE    START ADDRESS   END ADDRESS     SIZE  TYPE  ALIGN
=======              =====    =============   ===========     ====  ====  =====
INTVEC                             00000000 - 0000003F          40   com    2
ICODE                              00000040 - 00000253         214   rel    2
DIFUNCT                            00000254 - 0000027B          28   rel    2
CODE                               0000027C - 00006D57        6ADC   rel    2
INITTAB                            00006D58 - 00006D6F          18   rel    2
DATA_ID                            00006D70 - 00006F3B         1CC   rel    2
DATA_C                             00006F3C - 00007B18         BDD   rel    2
DATA_I                             00200000 - 002001CB         1CC   rel    2
DATA_Z                             002001CC - 00200CD5         B0A   rel    2
HEAP                               00200CD8 - 00201CD7        1000   rel    2
CSTACK                             00201CD8 - 002030D7        1400   stk    2
SVC_STACK                          002030D8 - 00203117          40   stk    2
IRQ_STACK                          00203118 - 00203517         400   stk    2
FIQ_STACK                          00203518 - 00203557          40   stk    2

                ****************************************
                *                                      *
                *        END OF CROSS REFERENCE        *
                *                                      *
                ****************************************

27 992 bytes of CODE  memory
13 654 bytes of DATA  memory
  3 521 bytes of CONST memory

Errors: none
Warnings: none
aaarrr
Что функция в цикле делает? Использует ли heap?
Master
Цитата(aaarrr @ May 24 2006, 17:50) *
Что функция в цикле делает? Использует ли heap?
Нет, не использует.
В данный момент функция выглядит вот так:
Код
unsigned char reset_sd(void)
{
    unsigned char resp = 0;
    BYTE    bRet = 0;

    #ifdef _DEBUG_ON_
        printf("\n\rReset CMD:  ");    
    #endif
    
    for( BYTE bCounter = 0; ( bCounter < 200 ) && ( bRet == 0 ); bCounter++ )        // try reset command 3 times if needed
    {
        SD_CS_OFF();
        //for( BYTE bCounterN = 0; bCounterN < 10; bCounterN++ )    // initialize clk signal to sync card
        _FF_spi(0xFF);
        _FF_spi(0xFF);
        _FF_spi(0xFF);
        _FF_spi(0xFF);
        _FF_spi(0xFF);
        _FF_spi(0xFF);
        _FF_spi(0xFF);
        _FF_spi(0xFF);
        _FF_spi(0xFF);
        _FF_spi(0xFF);
        resp = send_cmd( CMD0, 0 );
        for( BYTE bCounterN = 0; ( bCounterN < 200 ) && ( bRet == 0 ); bCounterN++ )
        {
            if (resp == 0x1)
            {
                SD_CS_OFF();
                    #ifdef _DEBUG_ON_
                    printf("OK!!!");
                #endif
                //SPCR = 0x50;
                MemCard.Speed( MC_BR );
                //return(1);
                bRet = 1;
            }
            else
                      resp = _FF_spi(0xFF);
        }
        if ( bRet == 0 ){
            #ifdef _DEBUG_ON_
                printf("ERROR!!!");
            #endif
            if (spi_speedset()==0)
            {
                SD_CS_OFF();
                continue;
                //return (0);
            }
        }
    }
    return bRet;
}

Чтоб не гадали, скажу, что это модифицированная функция из пакета FAT12_FAT16 для AVR.
GetSmart
Пардон, уже появилась процедура.
Master
Цитата(GetSmart @ May 24 2006, 18:22) *
Вообще-то мар-файла для поиска проблемы мало. Надо как минимум ещё кусок процедуры, из-за которой происходит зависание выкладывать. А ещё лучше весь проект. Тогда уже можно говорить по существу. А то гадать на кофекной гуще многим тут будет в облом.

Проект наверное выложить не получится (из таких-то соображений). Зависания как такового не происходит, происходит изменение дерева обратных вызовов. А вот почему портится стек, это и есть вопрос. Что вообще может вызвать порчу стека? Абсолютные адреса я не использую, к стеку напрямую не обращаюсь. Стек, как можно увидеть выше, огроменный. Собственно как и куча, которая здесь не используется. Вобщем, мистика какая-то.
aaarrr
Чудес не бывает. Для того, чтобы запороть стек совсем не обязательно использовать абсолютные адреса. Скорее всего, где-нибудь переполняется буфер или неправильно используется указатель.
Alex03
Иногда один стек на другой "налезает".
Проверьте размеры стеков IRQ, FIQ
Master
Цитата
Чудес не бывает. Для того, чтобы запороть стек совсем не обязательно использовать абсолютные адреса. Скорее всего, где-нибудь переполняется буфер или неправильно используется указатель.
Рою, но пока безуспешно.
Цитата(Alex03 @ May 24 2006, 19:21) *
Иногда один стек на другой "налезает".
Проверьте размеры стеков IRQ, FIQ
Вот фрагмент линковочного xcl-файла:
Код
//*************************************************************************
// Stack and heap segments.
//*************************************************************************
// in hexadecimal value!
-D_FIQ_STACK_SIZE=(2*8*4)
-D_IRQ_STACK_SIZE=(20*8*4)
-D_SVC_STACK_SIZE=(2*8*4)
-D_CSTACK_SIZE=(40*8*4)
-D_HEAP_SIZE=1000

-Z(DATA)HEAP+_HEAP_SIZE=RAMSTART-RAMEND
-Z(DATA)CSTACK+_CSTACK_SIZE=RAMSTART-RAMEND
-Z(DATA)SVC_STACK+_SVC_STACK_SIZE=RAMSTART-RAMEND
-Z(DATA)IRQ_STACK+_IRQ_STACK_SIZE=RAMSTART-RAMEND
-Z(DATA)FIQ_STACK+_FIQ_STACK_SIZE=RAMSTART-RAMEND
В этом я полагаюсь на компилятор. Если памяти не хватает, при компиляции выдаются сообщения. Пока не дошёл до того, чтобы проверять и в этом компилятор wink.gif
zltigo
Цитата(Master @ May 24 2006, 19:30) *
В этом я полагаюсь на компилятор. Если памяти не хватает, при компиляции выдаются сообщения.

Жесточайшее заблуждение по отношению к стеку. Думайте прежде всего сами о его размере, увеличивайте, измеряйте использованный. Компилятор это за Вас не сделает. Не по тому, что он
'плохой', а по тому, что невозможно.

Кстати, сможете ответить на вопрос - в каком стеке Вы при этом работаете?

Цитата
указанного цикла обратно больше не возвращается, и заканчивается это дело прерыванием Undefined.

Э... А может все с Undefined начинается. А?
aaarrr
Цитата(zltigo @ May 24 2006, 20:35) *
Э... А может все с Undefined начинается. А?

Не похоже: левый адрес возврата на стеке -> undefined.

Скорее глючит какая-нибудь из многочисленных вызываемых подпрограмм.
Я бы закомментил все, а затем подлючал по одной...
zltigo
Цитата(aaarrr @ May 24 2006, 20:06) *
Не похоже: левый адрес возврата на стеке -> undefined.

??? По каким признакам сделан вывод?

Или стек переключился. Причем для Undefined он не инициализирован в принципе.
Master
Цитата(zltigo @ May 24 2006, 21:27) *
Цитата(aaarrr @ May 24 2006, 20:06) *

Не похоже: левый адрес возврата на стеке -> undefined.

??? По каким признакам сделан вывод?

Или стек переключился. Причем для Undefined он не инициализирован в принципе.

Уважаемый zltigo! Прежде всего я благодарю Вас за участие и внимание к моей проблеме. Но вынужден заметить, что по-моему дело не в размере/расположении/названии стека - всё это я разумеется могу выдать (кстати по поводу оценки размера стека можно почитать здесь, где Andy Mozzhevilov также озадачивался данной проблемой).
Со своей стороны надеюсь, что Вы, давая совет считать размер стека, сами выполняли данную процедуру и готовы поделиться своими успехами.
Я вероятно не уточнил, каким образом меняется дерево Call Stack: адрес начала стека ведёт себя подобающим образом (тобишь при заходе в функцию уменьшается, при выходе - увеличивается), но вот содержимое стека после выполнения одной из итераций цикла частично меняется. По каким причинам это происходит, для меня - загадка.

P.S. Сегодня силы кончились, но я успел установить с помощью окна дизассемблера, что стек портится на операции POP {R4,R5,R6,R7}...
GetSmart
Цитата
P.S. Сегодня силы кончились, но я успел установить с помощью окна дизассемблера, что стек портится на операции POP {R4,R5,R6,R7}...

Прикольно. Команда POP Rx вообще не влияет на стек. То есть читает, но не пишет.
aaarrr
Ztigo, Вы меня удивляете, честное слово!
Цитата(zltigo @ May 24 2006, 21:27) *
??? По каким признакам сделан вывод?

А какие еще причины обычно заставляют процессор натолкнуться на неизвестную инструкцию,
кроме ошибочной загрузки PC или непосредственной порчи кода программы? Тем более, Master в первом посте написал, что у него портится стек.

Цитата(zltigo @ May 24 2006, 21:27) *
Или стек переключился. Причем для Undefined он не инициализирован в принципе.

Как переключился? Сам по себе?
zltigo
Цитата(aaarrr @ May 24 2006, 22:33) *
Как переключился? Сам по себе?

Из-за смены Mode. У Undifined Exception, естественно свой стек. Это естественно излагается как
вариант, если верить автору в его уверенности, что со стеком 'все хорошо' и отсутствии
информации (на тот момент) что такое "изменилось дерево..."

Цитата(Master @ May 24 2006, 21:01) *
что по-моему дело не...

Черканите, когда станет совсем уж не по Вашему. Про оценку размера стека я уже , помнится, уже однажды общался на этом форуме. Можете воспользоваться поиском.
Master
Цитата
Черканите, когда ...

Уважаемый zltigo! Ваша точка зрения ясна. Большое спасибо за помощь.
sapID
Для поиска таких ошибок удобно использовать Hardware Breakpoint (J-Link/MT-Link).
Ставишь брык на запись в область памяти и отладка остановится прямо на команде записи. Затем изучаешь Registers/Disassembler
Master
Цитата(sapID @ May 25 2006, 07:29) *
Для поиска таких ошибок удобно использовать Hardware Breakpoint (J-Link/MT-Link).
Ставишь брык на запись в область памяти и отладка остановится прямо на команде записи. Затем изучаешь Registers/Disassembler

Ну типа спасибо smile.gif Поймите правильно, я некоторое представление об отладке программ имею. В моём случае нужен бряк по изменению содержимого памяти. Подскажите лучше, как RDI по такому условию настроить.
spf
Цитата(Master @ May 25 2006, 00:01) *
Уважаемый zltigo! Прежде всего я благодарю Вас за участие и внимание к моей проблеме. Но вынужден заметить, что по-моему дело не в размере/расположении/названии стека - всё это я разумеется могу выдать (кстати по поводу оценки размера стека можно почитать здесь, где Andy Mozzhevilov также озадачивался данной проблемой).
Со своей стороны надеюсь, что Вы, давая совет считать размер стека, сами выполняли данную процедуру и готовы поделиться своими успехами.

Как то раз были у нас в конторе заскоки со стеком у MB90, долго маялись, в конце концов написал калькулятор стека (кстати, глядя на который Andy Mozzhevilov и затевал разговор) - calc_stk, но и это не помогло, дальнейший тЩательный разбор полетов выявил наезд стека на переменную, теперь все гуд.

Это к тому что не стоит отбрасывать ни одну версию до последнего ... и проверять все очень тщательно и свежей/трезвой головой.
Master
Цитата(spf @ May 25 2006, 13:49) *
Как то раз были у нас в конторе заскоки со стеком у MB90, долго маялись, в конце концов написал калькулятор стека (кстати, глядя на который Andy Mozzhevilov и затевал разговор) - calc_stk, но и это не помогло, дальнейший тЩательный разбор полетов выявил наезд стека на переменную, теперь все гуд.

В чём оказалась проблема? Если можно, расскажите поподробнее. У меня, чувствуется, похожая ситуация.
Причём отследить мне так и не удалось, на какой операции программа вылетает в exception, т.к. происходит это в разных местах. Поставлю бряк в одном месте, она вылетает в другом. В общем, мистика да и только.


Цитата(Master @ May 25 2006, 15:36) *
В чём оказалась проблема? Если можно, расскажите поподробнее. У меня, чувствуется, похожая ситуация.

Получил подтверждение тому, что что-то лезет на стек: вставил задержку перед выводом в DebugUnit, и стек слетать перестал. Посему очень интересен Ваш способ выхода из данной ситуации.
spf
Цитата(Master @ May 25 2006, 18:45) *
В чём оказалась проблема? Если можно, расскажите поподробнее. У меня, чувствуется, похожая ситуация.
Причём отследить мне так и не удалось, на какой операции программа вылетает в exception, т.к. происходит это в разных местах. Поставлю бряк в одном месте, она вылетает в другом. В общем, мистика да и только.

Проблема была банальная - "ручное" распределение памяти с небольшим наездом отдельных частей друг на друга, корни проблемы росли из особенностей архитектуры процессора. Все до мелочей уже не помню, в общих чертах: проц с регистровыми банками в памяти, на каком-то вираже добавили обработчик прерывания с индивидуальным банком регистров, некоторое время все работало, потом стали наворачивать, стало падать, но не стабильно... в конце концов выяснилось что при выполнении определенной функции в одной из задач и вызове в это время того самого прерывания (достаточно редкое) портилась пара адресов возврата. Т.к. банк регистров наезжал на стек задачи (или наоборот), а из-за "ручного" распределения памяти не было сообщения об ошибке при линковке, то операции с некоторыми регистрами в прерывании приводили к изменению значений в памяти, куда смотрел и указатель стека задачи. Память была "забита" под завязку, поэтому увеличивать стеки особы было некуда, да и калькулятор подтверждал что уже есть небольшой запас...
sapID
Цитата(Master @ May 25 2006, 15:00) *
Цитата(sapID @ May 25 2006, 07:29) *

Для поиска таких ошибок удобно использовать Hardware Breakpoint (J-Link/MT-Link).
Ставишь брык на запись в область памяти и отладка остановится прямо на команде записи. Затем изучаешь Registers/Disassembler

Ну типа спасибо smile.gif Поймите правильно, я некоторое представление об отладке программ имею. В моём случае нужен бряк по изменению содержимого памяти. Подскажите лучше, как RDI по такому условию настроить.

Типа, всегда пожалуйста smile.gif
Про RDI точно не знаю - работаю в режиме J-Link
Там в отладке появляется менюшка J-Link -> Watchpoints
Дальше все интуитивно понятно, кроме поля Mask - его, обычно, надо ставить 0xFFFFFFFF
Alex03
Цитата(spf @ May 26 2006, 10:05) *
Проблема была банальная - "ручное" распределение памяти с небольшим наездом отдельных частей друг на друга...


smile.gif Не я один такой. smile.gif
Тут недавно тоже у себя обнаружил ошибку в ручном распределение внешней памяти LPC2292 на 4 кольцевых FIFO буфера.
Все 4 буфера пересекались и длины не соответствовали.

Когда нашёл волосы дыбом встали как я такое понаписать мог (в 3-х макросах запутался)!

А ведь как-то год работало. smile.gif
Видимо потому как данные в буфер попадали на очень небольшое время.
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.