Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: Прерывание PIO AT91SAM7A3
Форум разработчиков электроники ELECTRONIX.ru > Микроконтроллеры (MCs) > ARM
Balaganoff
Помогите разобраться, что не так. Хочу разобраться с прерываниями по изменению уровня на PIOA, прерывание должно наступать по нажатию джойстика. Код брал из примера,немного переработав для удобства. Не входит в прерывание и все тут.


Код
void main (void)
{
AT91F_PMC_EnablePeriphClock ( AT91C_BASE_PMC, 1 << AT91C_ID_PIOA );
AT91F_PIO_CfgOutput( AT91C_BASE_PIOA, LED_MASK );
AT91F_PIO_SetOutput( AT91C_BASE_PIOA, LED_MASK );
AT91F_PIO_CfgInput(AT91C_BASE_PIOA, SW3_MASK | SW4_MASK);


AT91F_AIC_ConfigureIt ( pAic, AT91C_ID_PIOA, PIO_INTERRUPT_LEVEL,AT91C_AIC_SRCTYPE_INT_HIGH_LEVEL, pio_c_irq_handler);
AT91F_PIO_InterruptEnable(AT91C_BASE_PIOA,SW4_MASK);
//* set the interrupt by software
AT91F_AIC_EnableIt (pAic, AT91C_ID_PIOA);

for (;;)
{}
}


// обработчик

void pio_c_irq_handler ( void )
{
int dummy;
count_int_pio++;

    
    AT91F_PIO_ClearOutput( AT91C_BASE_PIOA, LED2);
    delay_t (2000000);
    AT91F_PIO_SetOutput( AT91C_BASE_PIOA, LED2);
    delay_t (2000000);
  
    dummy =AT91C_BASE_PIOA->PIO_ISR;
    


}
Сергей Борщ
Цитата(Balaganoff @ Sep 17 2008, 17:21) *
Код
// обработчик
Это не весь обработчик. Показывайте, что сидит на векторе исключения, как осуществляется переход по адрусу из контроллера прерываний. Используете ли отладчик? Если да - не открыто ли окно с регистрами контроллера прерываний?
VSt&
можно просмотреть ассемблерный обработчик, начиная с IRQ_Handler_Entry;
внешние резисторные подтяжки могут оказаться не лишними;
AT91C_AIC_SRCTYPE_INT_HIGH_LEVEL иногда помогает заменить на AT91C_AIC_SRCTYPE_INT_POSITIVE_EDGE (по причинам, до конца мне не яснымsmile.gif);
+ сбрасывать флаги прерываний в периферии и AIC надежней вручную;

кроме того, бит PIO_ISR устанавливается (и генерит прерывание по & с PIO_IMR) на каждый фронт;
компилятор может выкинуть последнюю строчку из хэндлера, вычитывающую PIO_ISR при "оптимизации"
aaarrr
Цитата(VSt& @ Sep 18 2008, 06:43) *
AT91C_AIC_SRCTYPE_INT_HIGH_LEVEL иногда помогает заменить на AT91C_AIC_SRCTYPE_INT_POSITIVE_EDGE (по причинам, до конца мне не яснымsmile.gif);

Дык Вы бы уяснили для себя причины, прежде чем советы давать. Работать по фронту с внутренними источниками весьма черевато.

Цитата(VSt& @ Sep 18 2008, 06:43) *
кроме того, бит PIO_ISR устанавливается (и генерит прерывание по & с PIO_IMR) на каждый фронт;
компилятор может выкинуть последнюю строчку из хэндлера, вычитывающую PIO_ISR при "оптимизации"

Не может, ибо это volatile. Но можно просто написать AT91C_BASE_PIOA->PIO_ISR, без всяких dummy.
Balaganoff
Не сердитесь, если что не так, я хочу разобраться.

Использую JTAG SAM-ICE Segger + кит на AT91SAM7A3 + IAR 4.42A .
Окно с регистрами контроллера прерываний было, открыто,закрыл, все равно...
Флаги прерываний AIC и PIO сбросил вручную. менял AT91C_AIC_SRCTYPE_INT_HIGH_LEVEL
на AT91C_AIC_SRCTYPE_INT_POSITIVE_EDGE . Все тоже.

Объясните,пожалуйста,как все это происходит


Я не назначаю вручную адресс обработчика прерывания.Я так понимаю это должно делаеться автоматически. При возникновении прерывания от PIO,если оно разрешено, автоматом читается вектор
прерывания AIC_IVR и возвращается значение адресса обработчика соответсвующего прерывания,
который должен сидеть AIC_SVR[AT91C_ID_PIOA] для прерывания от PIO.

