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

lpc2148 + eint0 == интересная вестч

Уважаемые господа.

Я сталкнулся с проблемой странного поведения процессора при обработке eint0.

Прерывание от кнопки. По спаду импульса.

Инициализация такая:

 

{

PINSEL1_bit.P0_16=0x1;

EXTINT = 0x01;

VPBDIV = 0x0;

EXTMODE = 0x01;

VPBDIV = 0x00;

VPBDIV = 0x00; // one-fourth

VICIntSelect &= ~(1<<VIC_EINT0);

VICVectAddr3 = (uint32_t)&HwInterrupt0Interrupt;

VICVectCntl3 = 0x20 | VIC_EINT0;for external 0

VICIntEnable = (1<<VIC_EINT0);

}

 

Причем VPBDIV = 0x00; вокруг других операций , между ними и их количество на работу не влияют.

 

Обработчик прерываний выглядит так:

 

volatile int intsrc;

 

__irq HwInterrupt0Interrupt()

{

EXTINT = 1;

VICVectAddr = 0;

intsrc = 1<<VIC_EINT0;

}

 

Компилер - GCC. режим АРМ для всего кода и код генерится правильный (я глазками смотрю, да и другие прерывания рботают - УАРТ, ТАЙМЕР и т.д.)

 

Далее у меня бесконечный цикл в котором я анализирую intsrc и если она имеет флажок, то дергаю ногой процессора вот так:

 

while(1)

{

PCON = 1;

if (intsrc & (1<<VIC_EINT0))

{

FIO0CLR = 1 << 20;

intsrc & ~(1<<VIS_EINT0);

FIO0SET = 1 << 20;

}

}

 

И что интересно:

Один раз ногой удается дернуть, а вот потом процессор сваливается в непредсказуемое состояние, которое не является обработчиком прерывания. Создается впечатление, что он вваливается в бесконечный цикл, но не понятно где...

Отладчиком не посмотреть - это уже впаяно в изделие.

PLL не задействована. Все кварцы генерят...

 

Вопрос - где грабли?

(Вариант - дребезг - не предлагать!)

Что надо еще прочитать?

 

Заранее благодарен,

Дима

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


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

У атмела SAM7S наступал на такие грабли: 8-миуровневый приоритет прерываний, несколько прерываний разных приоритетов, 2 от 2-х таймеров, 1 от USART, 1 от АЦП. Каждое прерывание после сброса выполнялось всего 1 раз. Для возобновления работы приходилось ресетить NRSTом. Глюк был в том, что надо прописать в один регистр, называвшийся End Of Interrupt Control Register (EOICR), любое число. Это давало знать контроллеру прерывания, что данное прерывание обработано. Когда вставил в конце прерывания EOICR = 1, все стало работать пока не надоест в любых приоритетах. Нет ли у LPCшного контроллера прерываний подобного наворота? Сам с ними не знаком, работал только на SAM7S.

Успехов.

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


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

У атмела SAM7S наступал на такие грабли: 8-миуровневый приоритет прерываний, несколько прерываний разных приоритетов, 2 от 2-х таймеров, 1 от USART, 1 от АЦП. Каждое прерывание после сброса выполнялось всего 1 раз. Для возобновления работы приходилось ресетить NRSTом. Глюк был в том, что надо прописать в один регистр, называвшийся End Of Interrupt Control Register (EOICR), любое число. Это давало знать контроллеру прерывания, что данное прерывание обработано. Когда вставил в конце прерывания EOICR = 1, все стало работать пока не надоест в любых приоритетах. Нет ли у LPCшного контроллера прерываний подобного наворота? Сам с ними не знаком, работал только на SAM7S.

Успехов.

 

VICVectAddr = 0;

и это там указано...

кажется что грабли в другом...

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


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

Один раз ногой удается дернуть...

