Перейти к содержанию
    

вопрос про прерывания

Про ошибку завтра днём. Компилятор (от IAR 5.11) дома не пашет.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

У меня почти такая же проблема: второй раз не обрабатывает прерывание и докучи перезаписывает один из существующих массивов (программа не зависает, если это важно).

Обработчик:

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;
}

 

Во-первых как Вам уже сказали нужно оформить правильно функцию прерывания(в зависимости от компилятора).

 

Ну и вообще-то сброс прерывания от PIO делается не записью AIC_ICCR,

а чтением PIOx_ISR, при этом нужно иметь в виду что сбросятся все прерывания которые пришли на порт в данный

момент времени:

When the software reads PIO_ISR, all the interrupts are automatically cleared. This signifies that

all the interrupts that are pending when PIO_ISR is read must be handled.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Ну и вообще-то сброс прерывания от PIO делается не записью AIC_ICCR,

а чтением PIOx_ISR...

Ну, вот и Вы попались :) Это не прерывание PIO, а вполне честное EXT_IRQ2.

А имя PIOA_Handler, похоже, перекочевало "из книжки". Или дано специально для введения в заблуждение желающих помочь.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Ну, вот и Вы попались :) Это не прерывание PIO, а вполне честное EXT_IRQ2.

А имя PIOA_Handler, похоже, перекочевало "из книжки". Или дано специально для введения в заблуждение желающих помочь.

Да..., хорошее имя..., информативное... :)

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

extern int p[33];
static  void PIOA_Handler( void )
{  AT91C_BASE_AIC->AIC_IVR;

...

__irq_handler:
        ldr PC,[PC,#-0xF20]          ;; IRQ
....

AIC_IVR читается дважды. Огласите название книжки.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

AIC_IVR читается дважды. Огласите название книжки.

Это моя отсебятина, начитался pdf-ника. Там сказано регистр считать, а cstartup.s не доглядел.

Про ошибку:

При использовании функции AT91F_AIC_ConfigureIt объявляя функцию static __arm __irq void PIOA_Handler( void ), получаю ошибку:

Error[Pe167]: argument of type "void (__arm __irq *)()" is incompatible with parameter of type "void (*)()"

На данный момент сделал так:

Инит:

AT91C_BASE_PIOA->PIO_PPUDR |= ( DataInput );
  AT91C_BASE_PIOA->PIO_ODR = ( DataInput );
  AT91C_BASE_PIOA->PIO_BSR = ( 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_EXT_HIGH_LEVEL ) | ( 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

Обработка:

static __irq __arm void PIOA_Handler( void )
{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_EOICR = 0;  
}

виснет после команды __enable_interrupt();

P.S. Имя обработчика прерывания осталось от нужного когда-то прерывания, извините уж.

А книжка - Это Редькин П.П. "32/16-битные микроконтроллеры ARM7 семейства AT91SAM7 Руководство пользователя"

Изменено пользователем Antokha

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

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_EXT_HIGH_LEVEL ) | ( 7 ); // prio 7

Опять |=, да еще и при записи адреса.

 

А книжка - Это Редькин П.П. "32/16-битные микроконтроллеры ARM7 семейства AT91SAM7 Руководство пользователя"

В печку ее.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Опять |=, да еще и при записи адреса.

 

В печку ее.

 

Вместе с автором.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

AT91SAM7S32

 

Если читаю IVR вначале прерывания, прерывание один раз происходит и больше не хочет. Почему так ?

Если убрать строчку i=*AT91C_AIC_IVR; прерывание происходит много раз как и должно.

 

Спасибо !

 

__irq void PIOA_interrupt(void)

{

int i;

 

i=*AT91C_AIC_IVR;

 

i=*AT91C_PIOA_ISR;

i=*AT91C_PIOA_PDSR;

 

*AT91C_AIC_EOICR = 0;

}

 

 

void SET_PIOA_interrupt(void)

{

 

AT91C_BASE_AIC->AIC_SMR[AT91C_ID_PIOA]=(3<<0)|(0<<5);

AT91C_BASE_AIC->AIC_SVR[AT91C_ID_PIOA]=(unsigned long)PIOA_interrupt;

AT91C_BASE_AIC->AIC_IECR=(1<<AT91C_ID_PIOA);

}

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Потому что если вы уже попали в обработчик конкретного прерывания, значит обертка на IRQ векторе уже прочитала этот регистр и перешла по соответствующему адресу. Вы же его читаете повторно.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.

Гость
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...