реклама на сайте
подробности

 
 
> Внешнее прерывание AT91SAM7S256., Прерывание по нажатию кнопки.
vutang
сообщение May 24 2013, 10:01
Сообщение #1


Участник
*

Группа: Участник
Сообщений: 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
Go to the top of the page
 
+Quote Post
 
Start new topic
Ответов (1 - 11)
aaarrr
сообщение May 24 2013, 10:39
Сообщение #2


Гуру
******

Группа: Свой
Сообщений: 10 713
Регистрация: 11-12-04
Пользователь №: 1 448



Почему Вы для прерывания PIO инициализируете источник IRQ1?
AT91C_PIOA_IMR - Read Only, писать его смысла нет.
Go to the top of the page
 
+Quote Post
vutang
сообщение May 24 2013, 10:59
Сообщение #3


Участник
*

Группа: Участник
Сообщений: 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);


Теперь программа сразу уходит в обработчик прерывания и висит в нем. Такое ощущение, что условия срабатывания по фронту не работают...
Go to the top of the page
 
+Quote Post
aaarrr
сообщение May 24 2013, 11:14
Сообщение #4


Гуру
******

Группа: Свой
Сообщений: 10 713
Регистрация: 11-12-04
Пользователь №: 1 448



PIO - это не внешний источник, а внутренний. Детектирование фронта производится в самом модуле PIO, так что в SMR можно спокойно прописать level sensetive.

С механизмом "висения" что-то не очень ясно пока. Как организован код вектора прерывания?
Go to the top of the page
 
+Quote Post
vutang
сообщение May 24 2013, 11:28
Сообщение #5


Участник
*

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



Извините не совсем понял про код вектора прерывания, где его посмотреть можно?
Go to the top of the page
 
+Quote Post
aaarrr
сообщение May 24 2013, 11:29
Сообщение #6


Гуру
******

Группа: Свой
Сообщений: 10 713
Регистрация: 11-12-04
Пользователь №: 1 448



Смотрите startup.s или что-то похожее.
Go to the top of the page
 
+Quote Post
vutang
сообщение May 24 2013, 11:46
Сообщение #7


Участник
*

Группа: Участник
Сообщений: 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] - для короткого!!!
Go to the top of the page
 
+Quote Post
aaarrr
сообщение May 24 2013, 11:48
Сообщение #8


Гуру
******

Группа: Свой
Сообщений: 10 713
Регистрация: 11-12-04
Пользователь №: 1 448



Тогда уберите из вашего обработчика модификатор __irq и запись AIC_EOICR, так как все это уже сделано в обертке irqHandler.
Go to the top of the page
 
+Quote Post
vutang
сообщение May 24 2013, 12:13
Сообщение #9


Участник
*

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



Эффекта нет. Пошагово просмотрел как выполняется программа, сразу после строки "BX r0" в файле board_cstartup_iar.s входит в прерывание. Смотрел примеры на сайте производителя, так там просто в цикле опрашивается состояние пинов. Хочется на прерываниях сделать, не думал, что вылезут такие косяки. Подумываю уже таймер задействовать...
Go to the top of the page
 
+Quote Post
RabidRabbit
сообщение May 24 2013, 12:32
Сообщение #10


Местный
***

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



Чтение PIO_ISR есть, проглючило меня sm.gif

запись *AT91C_PIOA_CODR |= LED1 можно смело заменить на *AT91C_PIOA_CODR = LED1

BIT7 = это (1 << 7)?
тогда что за странная запись *AT91C_PIOA_ASR = (1<<SW2); ?
а тактирование PIO включено?

Сообщение отредактировал RabidRabbit - May 24 2013, 12:41
Go to the top of the page
 
+Quote Post
aaarrr
сообщение May 24 2013, 12:40
Сообщение #11


Гуру
******

Группа: Свой
Сообщений: 10 713
Регистрация: 11-12-04
Пользователь №: 1 448



Цитата(vutang @ May 24 2013, 16:13) *
Эффекта нет. Пошагово просмотрел как выполняется программа, сразу после строки "BX r0" в файле board_cstartup_iar.s входит в прерывание.

Вот "пошагово" - это и источник всех бед. AIC под отладчиком не сброшен, потому и чудит.
Go to the top of the page
 
+Quote Post
vutang
сообщение May 27 2013, 03:19
Сообщение #12


Участник
*

Группа: Участник
Сообщений: 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
Go to the top of the page
 
+Quote Post

Reply to this topicStart new topic
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 


RSS Текстовая версия Сейчас: 22nd July 2025 - 04:01
Рейтинг@Mail.ru


Страница сгенерированна за 0.01458 секунд с 7
ELECTRONIX ©2004-2016