Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: Проблема с прерываниями AT91SAM7S256
Форум разработчиков электроники ELECTRONIX.ru > Микроконтроллеры (MCs) > ARM
subver
День добрый. Вот столкнулся с такой проблемой:
при непонятных условиях перестают срабатывать прерывания (все).
Хотя в регистре AIC Interrupt Pending register взведены соответствующие биты
AIC Interrupt Mask Register также содержит правильное значение, т.е. прерывания от соотвтетсвующих периферийных устройств разрешены, однако процессор не переходит на вектор обработки прерывания.
Вообще. Т.е. не выполняется даже IRQ Handler, который прописан в стартапе. Чего делать совсем не пойму.

Работоспособность восстанавливается только после аппаратного сброса.
zhevak
Цитата(subver @ Oct 8 2008, 09:41) *
Вообще. Т.е. не выполняется даже IRQ Handler, который прописан в стартапе. Чего делать совсем не пойму.


Уважаемый, Вы ошиблись. Это не сайт телепатов.
-- Алло? Скорая? Доктор, Вы не знаете почему я ничего не вижу и в боку колет?

Код в студию!
Будем обсуждать.
subver
Вот стартап:

Код
                B           InitReset         ; 0x00 Reset handler
undefvec:
                B           undefvec          ; 0x04 Undefined Instruction
swivec:
                B           swivec            ; 0x08 Software Interrupt
pabtvec:
                B           pabtvec        ; 0x0C Prefetch Abort
dabtvec:
                B           dabtvec        ; 0x10 Data Abort
rsvdvec:
                B           rsvdvec        ; 0x14 reserved
irqvec:
                B           IRQ_Handler_Entry ; 0x18 IRQ
fiqvec:                       ; 0x1c FIQ


void AT91F_LowLevelInit( void)
{
unsigned int i;
  AT91C_BASE_RSTC->RSTC_RMR = 0xa5000801;
  AT91PS_PMC     pPMC = AT91C_BASE_PMC;
  //* Set Flash Waite sate
  //  Single Cycle Access at Up to 30 MHz, or 40
  //  if MCK = 47923200 I have 50 Cycle for 1 usecond ( flied MC_FMR->FMCN
  AT91C_BASE_MC->MC_FMR = ((AT91C_MC_FMCN)&(48 <<16)) | AT91C_MC_FWS_1FWS;
  //* Set MCK at 47 923 200
  // 1 Enabling the Main Oscillator:
  // SCK = 1/32768 = 30.51 uSecond
  // Start up time = 8 * 6 / SCK = 48 * 30.51 = 1,46484375 ms
  pPMC->PMC_MOR = (( AT91C_CKGR_OSCOUNT & (0x06 <<8) | AT91C_CKGR_MOSCEN ));
  // Wait the startup time
  while(!(pPMC->PMC_SR & AT91C_PMC_MOSCS));
  // 2 Checking the Main Oscillator Frequency (Optional)
  // 3 Setting PLL and divider:
  // - div by 5 Fin = 3,6864 =(18,432 / 5)
  // - Mul 25+1: Fout =    95,8464 =(3,6864 *26)
  // for 96 MHz the erroe is 0.16%
  // Field out NOT USED = 0
  // PLLCOUNT pll startup time estimate at : 0.844 ms
  // PLLCOUNT 28 = 0.000844 /(1/32768)
  pPMC->PMC_PLLR = ((AT91C_CKGR_DIV & 0x05) |
                    (AT91C_CKGR_PLLCOUNT & (28<<8)) |
                    (AT91C_CKGR_MUL & (25<<16)));
  // Wait the startup time
  while(!(pPMC->PMC_SR & AT91C_PMC_LOCK));
  while(!(pPMC->PMC_SR & AT91C_PMC_MCKRDY));
  // 4. Selection of Master Clock and Processor Clock
  // select the PLL clock divided by 2
  pPMC->PMC_MCKR =  AT91C_PMC_PRES_CLK_2;
  while(!(pPMC->PMC_SR & AT91C_PMC_MCKRDY));
  pPMC->PMC_MCKR |= AT91C_PMC_CSS_PLL_CLK;
  while(!(pPMC->PMC_SR & AT91C_PMC_MCKRDY));
  // Set up the default interrupts handler vectors
  AT91C_BASE_AIC->AIC_EOICR = 0xFFFFFFFF;
  AT91C_BASE_AIC->AIC_IDCR = 0xFFFFFFFF;
  AT91C_BASE_AIC->AIC_ICCR = 0xFFFFFFFF;
  for(i=0;i<31;i++)
  {
    AT91C_BASE_AIC->AIC_SMR[i] = 0;
  }
  AT91C_BASE_AIC->AIC_SVR[0] = (int) AT91F_Default_FIQ_handler;
  for (i=1;i < 31; i++)
  {
    AT91C_BASE_AIC->AIC_SVR[i] = (int) AT91F_Default_IRQ_handler;
  }
  AT91C_BASE_AIC->AIC_SPU  = (int) AT91F_Spurious_handler;
}