Сдается мне, что это Вам показалось :(. Зависает он при инициализации.

При инициализации именно INT0 по фронту есть еще дополнительный баг и рабочий вариант инициализации выглядит так:

{
PINSEL1_bit.P0_16=0x1; 
EXTINT = 0x01;

VPBDIV = 0x0;           
EXTMODE = 0x01;
         
VPBDIV= 0x01; // Это по Errata
VPBDIV = 0x00;      // А это если INT0 настраивается, для остальных необязательно                    

VPBDIV = 0x00;    // one-fourth  
VICIntSelect &= ~(1<<VIC_EINT0);        
VICVectAddr3 = (uint32_t)&HwInterrupt0Interrupt;        
VICVectCntl3 = 0x20 | VIC_EINT0;for external 0                  
VICIntEnable = (1<<VIC_EINT0);                                  
}

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


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

Сдается мне, что это Вам показалось :(. Зависает он при инициализации.

При инициализации именно INT0 по фронту есть еще дополнительный баг и рабочий вариант инициализации выглядит так:

{
PINSEL1_bit.P0_16=0x1; 
EXTINT = 0x01;

VPBDIV = 0x0;           
EXTMODE = 0x01;
         
VPBDIV= 0x01; // Это по Errata
VPBDIV = 0x00;      // А это если INT0 настраивается, для остальных необязательно                    

VPBDIV = 0x00;    // one-fourth  
VICIntSelect &= ~(1<<VIC_EINT0);        
VICVectAddr3 = (uint32_t)&HwInterrupt0Interrupt;        
VICVectCntl3 = 0x20 | VIC_EINT0;for external 0                  
VICIntEnable = (1<<VIC_EINT0);                                  
}

 

 

А где можно эту эррата почитать?

Ту, что у филипса вытаскиваю -0 ничего про это нет...

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


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

А где можно эту эррата почитать?

Ту, что у филипса вытаскиваю -0 ничего про это нет...

Не совсем понял - errata по на филипсе есть. А вот еще одной шаманской записи для обеспечения работоспособности именно INT0 в ней нет - это я уже сам пару лет назад, когда использовал все четыре, в полный рост... и почти случайно нашел как заставить работать.

 

Полная :) инструкция:

    // Set edle-sensetive Mode
    // The steps involved in the configuration of the EXTMODE and/or EXTPOLAR would be as follow:-
    // 1. Write 0x00 to VPBDIV
    // 2. Write the desired value to EXTMODE or EXTPOLAR register
    // 3. Write the same value to VPBDIV
    // 3a. Write 0x00 to VPBDIV (additional step for INT0 )
    // 4. Restore the VPBDIV to the previously saved value or simply write to the register again
    //    with the desired value.

    VPBDIV = 0;                 // 1.
    ii = EXTMODE & ( EXTMODE_EXTMODE0|EXTMODE_EXTMODE1|EXTMODE_EXTMODE2|EXTMODE_EXTMODE3);  // Get Curent Value
    ii |= EXTMODE_EXTMODE0;
    EXTMODE = ii;             // 2.
    VPBDIV  = ii;             // 3.
    VPBDIV  = 0;              // 3a!!!
    VPBDIV  = configBUS_CLK; // 4.

3a. Пункт от себя добавлен, остальное цитирует errata.

 

Помогло?

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


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

Не совсем понял - errata по на филипсе есть. А вот еще одной шаманской записи для обеспечения работоспособности именно INT0 в ней нет - это я уже сам пару лет назад, когда использовал все четыре, в полный рост... и почти случайно нашел.

Помогло-то?

 

примного благодарствую.

Я еще не пробовал - вечером скажу...

А в эрратах ничего подобного нет...

Хотя нашел.. для 2129...

 

спасибо еще раз. буду пробовать

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


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

Хотя нашел.. для 2129...

Я наступал на 2124, после этого такая процедура используется (не проверял без нее) для всех LPC, включая и 2148.

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


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

Значится разобрался... Этого бага в 2148 нет. Т.е. работает следующий код:

  EXTINT = 15;
  EXTMODE = 15;
  EXTPOLAR = 4; // all falling except timepulse

  VICIntSelect &= ~(VIC_BIT(VIC_EINT0) | VIC_BIT(VIC_EINT1));// | VIC_BIT(VIC_EINT2));// | VIC_BIT(VIC_EINT3));
  VICIntEnable = VIC_BIT(VIC_EINT0) | VIC_BIT(VIC_EINT1);// | VIC_BIT(VIC_EINT2);// | VIC_BIT(VIC_EINT3);

  VICVectCntl5 = VIC_ENABLE | VIC_EINT0;
  VICVectAddr5 = (uint32_t)extint0;    // address of the ISR

  VICVectCntl6 = VIC_ENABLE | VIC_EINT1;
  VICVectAddr6 = (uint32_t)extint1;    // address of the ISR

  EXTINT = 15;   // а вот без этого не работает почему-то ???
  VICIntSelect &= ~(VIC_BIT(VIC_EINT2) | VIC_BIT(VIC_EINT3));
  VICIntEnable = VIC_BIT(VIC_EINT2) | VIC_BIT(VIC_EINT3);

  VICVectCntl1 = VIC_ENABLE | VIC_EINT2;
  VICVectAddr1 = (uint32_t)extint2;    // address of the ISR

  VICVectCntl13 = VIC_ENABLE | VIC_EINT3;
  VICVectAddr13 = (uint32_t)extint3;    // address of the ISR

 

 

Просто я при описании процедуры обработчика прерывания лоханулся с возвратом, за что и поплатился.

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


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

    // Set edle-sensetive Mode
    // The steps involved in the configuration of the EXTMODE and/or EXTPOLAR would be as follow:-
    // 1. Write 0x00 to VPBDIV
    // 2. Write the desired value to EXTMODE or EXTPOLAR register
    // 3. Write the same value to VPBDIV
    // 3a. Write 0x00 to VPBDIV (additional step for INT0 )
    // 4. Restore the VPBDIV to the previously saved value or simply write to the register again
    //    with the desired value.

    VPBDIV = 0;                 // 1.
    ii = EXTMODE & ( EXTMODE_EXTMODE0|EXTMODE_EXTMODE1|EXTMODE_EXTMODE2|EXTMODE_EXTMODE3);  // Get Curent Value
    ii |= EXTMODE_EXTMODE0;
    EXTMODE = ii;             // 2.
    VPBDIV  = ii;             // 3.
    VPBDIV  = 0;              // 3a!!!
    VPBDIV  = configBUS_CLK; // 4.

3a. Пункт от себя добавлен, остальное цитирует errata.

 

Помогло?

Только что встал на такие же грабли в LPC2294 с EINT0. Сделал как здесь и... помогло! Причём без пункта 3а не работает!

 

Мне, кстати, внутри прерывания приходится инвертировать полярность его следующего срабатывания и такой изврат заметно тормозит.

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


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

Сделал как здесь и... помогло! Причём без пункта 3а не работает!

Рад. Незнаю, как я до этого дошел - похоже печенкой чего-то додумал, но эффект был забавный :(

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


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

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

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

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

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

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

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

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

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

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