Sergei_K 0 6 декабря, 2007 Опубликовано 6 декабря, 2007 · Жалоба Судя по даташиту, в начале обработки прерывания необходимо прочитать регистр 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 и если да, то в каких случаях? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Сергей Борщ 141 6 декабря, 2007 Опубликовано 6 декабря, 2007 · Жалоба В связи с этим вопрос: необходимо ли читать регистр AIC_IVRДа, необходимо.и если да, то в каких случаях?Вы же в самом начале привели цитату - как только вошли в обработчик прерывания, чтобы определить источник прерывания. Один раз у вас срабатывает скорее всего потому, что вы не пишете EOICR в конце обработчика. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
aaarrr 69 6 декабря, 2007 Опубликовано 6 декабря, 2007 · Жалоба Добавлю немного. AIC_IVR лучше читать сразу при переходе на вектор IRQ: 00000018 ldr pc, [pc, #-0xf20] ; IRQ для того контроллер прерываний и положили в верхние адреса. Если не записать AIC_EOICR в конце процедуры обработки прерывания, то AIC перестанет реагировать на прерывания с более низким приоритетом. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
xelax 0 7 декабря, 2007 Опубликовано 7 декабря, 2007 · Жалоба не перестанет если AIC находится в Protect режиме. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Antokha 0 22 апреля, 2009 Опубликовано 22 апреля, 2009 (изменено) · Жалоба У меня почти такая же проблема: второй раз не обрабатывает прерывание и докучи перезаписывает один из существующих массивов (программа не зависает, если это важно). Камень 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 */ ... Изменено 22 апреля, 2009 пользователем Antokha Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
aaarrr 69 22 апреля, 2009 Опубликовано 22 апреля, 2009 · Жалоба Во-первых, не нужно читать write-only регистры. Во-вторых, какой смысл использовать прерывания по фронту для внутреннего источника в данном случае? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Antokha 0 22 апреля, 2009 Опубликовано 22 апреля, 2009 · Жалоба Во-первых, не нужно читать 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 на контроллер это и прерывание по фронту для внутреннего источника так и прерывание по спаду для внешнего прерывания. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
aaarrr 69 22 апреля, 2009 Опубликовано 22 апреля, 2009 · Жалоба Если это про AIC_IVR... Нет, это про PIO_SODR, PIO_CODR, AIC_ICCR и т.д. AT91C_AIC_SRCTYPE_INT_EDGE_TRIGGERED в файле AT91RM9200.h описан как... Смысл какой? Источник у Вас внутренний, так зачем работать по фронту, рискуя огрести проблемы (что, судя по всему, и случилось)? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Antokha 0 22 апреля, 2009 Опубликовано 22 апреля, 2009 (изменено) · Жалоба 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 в единичку) Изменено 22 апреля, 2009 пользователем Antokha Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
aaarrr 69 22 апреля, 2009 Опубликовано 22 апреля, 2009 · Жалоба AT91C_BASE_PIOB->PIO_SODR |= ( DDS_P2_MODULATION ); - установить вывод PB7 в 1. AT91C_BASE_PIOB->PIO_CODR |= ( DDS_P2_MODULATION ); - установить вывод PB7 в 0. AIC_ICCR - это на самом деле лишнее. Вместо |= нужно просто =, дабы не плодить бессмысленные и потенциально опасные действия. Прерывание - внешнее - IRQ2, соответствует выводу PA25. Да, пардон, меня сбило с толку имя обработчика - PIOA_Handler. Тогда следующий вопрос. Если у Вас в стартапе __irq_handler: ldr PC,[PC,#-0xF20] ;; IRQ то где оформление функции как прерывания? static void PIOA_Handler( void ) Мне лучше, чтобы по фронтуили спаду прерывание обрабатывалось, чем по уровню. Я думаю будет точнее работать (время от появления какого либо фронта до установления PB7 в единичку) Работать будет одинаково, а вот шанс пропустить событие возрастает. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
sergeeff 1 22 апреля, 2009 Опубликовано 22 апреля, 2009 · Жалоба Функция обработчика объявлена как обычная функция, не содержащая необходимых действий по сохранению/восстановлению контекста. Именно поэтому прерывание только один раз и вызывается. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Antokha 0 22 апреля, 2009 Опубликовано 22 апреля, 2009 (изменено) · Жалоба Функция обработчика объявлена как обычная функция, не содержащая необходимых действий по сохранению/восстановлению контекста. Именно поэтому прерывание только один раз и вызывается. Функция (обработчик прерывания) должна выплюнуть последовательный код на ножку 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; } Изменено 22 апреля, 2009 пользователем Antokha Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
aaarrr 69 22 апреля, 2009 Опубликовано 22 апреля, 2009 · Жалоба Вообще void IntInit(void) брал из книги по ARM7, там AIC такой-же. Уж не Редькина ли книжка? PIOA_Handler должен быть не void PIOA_Handler( void ), а __irq void PIOA_Handler(void) или void PIOA_Handler(void) __attribute__ ((interrupt ("IRQ"))); или иметь еще какие-нибудь модификаторы, в зависимости от используемого компилятора. Иначе процессор никогда не выйдет из режима IRQ. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Antokha 0 22 апреля, 2009 Опубликовано 22 апреля, 2009 (изменено) · Жалоба Книжка может быть и Редькина, точно скажу завтра днем. При использовании функции 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 ); без ошибок компилируется, но работает также. Изменено 22 апреля, 2009 пользователем Antokha Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
aaarrr 69 22 апреля, 2009 Опубликовано 22 апреля, 2009 · Жалоба При использовании функции AT91F_AIC_ConfigureIt объявляя функцию static __arm __irq void PIOA_Handler( void ), получаю ошибку. Какую? Ну, напишите там (void*)PIOA_Handler. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться