|
Внешнее прерывание AT91SAM7S256., Прерывание по нажатию кнопки. |
|
|
|
May 24 2013, 10:01
|
Участник

Группа: Участник
Сообщений: 42
Регистрация: 10-12-09
Из: Томск
Пользователь №: 54 174

|
Добрый день всем! Имеется отладочная плата sam7-mt256 фирмы olimex. На плате имеется джойстик, состоящий из 5 кнопок. Хочу сделать прерывание по нажатию на одну из этих кнопок, но как-то не выходит. Т.е. по нажатию на кнопку программа уходит в прерывание и крутится в нем, пока не перезагрузишь контроллер. На сколько я понял, за окончание прерывания отвечает запись любого значения в регистр AIC_EOICR, но это тоже не помогает. Может кто делал что-нибудь подобное, подскажите куда копать? Ниже приведена часть кода, в котором производится настройка и описание прерывания. Используемая среда разработки IAR 5.4. CODE #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) {
} }
Сообщение отредактировал vutang - May 24 2013, 10:15
|
|
|
|
|
 |
Ответов
(1 - 11)
|
May 24 2013, 10:59
|
Участник

Группа: Участник
Сообщений: 42
Регистрация: 10-12-09
Из: Томск
Пользователь №: 54 174

|
Исправил код следующим образом: Код 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); Теперь программа сразу уходит в обработчик прерывания и висит в нем. Такое ощущение, что условия срабатывания по фронту не работают...
|
|
|
|
|
May 24 2013, 11:28
|
Участник

Группа: Участник
Сообщений: 42
Регистрация: 10-12-09
Из: Томск
Пользователь №: 54 174

|
Извините не совсем понял про код вектора прерывания, где его посмотреть можно?
|
|
|
|
|
May 24 2013, 11:46
|
Участник

Группа: Участник
Сообщений: 42
Регистрация: 10-12-09
Из: Томск
Пользователь №: 54 174

|
Часть кода из файла board_cstartup_iar.s. На сколько я понимаю тут на ассемблере написано, а я в нем не силен. CODE /* 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
Сообщение отредактировал IgorKossak - May 24 2013, 12:37
Причина редактирования: [codebox] для длинного кода, [code] - для короткого!!!
|
|
|
|
|
May 24 2013, 12:13
|
Участник

Группа: Участник
Сообщений: 42
Регистрация: 10-12-09
Из: Томск
Пользователь №: 54 174

|
Эффекта нет. Пошагово просмотрел как выполняется программа, сразу после строки "BX r0" в файле board_cstartup_iar.s входит в прерывание. Смотрел примеры на сайте производителя, так там просто в цикле опрашивается состояние пинов. Хочется на прерываниях сделать, не думал, что вылезут такие косяки. Подумываю уже таймер задействовать...
|
|
|
|
|
May 24 2013, 12:32
|

Местный
  
Группа: Свой
Сообщений: 397
Регистрация: 3-12-09
Из: Россия, Москва
Пользователь №: 54 040

|
Чтение PIO_ISR есть, проглючило меня  запись *AT91C_PIOA_CODR |= LED1 можно смело заменить на *AT91C_PIOA_CODR = LED1 BIT7 = это (1 << 7)? тогда что за странная запись *AT91C_PIOA_ASR = (1<<SW2); ? а тактирование PIO включено?
Сообщение отредактировал RabidRabbit - May 24 2013, 12:41
|
|
|
|
|
May 27 2013, 03:19
|
Участник

Группа: Участник
Сообщений: 42
Регистрация: 10-12-09
Из: Томск
Пользователь №: 54 174

|
Короче все заработало. Наверное проблема была в том, что 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
|
|
|
|
|
  |
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|