Вот инициализация таймера:


Код
void init_inquiry_timer()
{
  AT91F_PMC_EnablePeriphClock(AT91C_BASE_PMC,1<<INQUIRYTIMERID);
  AT91F_TC_Open(INQUIRYTIMERREG,TC_CLKS_MCK1024|AT91C_TC_WAVESEL_UP_AUTO,INQUIRYTIMERID);
  AT91F_AIC_ConfigureIt(AT91C_BASE_AIC,INQUIRYTIMERID,INQUIRYINTPRIOR,AT91C_AIC_SRCTYPE_INT_LEVEL_SE
NSITIVE, _one_sec_timer_isr);
  AT91F_AIC_EnableIt(AT91C_BASE_AIC,INQUIRYTIMERID);
  INQUIRYTIMERREG->TC_IER = AT91C_TC_CPCS;
  INQUIRYTIMERREG->TC_RC = 46800;
  INQUIRYTIMERREG->TC_CCR = AT91C_TC_SWTRG;
}


Содержимое регистров:

AIC_IPR = 0b01000000000000000101000011000000
AIC_IMR = 0b00000000000000000001000000000000

Т.е. должно выполняться прерывание от Timer/Counter0, таймер тикает, флаги взводятся. Прерывание не выполняется. Нет перехода на IRQ_Handler_Entry.
Насколько я понял в Power Managment Controller для Advanced Interrupt Controller никаких настроек нет, или есть?
aaarrr
Цитата(subver @ Oct 8 2008, 08:13) *
Т.е. должно выполняться прерывание от Timer/Counter0, таймер тикает, флаги взводятся. Прерывание не выполняется. Нет перехода на IRQ_Handler_Entry.

Вариантов не так и много:
- прерывания запрещены глобально
- забыли где-то сбросить AIC записью в AIC_EOICR (ИМХО, наиболее вероятно)
- в отладчике открыто окно с содержимым регистров AIC

Цитата(subver @ Oct 8 2008, 08:13) *
Насколько я понял в Power Managment Controller для Advanced Interrupt Controller никаких настроек нет, или есть?

Никаких настроек нет.
_dem
Или зависли в прерывании более высокого приоритета...
subver
Цитата(_dem @ Oct 8 2008, 14:43) *
Или зависли в прерывании более высокого приоритета...


Не. программа крутится вне прерываний. Вроде наблюдается только под отладчиком такое поведение.
aaarrr
Цитата(subver @ Oct 8 2008, 12:16) *
Не. программа крутится вне прерываний. Вроде наблюдается только под отладчиком такое поведение.

Чтобы завесить AIC, достаточно не записать AIC_EOICR в обработчике или прочитать AIC_IVR не процессором, что по сути одно и то же.
Закройте в отладчике любые watch'и и окошки, отображающие содержимое AIC.
Dron_Gus
Чтобы прерывания "не висли" под отладчиком, используйте соответствующий режим AIC.
zhz
Цитата(aaarrr @ Oct 8 2008, 11:25) *
Чтобы завесить AIC, достаточно не записать AIC_EOICR в обработчике или прочитать AIC_IVR не процессором, что по сути одно и то же.
Закройте в отладчике любые watch'и и окошки, отображающие содержимое AIC.


под отладчиком перевести AIC в protected mode:
Код
#ifdef   AIC_PROTECT_MODE
   bAIC->AIC_DCR = AT91C_AIC_DCR_PROT;    // set protected mode
#else
   bAIC->AIC_DCR = 0;
#endif


в начале обработчика прерывания делать запись в IVR:
Код
#ifdef   AIC_PROTECT_MODE
   bAIC->AIC_IVR = 0;               // for protected mode of AIC
#endif
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.