Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: lpc2148 + eint0 == интересная вестч
Форум разработчиков электроники ELECTRONIX.ru > Микроконтроллеры (MCs) > ARM
diwil
Уважаемые господа.
Я сталкнулся с проблемой странного поведения процессора при обработке 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 не задействована. Все кварцы генерят...

Вопрос - где грабли?
(Вариант - дребезг - не предлагать!)
Что надо еще прочитать?

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


VICVectAddr = 0;
и это там указано...
кажется что грабли в другом...
zltigo
Цитата(diwil @ Jul 3 2007, 13:17) *
Один раз ногой удается дернуть...

Сдается мне, что это Вам показалось sad.gif. Зависает он при инициализации.
При инициализации именно 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);                                  
}
diwil
Цитата(zltigo @ Jul 3 2007, 15:33) *
Сдается мне, что это Вам показалось sad.gif. Зависает он при инициализации.
При инициализации именно 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 ничего про это нет...
zltigo
Цитата(diwil @ Jul 3 2007, 14:54) *
А где можно эту эррата почитать?
Ту, что у филипса вытаскиваю -0 ничего про это нет...

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

Полная smile.gif инструкция:
Код
    // 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.

Помогло?
diwil
Цитата(zltigo @ Jul 3 2007, 16:06) *
Не совсем понял - errata по на филипсе есть. А вот еще одной шаманской записи для обеспечения работоспособности именно INT0 в ней нет - это я уже сам пару лет назад, когда использовал все четыре, в полный рост... и почти случайно нашел.
Помогло-то?


примного благодарствую.
Я еще не пробовал - вечером скажу...
А в эрратах ничего подобного нет...
Хотя нашел.. для 2129...

спасибо еще раз. буду пробовать
zltigo
Цитата(diwil @ Jul 3 2007, 15:20) *
Хотя нашел.. для 2129...

Я наступал на 2124, после этого такая процедура используется (не проверял без нее) для всех LPC, включая и 2148.
diwil
Значится разобрался... Этого бага в 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



Просто я при описании процедуры обработчика прерывания лоханулся с возвратом, за что и поплатился.
GetSmart
Цитата(zltigo @ Jul 3 2007, 18:06) *
Код
    // 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а не работает!

Мне, кстати, внутри прерывания приходится инвертировать полярность его следующего срабатывания и такой изврат заметно тормозит.
zltigo
Цитата(GetSmart @ Nov 7 2007, 16:53) *
Сделал как здесь и... помогло! Причём без пункта 3а не работает!

Рад. Незнаю, как я до этого дошел - похоже печенкой чего-то додумал, но эффект был забавный sad.gif
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.