|
вопрос про прерывания, AT91SAM7X |
|
|
|
Dec 6 2007, 11:06
|
Участник

Группа: Новичок
Сообщений: 49
Регистрация: 14-02-07
Пользователь №: 25 346

|
Судя по даташиту, в начале обработки прерывания необходимо прочитать регистр AIC_IVR, как они выражаются, это the entry point of the interrupt handling.. В конце обработки прерывания необходимо прописать что-нибудь в регистр AIC_EOICR, т.к. это the exit point of the interrupt handling..
Так вот.. до недавнего времени мне удавалось вполне успешно обрабатывать прерывания (TC, CAN, ADC), не читая AIC_IVR, а читая соответствующие статусные регистры перриферии, сбрасывающие флаг, свидетельствующий о произошедшем прерывании и прописывая какое-то значение в AIC_EOICR..
Однако при обработке прерываний от PIO и IRQ0, IRQ1 я натолкнулся на некоторые трудности.. Например, при настройке IRQ0 на срабатывание по высокому уровню без чтения AIC_IVR программа зацикливается на функции прерывания.. Когда же произвожу чтение AIC_IVR, функция прерывания выполняется один раз и больше ни на что не реагирует (кроме ресета..)
В связи с этим вопрос: необходимо ли читать регистр AIC_IVR и если да, то в каких случаях?
|
|
|
|
|
Dec 6 2007, 11:19
|

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

|
Цитата(Sergei_K @ Dec 6 2007, 13:06)  В связи с этим вопрос: необходимо ли читать регистр AIC_IVR Да, необходимо. Цитата и если да, то в каких случаях? Вы же в самом начале привели цитату - как только вошли в обработчик прерывания, чтобы определить источник прерывания. Один раз у вас срабатывает скорее всего потому, что вы не пишете EOICR в конце обработчика.
--------------------
На любой вопрос даю любой ответ"Write code that is guaranteed to work, not code that doesn’t seem to break" ( C++ FAQ)
|
|
|
|
|
Dec 6 2007, 14:02
|
Гуру
     
Группа: Свой
Сообщений: 10 713
Регистрация: 11-12-04
Пользователь №: 1 448

