Перейти к содержанию
    

DAbt_Handler?A или проблема с прерыванием?

Проект для 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;
}

Вообщем что делать ума не приложу.

Что то в уме смутно бродит про защиту выполнения кода от прерывания. Есть ли такое? и поможет ли?

Изменено пользователем GenEv

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Эээээ. Стек неконтролирую. А как узнать его размер?

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

 

и как узнать что его не хватает?

а)В самых вложенных функциях (в прерываниях) проверять текущее значение указателя стека

б)Заполнить какими-то "уникальными" значениями, например 0х12345678 и проверять что они не все затерлись

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Вот настройки стека:

2a2352c67326235d45.jpg

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

f65c7a43070c880ccf.jpg

А вот это было при зависании:

13ce7aeafc7810c027.jpg

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Как я понял, это Keil, я с ним не знаком и оболочкой не пользуюсь. Могу только предложить:

1. Увеличить стеки IRQ и Supervisor в два раза. Посмотреть пройдут ли зависания.

2. Смотреть стек в прерывании через оболочку не совсем удобно, т.к. во первых надо бы смотреть на значение указателя стека и сравнивать его с отведенной под стек областью. А во вторых, при переходе в прерывание указатель стека меняет свое значение на "указатель стека в прерывании" и ни как не связан со стеком в обычном режиме.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Если действительно проблема со стеком - его размером - то вылетание программы раз в несколько минут (часов/дней) то тогда стека "в основном хватает", но при определенной комбинации вызовов его не хватает.

Я в таких случаях подставляю в ABT_handler вывод в RS232 всего содержимого стеков и регистров для каждого режима.

По полученному дампу стека и регистров можно вычислить, хватает ли его.

 

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

 

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

У Вас нигде адреса не вычисляются?

 

А еще модификация глобальных переменных в функции, в то время как IRQ тоже ее модифицирует.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Еще DABT может происходить из попыток доступа к данным по невыровненным адресам

 

Уверены? :)

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

А вот это было при зависании:

Abort LR (R14) смотрите. Он приведет вас ровно в ту точку где произошел DAbt.

Потом в дизассемблере смотрите место с адресом DAbt'a, а там уже и причину не трудно будет найти.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Уверены? :)

Да.

Если камень соответствует спецификации.

А то были какие-то непонятки с LPC. Тут на форуме обсуждалось.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Да.

Если камень соответствует спецификации.

Берем спецификацию, т.е. документ имени 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.
И никаких абортов.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.

Гость
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...