vutang 0 24 мая, 2013 Опубликовано 24 мая, 2013 (изменено) · Жалоба Добрый день всем! Имеется отладочная плата sam7-mt256 фирмы olimex. На плате имеется джойстик, состоящий из 5 кнопок. Хочу сделать прерывание по нажатию на одну из этих кнопок, но как-то не выходит. Т.е. по нажатию на кнопку программа уходит в прерывание и крутится в нем, пока не перезагрузишь контроллер. На сколько я понял, за окончание прерывания отвечает запись любого значения в регистр AIC_EOICR, но это тоже не помогает. Может кто делал что-нибудь подобное, подскажите куда копать? Ниже приведена часть кода, в котором производится настройка и описание прерывания. Используемая среда разработки IAR 5.4. #define SW2 BIT27 #define LED1 BIT7 int a = 0; __irq void int_sw(void){ for(int i=0;i<10000;i++) {} a=~a; if(a!=0) { *AT91C_PIOA_CODR |= LED1; } else { *AT91C_PIOA_SODR |= LED1; } AT91C_BASE_AIC->AIC_EOICR = AT91C_BASE_PIOA->PIO_ISR; } int main(void) { InitPeriphery(); InitFrec(); // Initialize interrupts *AT91C_PIOA_ASR = (1<<SW2); *AT91C_PIOA_IER = SW2; *AT91C_PIOA_IMR = SW2; AT91C_BASE_AIC->AIC_SMR[AT91C_ID_IRQ1] = 0x00; AT91C_BASE_AIC->AIC_SVR[AT91C_ID_IRQ1] = (unsigned int) int_sw; AT91C_BASE_AIC->AIC_IECR = (1 << AT91C_ID_IRQ1); while (1) { } } Изменено 24 мая, 2013 пользователем vutang Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
aaarrr 68 24 мая, 2013 Опубликовано 24 мая, 2013 · Жалоба Почему Вы для прерывания PIO инициализируете источник IRQ1? AT91C_PIOA_IMR - Read Only, писать его смысла нет. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
vutang 0 24 мая, 2013 Опубликовано 24 мая, 2013 · Жалоба Исправил код следующим образом: portA->PIO_IFER = SW1; pAic->AIC_IDCR = (1<<AT91C_ID_PIOA); pAic->AIC_SMR[AT91C_ID_PIOA] =(AT91C_AIC_SRCTYPE_EXT_POSITIVE_EDGE|AT91C_AIC_PRIOR_HIGHEST); pAic->AIC_SVR[AT91C_ID_PIOA] = (unsigned int) int_sw; pAic->AIC_ICCR = (1<<AT91C_ID_PIOA); portA->PIO_IER = SW1; pAic->AIC_IECR = (1 << AT91C_ID_PIOA); Теперь программа сразу уходит в обработчик прерывания и висит в нем. Такое ощущение, что условия срабатывания по фронту не работают... Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
aaarrr 68 24 мая, 2013 Опубликовано 24 мая, 2013 · Жалоба PIO - это не внешний источник, а внутренний. Детектирование фронта производится в самом модуле PIO, так что в SMR можно спокойно прописать level sensetive. С механизмом "висения" что-то не очень ясно пока. Как организован код вектора прерывания? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
vutang 0 24 мая, 2013 Опубликовано 24 мая, 2013 · Жалоба Извините не совсем понял про код вектора прерывания, где его посмотреть можно? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
aaarrr 68 24 мая, 2013 Опубликовано 24 мая, 2013 · Жалоба Смотрите startup.s или что-то похожее. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
vutang 0 24 мая, 2013 Опубликовано 24 мая, 2013 (изменено) · Жалоба Часть кода из файла board_cstartup_iar.s. На сколько я понимаю тут на ассемблере написано, а я в нем не силен. /* Handles incoming interrupt requests by branching to the corresponding handler, as defined in the AIC. Supports interrupt nesting. */ irqHandler: /* Save interrupt context on the stack to allow nesting */ SUB lr, lr, #4 STMFD sp!, {lr} MRS lr, SPSR STMFD sp!, {r0, lr} /* Write in the IVR to support Protect Mode */ LDR lr, =AT91C_BASE_AIC LDR r0, [r14, #AIC_IVR] STR lr, [r14, #AIC_IVR] /* Branch to interrupt handler in Supervisor mode */ MSR CPSR_c, #ARM_MODE_SYS STMFD sp!, {r1-r3, r4, r12, lr} MOV lr, pc BX r0 LDMIA sp!, {r1-r3, r4, r12, lr} MSR CPSR_c, #ARM_MODE_IRQ | I_BIT /* Acknowledge interrupt */ LDR lr, =AT91C_BASE_AIC STR lr, [r14, #AIC_EOICR] /* Restore interrupt context and branch back to calling code */ LDMIA sp!, {r0, lr} MSR SPSR_cxsf, lr LDMIA sp!, {pc}^ /* After a reset, execution starts here, the mode is ARM, supervisor with interrupts disabled. Initializes the chip and branches to the main() function. */ SECTION .cstartup:CODE:NOROOT(2) PUBLIC resetHandler EXTERN LowLevelInit EXTERN ?main REQUIRE resetVector ARM resetHandler: /* Set pc to actual code location (i.e. not in remap zone) */ LDR pc, =label /* Perform low-level initialization of the chip using LowLevelInit() */ label: LDR r0, =LowLevelInit LDR r4, =SFE(CSTACK) MOV sp, r4 MOV lr, pc BX r0 /* Set up the interrupt stack pointer. */ MSR cpsr_c, #ARM_MODE_IRQ | I_BIT | F_BIT ; Change the mode LDR sp, =SFE(IRQ_STACK) /* Set up the SYS stack pointer. */ MSR cpsr_c, #ARM_MODE_SYS | F_BIT ; Change the mode LDR sp, =SFE(CSTACK) /* Branch to main() */ LDR r0, =?main MOV lr, pc BX r0 /* Loop indefinitely when program is finished */ loop4: B loop4 END Изменено 24 мая, 2013 пользователем IgorKossak [codebox] для длинного кода, [code] - для короткого!!! Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
aaarrr 68 24 мая, 2013 Опубликовано 24 мая, 2013 · Жалоба Тогда уберите из вашего обработчика модификатор __irq и запись AIC_EOICR, так как все это уже сделано в обертке irqHandler. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
vutang 0 24 мая, 2013 Опубликовано 24 мая, 2013 · Жалоба Эффекта нет. Пошагово просмотрел как выполняется программа, сразу после строки "BX r0" в файле board_cstartup_iar.s входит в прерывание. Смотрел примеры на сайте производителя, так там просто в цикле опрашивается состояние пинов. Хочется на прерываниях сделать, не думал, что вылезут такие косяки. Подумываю уже таймер задействовать... Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
RabidRabbit 0 24 мая, 2013 Опубликовано 24 мая, 2013 (изменено) · Жалоба Чтение PIO_ISR есть, проглючило меня :) запись *AT91C_PIOA_CODR |= LED1 можно смело заменить на *AT91C_PIOA_CODR = LED1 BIT7 = это (1 << 7)? тогда что за странная запись *AT91C_PIOA_ASR = (1<<SW2); ? а тактирование PIO включено? Изменено 24 мая, 2013 пользователем RabidRabbit Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
aaarrr 68 24 мая, 2013 Опубликовано 24 мая, 2013 · Жалоба Эффекта нет. Пошагово просмотрел как выполняется программа, сразу после строки "BX r0" в файле board_cstartup_iar.s входит в прерывание. Вот "пошагово" - это и источник всех бед. AIC под отладчиком не сброшен, потому и чудит. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
vutang 0 27 мая, 2013 Опубликовано 27 мая, 2013 · Жалоба Короче все заработало. Наверное проблема была в том, что PORTA находился в таком состоянии, что прерывание вызывалось постоянно. Решил проблему добавив в обработчик проверку конкретного бита этого порта. Инициализация для одной кнопки: // Initialize interrupts portA->PIO_IFER = SW1; pAic->AIC_IDCR = (1<<AT91C_ID_PIOA); pAic->AIC_SMR[AT91C_ID_PIOA] =(AT91C_AIC_SRCTYPE_INT_LEVEL_SENSITIVE|AT91C_AIC_PRIOR_HIGHEST); pAic->AIC_SVR[AT91C_ID_PIOA] = (unsigned int) int_sw; portA->PIO_IER = SW1; pAic->AIC_IECR = (1<<AT91C_ID_PIOA); Обработчик: void int_sw(void){ if(!((portA->PIO_PDSR) & SW1)) { Delay(5,'m'); portA->PIO_SODR |= LED1; }else if(((portA->PIO_PDSR) & SW1)) { Delay(5,'m'); portA->PIO_CODR |= LED1; } } где #define SW1 BIT29 #define LED1 BIT7 Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться