Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: DAbt_Handler?A или проблема с прерыванием?
Форум разработчиков электроники ELECTRONIX.ru > Микроконтроллеры (MCs) > ARM
GenEv
Проект для LPC2294.
Вообщем проблема не понятная.
Смысл такой. Есть основной цикл. по прерыванию набирается пакет байтов.
Так вот если убрать
AppBrake = GetAppBrake();
//____________________________________________ Опрос углов _____________________________
Azimut.Angle = GetAngle() + Azimut.Corr;
Elev.Angle = 14.5 + Elev.Corr;

... // Рсчеты, расчеты

т.е. различные расчеты, то все работает отлично, стоит только добавить фунцию GetAngle(); так возникает проблема DAbt_Handler?A, причем все время по разному. Обмен может происходить 30 секунд, минуту, но все равно срабатывает прерывание по DAbt_Handler?A.
Код
while(1)
    {
AppBrake = GetAppBrake();
//____________________________________________ Опрос углов _____________________________
    Azimut.Angle = GetAngle() + Azimut.Corr;
    Elev.Angle = 14.5 + Elev.Corr;

... // Рсчеты, расчеты
        
//___________________________________________ Обработка команд по RS _________________
        switch (Action) // !!!!!!
        {
        case PACK:
            IDCommand(PackNumber);
            Action = FALSE;
            for (cl = 0; cl < 20; cl ++) PackRead[cl] = 0;
            break;                                      
        case ERR_CHECK:
            WriteData(PackRead[1], "d", 1);
            Action = FALSE;
            for (cl = 0; cl < 20; cl ++) PackRead[cl] = 0;
            break;
        case ERR_PACK:
            WriteData(PackRead[1], "e", 1);
            Action = FALSE;
            for (cl = 0; cl < 20; cl ++) PackRead[cl] = 0;
            break;
        }
    }


Функция GetAngle()
Код
float GetAngle()
{
    USHORT *Adress;
    USHORT go, to;
    int s, c, turn;
    float res;
    c = 0;
    go = 0;
    to = 0;
    //======================  Азимут  =====================================================
    
    Adress = 0x82020000;        //грубый отсчет
    IOCLR1 = SP(21);
    go = *Adress;
    IOSET1 = SP(21);    

    Adress = 0x82040000;        //точный отсчет
    IOCLR1 = 0x200000;
    to = *Adress;
    IOSET1 = 0x200000;
    
    s = (go & 0x7FF) - (to >> 5);
    if (s > 1500) c = 2047;
    if (s < -1500) c = - 2047;
    
    go = go & 0xF800;
    res = go + (to >> 5) + c;
    turn = IOPIN0;
    turn = (turn >> 19) & 1;
    if ( (turn == 1) && (res < 50000) ) res += 65536;
    res = res * 360 / 65536;
    return res - 5;
}

Вообщем что делать ума не приложу.
Что то в уме смутно бродит про защиту выполнения кода от прерывания. Есть ли такое? и поможет ли?
amw
А стека хватает?
GenEv
Эээээ. Стек неконтролирую. А как узнать его размер? и как узнать что его не хватает?
Alexey Bishletov
Цитата(GenEv @ Jul 24 2007, 09:30) *
Эээээ. Стек неконтролирую. А как узнать его размер?

Обычно размер указывается в линкерном скрипте, формат зависит от компилятора

Цитата(GenEv @ Jul 24 2007, 09:30) *
и как узнать что его не хватает?

а)В самых вложенных функциях (в прерываниях) проверять текущее значение указателя стека
б)Заполнить какими-то "уникальными" значениями, например 0х12345678 и проверять что они не все затерлись
GenEv
Вот настройки стека:

Вот такую информацию дает Call Stack при брекпойнте в прерывание по UART0.

А вот это было при зависании:
Alexey Bishletov
Как я понял, это Keil, я с ним не знаком и оболочкой не пользуюсь. Могу только предложить:
1. Увеличить стеки IRQ и Supervisor в два раза. Посмотреть пройдут ли зависания.
2. Смотреть стек в прерывании через оболочку не совсем удобно, т.к. во первых надо бы смотреть на значение указателя стека и сравнивать его с отведенной под стек областью. А во вторых, при переходе в прерывание указатель стека меняет свое значение на "указатель стека в прерывании" и ни как не связан со стеком в обычном режиме.
amw
Если действительно проблема со стеком - его размером - то вылетание программы раз в несколько минут (часов/дней) то тогда стека "в основном хватает", но при определенной комбинации вызовов его не хватает.
Я в таких случаях подставляю в ABT_handler вывод в RS232 всего содержимого стеков и регистров для каждого режима.
По полученному дампу стека и регистров можно вычислить, хватает ли его.

Вероятно тут может помочь JTAG отладка.

Еще DABT может происходить из попыток доступа к данным по невыровненным адресам, или по несуществующим.
У Вас нигде адреса не вычисляются?

А еще модификация глобальных переменных в функции, в то время как IRQ тоже ее модифицирует.
abcdefg
Цитата(amw @ Jul 24 2007, 16:52) *
Еще DABT может происходить из попыток доступа к данным по невыровненным адресам


Уверены? smile.gif
defunct
Цитата(GenEv @ Jul 24 2007, 10:44) *
А вот это было при зависании:

Abort LR (R14) смотрите. Он приведет вас ровно в ту точку где произошел DAbt.
Потом в дизассемблере смотрите место с адресом DAbt'a, а там уже и причину не трудно будет найти.
GenEv
Увеличил InterruptMode в 2 раза и все заработало!!!!
Спасибо всем!!!!
amw
Цитата(abcdefg @ Jul 24 2007, 20:18) *
Уверены? smile.gif

Да.
Если камень соответствует спецификации.
А то были какие-то непонятки с LPC. Тут на форуме обсуждалось.
Сергей Борщ
Цитата(amw @ Jul 25 2007, 17:53) *
Да.
Если камень соответствует спецификации.
Берем спецификацию, т.е. документ имени ARM под номером ARM DDI0029E, ARM7TDMI Data Sheet. Стр. 4-29, инструкции LDR, STR:
Цитата
A word load (LDR) will normally use a word aligned address. However, an address offset from a word boundary will cause the data to be rotated into the register so that the addressed byte occupies bits 0 to 7. This means that half-words accessed at offsets 0 and 2 from the word boundary will be correctly loaded into bits 0 through 15 of the register.
Стр. 4-41, инструкции LDM, STM:
Цитата
The address should normally be a word aligned quantity and non-word aligned addresses do not affect the instruction. However, the bottom 2 bits of the address will appear on A[1:0] and might be interpreted by the memory system.
И никаких абортов.
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.