А как посмтотреть что сидит на векторе исключения,
как осуществляется переход по адрессу из контроллера прерываний?
Сергей Борщ
Ну вот. Зная компилятор можно продолжать.
Цитата(Balaganoff @ Sep 18 2008, 11:52) *
Использую JTAG SAM-ICE Segger + кит на AT91SAM7A3 + IAR 4.42A .
Тогда откройте окно дизассемблера и посмотрите на адрес 0x18. Там будет или что-то вроде LDR PC,[PC, #24] и тогда по адресу 0x38 будет лежать адрес обработчика, либо там будет LDR PC, [PC, #-3872] - тогда это как раз и есть чтение AIC_IVR и передача управления.
В певом случае вам надо в окне дизассемблера пролистать до адреса обработчика и посмотреть, что там находится. Если там заглушка типа "переход на себя", надо добавить в программу обработчик:
Код
#pragma vector = 0x18
__irq __arm void IRQ_Switch() {
    void (*Handler)() = (void(*)())AT91C_BASE_AIC->AIC_IVR;
    Handler();
    AT91C_BASE_AIC->AIC_EOICR = 0;                    // Reset AIC logic
}
Во втором случае надо ваш обработчик объявить как __irq __arm void pio_c_irq_handler ( void ) и добавить в его конце AT91C_BASE_AIC->AIC_EOICR = 0;

В любом случае полезно добавить в программу после настройки контроллера строчку AT91C_BASE_AIC->AIC_EOICR = 0; ибо если вы находясь в обработчике прерывания нажмете иконку сброса в отладчике, сброса контроллера прерываний не происходит и прерывания с таким и более низким приоритетом останутся запрещены.
И самое главное - я не вижу в вашей программе строчки __enable_interrupt();
Balaganoff
по Адрессу
irgvec :
0x18 содержится IRQ_Handler_Entry ; IRQ 0x90

по
IRQ_Handler_Entry:
0x90 SUB LR,LR, #0x4


Это наверное и есть обработчик,
А почему нет разрешения прерываний, ведь

// настроили прерывания,указали обработчик
AT91F_AIC_ConfigureIt ( pAic, AT91C_ID_PIOA,PIO_INTERRUPT_LEVEL, AT91C_AIC_SRCTYPE_INT_HIGH_LEVEL, pio_c_irq_handler);

// разрешили прерывания от маски SW4_MASK PIOA
AT91F_PIO_InterruptEnable(AT91C_BASE_PIOA,SW4_MASK);

// разрешили прерывания для контроллера прерываний от периферии AT91C_ID_PIOA
AT91F_AIC_EnableIt (pAic, AT91C_ID_PIOA);
aaarrr
Цитата(Balaganoff @ Sep 18 2008, 19:05) *
по
IRQ_Handler_Entry:
0x90 SUB LR,LR, #0x4
Это наверное и есть обработчик,

А дальше что (по коду)?
Сергей Борщ
Цитата(Balaganoff @ Sep 18 2008, 18:05) *
А почему нет разрешения прерываний, ведь
А кто будет сбрасывать бит I в CPSR?
Balaganoff
Подключил <intrinsics.h> и вставил
функцию __enable_interrupt().


Вот текст программы
Код
void pio_c_irq_handler ( void )
{
int dummy;

  

    count_int_pio++;

    
    
    AT91F_PIO_ClearOutput( AT91C_BASE_PIOA, LED2);
    delay_t (2000000);
    AT91F_PIO_SetOutput( AT91C_BASE_PIOA, LED2);
    delay_t (2000000);
  
    dummy =AT91C_BASE_PIOA->PIO_ISR;
    dummy=AT91C_BASE_AIC->AIC_ISR;
    dummy=AT91C_BASE_AIC->AIC_IECR;  

}




void main( void )

{


       AT91F_PMC_EnablePeriphClock ( AT91C_BASE_PMC, 1 << AT91C_ID_PIOA );
        
       AT91F_PIO_CfgOutput( AT91C_BASE_PIOA, LED_MASK );
       AT91F_PIO_SetOutput( AT91C_BASE_PIOA, LED_MASK );

    

       AT91F_PIO_CfgInput(AT91C_BASE_PIOA, SW4_MASK);
    
       AT91F_AIC_ConfigureIt ( AT91C_BASE_AIC, AT91C_ID_PIOA,PIO_INTERRUPT_LEVEL,            AT91C_AIC_SRCTYPE_INT_HIGH_LEVEL, pio_c_irq_handler);
    
        AT91C_BASE_AIC->AIC_EOICR = 0;
        
        __enable_interrupt();
        
        AT91F_PIO_InterruptEnable(AT91C_BASE_PIOA,SW4_MASK);
    
       AT91F_AIC_EnableIt (pAic, AT91C_ID_PIOA);  
      


for (;;)
    {

    }


}


Вот, то что в окне дизасемблерра
Код
IRQ_Handler_Entry:
  00000090  E24EE004  SUB          LR, LR, #0x4
  00000094  E92D4000  STMDB        SP!, {LR}
  00000098  E14FE000  MRS          LR, SPSR
  0000009C  E92D4000  STMDB        SP!, {LR}
  000000A0  E92D0001  STMDB        SP!, {R0}
  000000A4  E59FE048  LDR          LR, [PC, #+72]          ; [_?2 (0xF4)] =AIC_SMR (0xFFFFF000)
  000000A8  E59E0100  LDR          R0, [LR, #+256]
  000000AC  E58EE100  STR          LR, [LR, #+256]
  000000B0  E321F013  MSR          CPSR_c, #0x13
  000000B4  E92D500E  STMDB        SP!, {R1,R2,R3,R12,LR}
  000000B8  E1A0E00F  MOV          LR, PC
  000000BC  E12FFF10  BX           R0
  000000C0  E8BD500E  LDMIA        SP!, {R1,R2,R3,R12,LR}
  000000C4  E321F092  MSR          CPSR_c, #0x92
  000000C8  E59FE024  LDR          LR, [PC, #+36]          ; [_?2 (0xF4)] =AIC_SMR (0xFFFFF000)
  000000CC  E58EE130  STR          LR, [LR, #+304]
  000000D0  E8BD0001  LDMIA        SP!, {R0}
  000000D4  E8BD4000  LDMIA        SP!, {LR}
  000000D8  E16FF00E  MSR          SPSR_cxsf, LR
  000000DC  E8FD8000  LDMIA        SP!, {PC}^
AT91F_Default_FIQ_handler:
  000000E0  EAFFFFFE  B            AT91F_Default_FIQ_handler; 0xE0
AT91F_Default_IRQ_handler:
  000000E4  EAFFFFFE  B            AT91F_Default_IRQ_handler; 0xE4
Сергей Борщ
Цитата(Balaganoff @ Sep 19 2008, 16:39) *
Подключил <intrinsics.h> и вставил
функцию __enable_interrupt().
Хорошо. Пойдем от самого простого. Поставьте точку останова на адрес 0x18. Вы попадете на эту точку останова?
Balaganoff
При том же исходном тесте , если комментирую в основном тексте программы,после настройки контроллера прерываний строчку AT91C_BASE_AIC->AIC_EOICR = 0 , то в точку останова не попадаю.


Если оставляю AT91C_BASE_AIC->AIC_EOICR = 0 , то если запаскаю программу на выполнение -начинает прерываться постоянно вне зависимости от уровня сигнала от джойстика.
Ставлю точку на адрес 0x18, попадаю туда, далее пошагово попадаю на IRQ_Handler_Entry, а с нее попадаю на pio_c_irq_handler, далее по коду дохожу до "вечного цикла", причем джойстик я не трогаю, т.е. прервание не инициализирую.
Сергей Борщ
Цитата(Balaganoff @ Sep 22 2008, 15:56) *
При том же исходном тесте , если комментирую в основном тексте программы,после настройки контроллера прерываний строчку AT91C_BASE_AIC->AIC_EOICR = 0 , то в точку останова не попадаю.
Почему это происходит я писал в конце сообщения #6.
Цитата(Balaganoff @ Sep 22 2008, 15:56) *
Если оставляю AT91C_BASE_AIC->AIC_EOICR = 0 , то если запаскаю программу на выполнение -начинает прерываться постоянно вне зависимости от уровня сигнала от джойстика.
Простите, а какой уровень приходит на входы порта от джойстика в состоянии покоя?
Balaganoff
В состоянии покоя на входах джойстика уровни "1" , но эти уровни от встроенных Pull-up резисторов в котроллер.

При нажатии на джойстик происходит замыкание входа на "землю".
Сергей Борщ
Цитата(Balaganoff @ Sep 23 2008, 11:25) *
В состоянии покоя на входах джойстика уровни "1" , но эти уровни от встроенных Pull-up резисторов в котроллер.
А какого поведения вы ожидаете от контроллера после AT91F_AIC_ConfigureIt ( AT91C_BASE_AIC, AT91C_ID_PIOA,PIO_INTERRUPT_LEVEL, AT91C_AIC_SRCTYPE_INT_HIGH_LEVEL, pio_c_irq_handler);?
aaarrr
Цитата(Сергей Борщ @ Sep 23 2008, 13:29) *
А какого поведения вы ожидаете от контроллера после AT91F_AIC_ConfigureIt ( AT91C_BASE_AIC, AT91C_ID_PIOA,PIO_INTERRUPT_LEVEL, AT91C_AIC_SRCTYPE_INT_HIGH_LEVEL, pio_c_irq_handler);?

Здесь-то как раз все правильно: прерывание по pin level change, поэтому источник внутренний и уровень высокий.
Balaganoff
Прерывания же от PIO считаются внутренними, а "значения активных уровней внутренних прерываний для пользователя не имеют значения" .
Там только

1.AT91C_AIC_SRCTYPE_INT_HIGH_LEVEL ( поле SRCTYPE регистра AIC_SMR0[n] =0). В этом случае прерывается постоянно даже без его инициализации джойстиком .

2.AT91C_AIC_SRCTYPE_POSITIVE_EDGE (поле SRCTYPE регистра AIC_SMR0[n] =1). В этом случае в этом случае прерывания не наступает ни при каких действиях .

3.AT91C_AIC_SRCTYPE_HIGH_LEVEL (поле SRCTYPE регистра AIC_SMR0[n] =2) . Как в п 1.


4.AT91C_AIC_SRCTYPE_POSITIVE_EDGE поле SRCTYPE регистра AIC_SMR0[n] =3) . Как в п.2.
Сергей Борщ
Цитата(Balaganoff @ Sep 23 2008, 15:02) *
Прерывания же от PIO считаются внутренними, а "значения активных уровней внутренних прерываний для пользователя не имеют значения" .
Да, ступил, признаю. Тогда надо проверять, что подтяжки действительно включены, что сигнал от джойстика приходит на нужную ногу, смотреть, в каком виде хочет второй параметр AT91F_PIO_InterruptEnable() и чему равна SW4_MASK
Больше у меня версий нет. Вот этот код работает:
Код
void CMX_init()
{
    AT91C_BASE_PIOA->PIO_IER = (1UL<<19);    // FFSK_CLK
    // AIC
    AT91C_BASE_AIC->AIC_SMR[AT91C_ID_PIOA] = AT91C_AIC_SRCTYPE_INT_HIGH_LEVEL | AT91C_AIC_PRIOR_LOWEST + 1;
    AT91C_BASE_AIC->AIC_SVR[AT91C_ID_PIOA] = (uint32_t)CMX469_Int_Handler;

    AT91C_BASE_AIC->AIC_IECR = (1<<AT91C_ID_PIOA);    // enable ints
}


OS_INTERRUPT void CMX469_Int_Handler()
{
    OS::TISRW ISR;
    if(AT91C_BASE_PIOA->PIO_ISR & (1<<19))
    {
        FFSK_modem.put(signal(FFSK_DATA), ADC.RSSI());
    }
    AT91C_BASE_AIC->AIC_EOICR = 0;            // Reset AIC logic
}
Balaganoff
Ух! Все заработало. Сразу хочу сказать большое всем спасибо за помощь, ценные советы и оказанное внимание.

Какой же я олух!!! С прерываниями от джостика не получалось,в итоге я параллелно начал работать только с одной ногой PIOB2, чтобы последовательно и наглядно без всяких там масок типа SW4_MASK все разобрать (благо все пины они введены на колодку ).

В итоге что-то комментарил , что разкомментарил , а обработчик был один для двух версий программ!!!
В конце его сброс регистра статуса dummy =AT91C_BASE_PIOA->PIO_ISR, но я то-работал уже c PIOB.

Т.е. я думаю было так, я коротил PIOB2 на землю с влюченной подтяжкой, наступало прерывание как и должно быть,но в конце програмым обработки нужный регистр статуса не сбрасывался. И получается вновь вход в перрывание и так постоянно.

В итоге исправил dummy =AT91C_BASE_PIOA->PIO_ISR, на dummy =AT91C_BASE_PIOB->PIO_ISR

Так по памяти, может еще что где исправлял, но вроде бы так было.
aaarrr
Цитата(Balaganoff @ Sep 23 2008, 18:53) *
В итоге исправил dummy =AT91C_BASE_PIOA->PIO_ISR, на dummy =AT91C_BASE_PIOB->PIO_ISR

Исправьте еще dummy =AT91C_BASE_PIOB->PIO_ISR просто на AT91C_BASE_PIOB->PIO_ISR;
Не нужно плодить лишние переменные.
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.