|
Добавлю немного. AIC_IVR лучше читать сразу при переходе на вектор IRQ: Код 00000018 ldr pc, [pc, #-0xf20] ; IRQ для того контроллер прерываний и положили в верхние адреса. Если не записать AIC_EOICR в конце процедуры обработки прерывания, то AIC перестанет реагировать на прерывания с более низким приоритетом.
|
|
|
|
|
Apr 22 2009, 14:39
|
Участник

Группа: Участник
Сообщений: 31
Регистрация: 20-10-08
Из: Нижний Новгород
Пользователь №: 41 078

|
У меня почти такая же проблема: второй раз не обрабатывает прерывание и докучи перезаписывает один из существующих массивов (программа не зависает, если это важно). Камень AT91RM9200 Инициализация (сделана отдельной функцией): Код void IntInit(void) {AT91F_PIO_CfgInput(AT91C_BASE_PIOA, DataInput); AT91F_PIO_CfgPeriph(AT91C_BASE_PIOA, DataInput, 0); AT91F_AIC_ConfigureIt (AT91C_BASE_AIC, AT91C_ID_IRQ2, 7, AT91C_AIC_SRCTYPE_INT_EDGE_TRIGGERED, PIOA_Handler); // prio AT91F_AIC_EnableIt (AT91C_BASE_AIC, AT91C_ID_IRQ2); } Обработчик: Код extern int p[33]; static void PIOA_Handler( void ) { AT91C_BASE_AIC->AIC_IVR; AT91C_BASE_PIOB->PIO_SODR |= ( DDS_P2_MODULATION ); /* PB7 - выв 87 AT91RM9200 */ AT91C_BASE_PIOB->PIO_CODR |= ( DDS_P2_MODULATION ); /* PB7 are output */ AT91C_BASE_AIC->AIC_ICCR |= ( 1UL<<AT91C_ID_IRQ2 );//clear interrupt AT91C_BASE_AIC->AIC_EOICR = 0; } Строки, касающиеся прерывания из main(): Код ... IntInit(); AT91C_BASE_PIOB->PIO_SODR |= ( DDS_P2_MODULATION ); /* PB7 - выв 87 AT91RM9200 */ __enable_interrupt(); delay(5000); AT91C_BASE_PIOB->PIO_CODR |= ( DDS_P2_MODULATION ); /* PB7 are output */ ...
Сообщение отредактировал Antokha - Apr 22 2009, 15:16
|
|
|
|
|
Apr 22 2009, 17:24
|
Участник

Группа: Участник
Сообщений: 31
Регистрация: 20-10-08
Из: Нижний Новгород
Пользователь №: 41 078

|
Цитата Во-первых, не нужно читать write-only регистры. Если это про AIC_IVR, то это я наверно на автомате набрал, читая pdf на контроллер. Вообще-то этот регистр уже наверно считался до входа в эту процедуру обработки: cstartup.s: Код ... __irq_handler: ldr PC,[PC,#-0xF20] ;; IRQ .... Цитата Во-вторых, какой смысл использовать прерывания по фронту для внутреннего источника в данном случае? AT91C_AIC_SRCTYPE_INT_EDGE_TRIGGERED в файле AT91RM9200.h описан как: #define AT91C_AIC_SRCTYPE_INT_EDGE_TRIGGERED ((unsigned int) 0x1 << 5) // (AIC) Internal Sources Code Label Edge triggered, т.е. в соответствии с pdf на контроллер это и прерывание по фронту для внутреннего источника так и прерывание по спаду для внешнего прерывания.
|
|
|
|
|
Apr 22 2009, 17:32
|
Гуру
     
Группа: Свой
Сообщений: 10 713
Регистрация: 11-12-04
Пользователь №: 1 448

|
Цитата(Antokha @ Apr 22 2009, 21:24)  Если это про AIC_IVR... Нет, это про PIO_SODR, PIO_CODR, AIC_ICCR и т.д. Цитата(Antokha @ Apr 22 2009, 21:24)  AT91C_AIC_SRCTYPE_INT_EDGE_TRIGGERED в файле AT91RM9200.h описан как... Смысл какой? Источник у Вас внутренний, так зачем работать по фронту, рискуя огрести проблемы (что, судя по всему, и случилось)?
|
|
|
|
|
Apr 22 2009, 17:52
|
Участник

Группа: Участник
Сообщений: 31
Регистрация: 20-10-08
Из: Нижний Новгород
Пользователь №: 41 078

|
AT91C_BASE_PIOB->PIO_SODR |= ( DDS_P2_MODULATION ); - установить вывод PB7 в 1. AT91C_BASE_PIOB->PIO_CODR |= ( DDS_P2_MODULATION ); - установить вывод PB7 в 0. AIC_ICCR - это на самом деле лишнее. Цитата Смысл какой? Источник у Вас внутренний, так зачем работать по фронту, рискуя огрести проблемы (что, судя по всему, и случилось)? Прерывание - внешнее - IRQ2, соответствует выводу PA25. Мне лучше, чтобы по фронтуили спаду прерывание обрабатывалось, чем по уровню. Я думаю будет точнее работать (время от появления какого либо фронта до установления PB7 в единичку)
Сообщение отредактировал Antokha - Apr 22 2009, 17:55
|
|
|
|
|
Apr 22 2009, 18:04
|
Гуру
     
Группа: Свой
Сообщений: 10 713
Регистрация: 11-12-04
Пользователь №: 1 448

|
Цитата(Antokha @ Apr 22 2009, 21:52)  AT91C_BASE_PIOB->PIO_SODR |= ( DDS_P2_MODULATION ); - установить вывод PB7 в 1. AT91C_BASE_PIOB->PIO_CODR |= ( DDS_P2_MODULATION ); - установить вывод PB7 в 0. AIC_ICCR - это на самом деле лишнее. Вместо |= нужно просто =, дабы не плодить бессмысленные и потенциально опасные действия. Цитата(Antokha @ Apr 22 2009, 21:52)  Прерывание - внешнее - IRQ2, соответствует выводу PA25. Да, пардон, меня сбило с толку имя обработчика - PIOA_Handler. Тогда следующий вопрос. Если у Вас в стартапе Код __irq_handler: ldr PC,[PC,#-0xF20] ;; IRQ то где оформление функции как прерывания? Код static void PIOA_Handler( void ) Цитата(Antokha @ Apr 22 2009, 21:52)  Мне лучше, чтобы по фронтуили спаду прерывание обрабатывалось, чем по уровню. Я думаю будет точнее работать (время от появления какого либо фронта до установления PB7 в единичку) Работать будет одинаково, а вот шанс пропустить событие возрастает.
|
|
|
|
|
Apr 22 2009, 19:00
|
Участник

Группа: Участник
Сообщений: 31
Регистрация: 20-10-08
Из: Нижний Новгород
Пользователь №: 41 078

|
Цитата Функция обработчика объявлена как обычная функция, не содержащая необходимых действий по сохранению/восстановлению контекста. Именно поэтому прерывание только один раз и вызывается. Функция (обработчик прерывания) должна выплюнуть последовательный код на ножку PB7. Восстановление контекста - какое именно, в pdf написано что возврат в прерванную функцию производится самостоятельно, ничего дописывать не надо, или я что-то не так понял. У меня поганится один из массивов - такое ощущение, что нормального выхода из прерывания нет и контроллер дальше выполняет инструкции, следующие за кодом прерывания (неизвестно какие -  ). Цитата то где оформление функции как прерывания? Код static void PIOA_Handler( void ) В void IntInit(void): ... AT91F_AIC_ConfigureIt (AT91C_BASE_AIC, AT91C_ID_IRQ2, 7, AT91C_AIC_SRCTYPE_INT_EDGE_TRIGGERED, PIOA_Handler); ... Вообще void IntInit(void) брал из книги по ARM7, там AIC такой-же. Вырезка из lib_AT91RM9200.h: Код __inline unsigned int AT91F_AIC_ConfigureIt ( AT91PS_AIC pAic, // \arg pointer to the AIC registers unsigned int irq_id, // \arg interrupt number to initialize unsigned int priority, // \arg priority to give to the interrupt unsigned int src_type, // \arg activation and sense of activation void (*newHandler) (void) ) // \arg address of the interrupt handler { unsigned int oldHandler; unsigned int mask; oldHandler = pAic->AIC_SVR[irq_id]; mask = 0x1 << irq_id; //* Disable the interrupt on the interrupt controller pAic->AIC_IDCR = mask; //* Save the interrupt handler routine pointer and the interrupt priority pAic->AIC_SVR[irq_id] = (unsigned int) newHandler; //* Store the Source Mode Register pAic->AIC_SMR[irq_id] = src_type | priority; //* Clear the interrupt on the interrupt controller pAic->AIC_ICCR = mask; return oldHandler; }
Сообщение отредактировал Antokha - Apr 22 2009, 19:15
|
|
|
|
|
Apr 22 2009, 19:16
|
Гуру
     
Группа: Свой
Сообщений: 10 713
Регистрация: 11-12-04
Пользователь №: 1 448

|
Цитата(Antokha @ Apr 22 2009, 23:00)  Вообще void IntInit(void) брал из книги по ARM7, там AIC такой-же. Уж не Редькина ли книжка? PIOA_Handler должен быть не Код void PIOA_Handler( void ), а
__irq void PIOA_Handler(void)
или
void PIOA_Handler(void) __attribute__ ((interrupt ("IRQ"))); или иметь еще какие-нибудь модификаторы, в зависимости от используемого компилятора. Иначе процессор никогда не выйдет из режима IRQ.
|
|
|
|
|
Apr 22 2009, 19:23
|
Участник

Группа: Участник
Сообщений: 31
Регистрация: 20-10-08
Из: Нижний Новгород
Пользователь №: 41 078

|
Книжка может быть и Редькина, точно скажу завтра днем. При использовании функции AT91F_AIC_ConfigureIt объявляя функцию static __arm __irq void PIOA_Handler( void ), получаю ошибку. Пробовал ещё так: - настройка: Код AT91C_BASE_PIOA->PIO_ODR |= ( DataInput ); /* PB27 are input */ AT91C_BASE_PIOA->PIO_ASR |= ( DataInput ); AT91C_BASE_AIC->AIC_IDCR |= ( 1UL<<AT91C_ID_IRQ2 );//disable interrupt IRQ2 AT91C_BASE_AIC->AIC_SVR[AT91C_ID_IRQ2] |= ( AT91_REG )PIOA_Handler; // set isr AT91C_BASE_AIC->AIC_SMR[AT91C_ID_IRQ2] |= ( AT91C_AIC_SRCTYPE_INT_EDGE_TRIGGERED ) | ( 7 )); // prio 7 AT91C_BASE_AIC->AIC_ICCR |= ( 1UL<<AT91C_ID_IRQ2 );//clear interrupt AT91C_BASE_AIC->AIC_IECR |= ( 1UL<<AT91C_ID_IRQ2 );//enable interrupt функцию PIOA_Handler объявляю как: static __arm __irq void PIOA_Handler( void ); без ошибок компилируется, но работает также.
Сообщение отредактировал Antokha - Apr 22 2009, 19:40
|
|
|
|
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|