|
Прерывание PIO AT91SAM7A3 |
|
|
|
Sep 17 2008, 14:21
|
Участник

Группа: Участник
Сообщений: 23
Регистрация: 24-08-07
Пользователь №: 30 034

|
Помогите разобраться, что не так. Хочу разобраться с прерываниями по изменению уровня на 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;
}
|
|
|
|
|
Sep 18 2008, 02:43
|
Частый гость
 
Группа: Свой
Сообщений: 101
Регистрация: 3-08-06
Из: Екатеринбург
Пользователь №: 19 275

|
можно просмотреть ассемблерный обработчик, начиная с IRQ_Handler_Entry; внешние резисторные подтяжки могут оказаться не лишними; AT91C_AIC_SRCTYPE_INT_HIGH_LEVEL иногда помогает заменить на AT91C_AIC_SRCTYPE_INT_POSITIVE_EDGE (по причинам, до конца мне не ясным  ); + сбрасывать флаги прерываний в периферии и AIC надежней вручную; кроме того, бит PIO_ISR устанавливается (и генерит прерывание по & с PIO_IMR) на каждый фронт; компилятор может выкинуть последнюю строчку из хэндлера, вычитывающую PIO_ISR при "оптимизации"
Сообщение отредактировал VSt& - Sep 18 2008, 02:59
|
|
|
|
|
Sep 18 2008, 07:52
|
Гуру
     
Группа: Свой
Сообщений: 10 713
Регистрация: 11-12-04
Пользователь №: 1 448

|
Цитата(VSt& @ Sep 18 2008, 06:43)  AT91C_AIC_SRCTYPE_INT_HIGH_LEVEL иногда помогает заменить на AT91C_AIC_SRCTYPE_INT_POSITIVE_EDGE ( по причинам, до конца мне не ясным ); Дык Вы бы уяснили для себя причины, прежде чем советы давать. Работать по фронту с внутренними источниками весьма черевато. Цитата(VSt& @ Sep 18 2008, 06:43)  кроме того, бит PIO_ISR устанавливается (и генерит прерывание по & с PIO_IMR) на каждый фронт; компилятор может выкинуть последнюю строчку из хэндлера, вычитывающую PIO_ISR при "оптимизации" Не может, ибо это volatile. Но можно просто написать AT91C_BASE_PIOA->PIO_ISR, без всяких dummy.
|
|
|
|
|
Sep 18 2008, 08:52
|
Участник

Группа: Участник
Сообщений: 23
Регистрация: 24-08-07
Пользователь №: 30 034

|
Не сердитесь, если что не так, я хочу разобраться.
Использую 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.
А как посмтотреть что сидит на векторе исключения, как осуществляется переход по адрессу из контроллера прерываний?
|
|
|
|
|
Sep 18 2008, 09:30
|

Гуру
     
Группа: Модераторы
Сообщений: 8 455
Регистрация: 15-05-06
Из: Рига, Латвия
Пользователь №: 17 095

|
Ну вот. Зная компилятор можно продолжать. Цитата(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();
--------------------
На любой вопрос даю любой ответ"Write code that is guaranteed to work, not code that doesn’t seem to break" ( C++ FAQ)
|
|
|
|
|
Sep 18 2008, 15:05
|
Участник

Группа: Участник
Сообщений: 23
Регистрация: 24-08-07
Пользователь №: 30 034

|
по Адрессу 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);
|
|
|
|
|
Sep 19 2008, 13:39
|
Участник

Группа: Участник
Сообщений: 23
Регистрация: 24-08-07
Пользователь №: 30 034

|
Подключил <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
|
|
|
|
|
Sep 22 2008, 12:56
|
Участник

Группа: Участник
Сообщений: 23
Регистрация: 24-08-07
Пользователь №: 30 034

|
При том же исходном тесте , если комментирую в основном тексте программы,после настройки контроллера прерываний строчку AT91C_BASE_AIC->AIC_EOICR = 0 , то в точку останова не попадаю.
Если оставляю AT91C_BASE_AIC->AIC_EOICR = 0 , то если запаскаю программу на выполнение -начинает прерываться постоянно вне зависимости от уровня сигнала от джойстика. Ставлю точку на адрес 0x18, попадаю туда, далее пошагово попадаю на IRQ_Handler_Entry, а с нее попадаю на pio_c_irq_handler, далее по коду дохожу до "вечного цикла", причем джойстик я не трогаю, т.е. прервание не инициализирую.
|
|
|
|
|
Sep 22 2008, 13:56
|

Гуру
     
Группа: Модераторы
Сообщений: 8 455
Регистрация: 15-05-06
Из: Рига, Латвия
Пользователь №: 17 095

|
Цитата(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 , то если запаскаю программу на выполнение -начинает прерываться постоянно вне зависимости от уровня сигнала от джойстика. Простите, а какой уровень приходит на входы порта от джойстика в состоянии покоя?
--------------------
На любой вопрос даю любой ответ"Write code that is guaranteed to work, not code that doesn’t seem to break" ( C++ FAQ)
|
|
|
|
|
Sep 23 2008, 08:25
|
Участник

Группа: Участник
Сообщений: 23
Регистрация: 24-08-07
Пользователь №: 30 034

|
В состоянии покоя на входах джойстика уровни "1" , но эти уровни от встроенных Pull-up резисторов в котроллер.
При нажатии на джойстик происходит замыкание входа на "землю".
|
|
|
|
|
Sep 23 2008, 09:29
|

Гуру
     
Группа: Модераторы
Сообщений: 8 455
Регистрация: 15-05-06
Из: Рига, Латвия
Пользователь №: 17 095

|
Цитата(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);?
--------------------
На любой вопрос даю любой ответ"Write code that is guaranteed to work, not code that doesn’t seem to break" ( C++ FAQ)
|
|
|
|
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|