Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: at91sam7x128 и TC
Форум разработчиков электроники ELECTRONIX.ru > Микроконтроллеры (MCs) > ARM
RuZaKi
Не могу заставить работать прерывание от таймера T0 по достижению RC .
Сам таймер работает, + при бесконечном опросе флага AT91C_TC_CPCS в TC_SR (произошло накопление счетчика до значения RC) все робит как нуно. Но мне нужны прерывания по такому поводу.
Как правельно настроить, чтобы появились прерывания от таймера T0 по достижению счетчика значения RC ?

Код
#include "AT91SAM7S128.h"

void timer_tick10ms(void) __attribute__ ((interrupt)); // забыл вставить, но в моей проге это было и есть

void timer_tick10ms(void)
{
   unsigned int temp;

   AT91C_BASE_AIC->AIC_IDCR = (1<<AT91C_ID_TC0);
   temp=AT91C_BASE_TC0->TC_SR;
   led_tgl();
   AT91C_BASE_AIC->AIC_ICCR = (1<<AT91C_ID_TC0);
   AT91C_BASE_TC0->TC_CCR = AT91C_TC_CLKEN | AT91C_TC_SWTRG;//перезапуск таймера
   AT91C_BASE_AIC->AIC_IECR = (1<<AT91C_ID_TC0);
   AT91C_BASE_AIC->AIC_EOICR = 0;//(1<<AT91C_ID_TC0);
}

void init_timer( void )
{
  AT91C_BASE_TCB->TCB_BCR = 1;
  AT91C_BASE_TCB->TCB_BMR = 0x15;
  AT91C_BASE_TC0->TC_CMR = (1 << 15) | (2<<13) | 1;//4
  AT91C_BASE_TC0->TC_RC = 0x1;
  //AT91C_BASE_TC0->TC_IDR = 0xFFFFFFFF;

  AT91C_BASE_TC0->TC_IDR &= ~((long)AT91C_TC_CPCS);
  AT91C_BASE_TC0->TC_IER |= AT91C_TC_CPCS;
  *AT91C_AIC_ICCR = (1<<AT91C_ID_TC0);

  AT91C_BASE_AIC->AIC_ICCR = 0xFFFFFFFF;
  AT91C_BASE_AIC->AIC_EOICR = 0;//*/

  AT91C_BASE_AIC->AIC_SVR[AT91C_ID_TC0] = (unsigned long)timer_tick10ms;
  AT91C_BASE_AIC->AIC_SMR[AT91C_ID_TC0] =  (1 << 5) | 0x7;

  AT91C_BASE_AIC->AIC_IDCR &= ~(1<<AT91C_ID_TC0);
  AT91C_BASE_AIC->AIC_IECR |= (1<<AT91C_ID_TC0);
  //AT91C_BASE_AIC->AIC_ISCR = (1<<AT91C_ID_TC0);
  ctl_global_interrupts_enable();
   //*/

  AT91C_BASE_PMC->PMC_PCER |= (1<<AT91C_ID_TC0);
  AT91C_BASE_TC0->TC_CCR = AT91C_TC_CLKEN | AT91C_TC_SWTRG;//запуск таймера
}

int init( void )
{
  int i;
  AT91PS_PMC pPMC = AT91C_BASE_PMC;
  AT91C_BASE_WDTC->WDTC_WDMR = AT91C_WDTC_WDDIS;
  pPMC->PMC_MOR = 1;//(( AT91C_CKGR_OSCOUNT & (0x06 <<8) | AT91C_CKGR_MOSCEN ));
  // Wait the startup time
  while(!(pPMC->PMC_SR & AT91C_PMC_MOSCS));

  pPMC->PMC_PLLR = ((AT91C_CKGR_DIV & 14) | (AT91C_CKGR_PLLCOUNT & (10<<8)) |    (AT91C_CKGR_MUL & (72<<16)));
  // Wait the startup time (until PMC Status register LOCK bit is set)
  while(!(pPMC->PMC_SR & AT91C_PMC_LOCK));

  pPMC->PMC_MCKR = AT91C_PMC_PRES_CLK_2 | 1;
  while(!(pPMC->PMC_SR & AT91C_PMC_MCKRDY));

  pPMC->PMC_MCKR |= AT91C_PMC_CSS_PLL_CLK;
  while(!(pPMC->PMC_SR & AT91C_PMC_MCKRDY));

  //*******************
  i=AT91C_PMC_PCK0 | AT91C_PMC_PCK;
  *AT91C_PMC_SCER = i;
  *AT91C_PMC_SCDR = ~i;

  pPMC->PMC_PCKR[0]=0x00000015;
  while( !(pPMC->PMC_SR & AT91C_PMC_PCK0RDY) );

  //**************************************************
  pPMC->PMC_IER=0xffffffff;
  pPMC->PMC_SCER=0xffffffff;

  i=(1 << AT91C_ID_PIOB) | (1 << AT91C_ID_US1);
  pPMC->PMC_PCER = i;
  pPMC->PMC_PCDR = ~i;
  //**************************************************

  volatile AT91PS_PIO pPIO = AT91C_BASE_PIOB; // pointer to PIO data structure

  pPIO->PIO_OWER = LED_MASK | PB20_PIN_MASK;
  pPIO->PIO_PER = LED_MASK | PB20_PIN_MASK;
  pPIO->PIO_PPUDR = LED_MASK | PB20_PIN_MASK; //disabele pull-up on PB19
  pPIO->PIO_OER = LED_MASK | PB20_PIN_MASK; //enable output on PB19
  pPIO->PIO_CODR = LED_MASK | PB20_PIN_MASK;
  pPIO->PIO_ASR=0;
  pPIO->PIO_BSR=0;    
    
  init_timer();

  return 0;
}

int main( void ) //************************* M A I N ******************************
{

  init();
  led_off();

  while(1)  //********************** W H I L E ******************************
  {
    //;
    /*if( (AT91C_BASE_TC0->TC_SR & AT91C_TC_CPCS) )
//если постоянно читать флаг , все работает как нуно( переключение сигнала с нужным переудом)
     {
       led_tgl();
       *AT91C_AIC_ICCR = 0;//AT91C_TC_CPCS;
       AT91C_BASE_TC0->TC_CCR = AT91C_TC_CLKEN | AT91C_TC_SWTRG;//перезапуск таймера
      }//*/
  }//while 1

  return -1;
}

код приведен не полностью , только самое важное.
aaarrr
Код
void timer_tick10ms(void)

У Вас прерывание сделано как простая функция.
RuZaKi
забыл вставить в самом верху есть строка
Код
void timer_tick10ms(void) __attribute__ ((interrupt));
aaarrr
Брр. Много лишних и непонятных телодвижений. Попробуйте код из соседней ветки - он точно работает.
RuZaKi
этот код не робит , да помоему он и не полный(для настройки прерывания от таймера).
Нуно же еще настраивать разрешение на прерывание - AIC_IECR, а как же остальные настройки типо
TC_BMR, TC_BCR и т.п.

+ не до конца ясно что должно быть обязательно в функции прирывания, типо обнуление AIC_EOICR , считывание в пустую регистр статуса таймера. Можете поподробнее это расписать.

Приведите плиз полный код для настройки прирываний от таймера.
KAlex
Цитата(RuZaKi @ Mar 12 2008, 15:59) *
Приведите плиз полный код для настройки прирываний от таймера.


void InitTimerInt(void) {
unsigned int dummy;
AT91C_BASE_PMC -> PMC_PCER = 1 << AT91C_ID_TC0;//Enable the clock of the timer0 module ([PMC_PCER]: id = 12)
AT91C_BASE_TC0 -> TC_CCR = AT91C_TC_CLKDIS; //Disable clock [TC_CCR\CLKDIS {p366}] =1
AT91C_BASE_TC0 -> TC_IDR = 0x000000FF;//Disable all interrupts[TC_IDR {p379}]
dummy = AT91C_BASE_TC0 -> TC_SR;//Clear all status by read [TC_SR {p376}]
dummy=dummy;
AT91C_BASE_TC0 -> TC_CMR = AT91C_TC_CLKS_TIMER_DIV5_CLOCK | AT91C_TC_CPCTRG;
AT91C_BASE_TC0 -> TC_CCR = AT91C_TC_CLKEN; //Enable clock [TC_CCR\CLKEN {p366}] =1
AT91C_BASE_TC0 -> TC_RC = 937;//Period/MCK/1024 = 46875 (48 MHz / 1024 / 46875 = 1 sec)
void (*handler)(void);
handler = timer0_irq_handler;
AT91C_BASE_AIC -> AIC_IDCR = (1 << AT91C_ID_TC0);//Disable the interrupt on the interrupt controller
AT91C_BASE_AIC -> AIC_SVR[AT91C_ID_TC0] = (unsigned int)handler;//Interrupt handler routine pointer
AT91C_BASE_AIC -> AIC_SMR[AT91C_ID_TC0] = (2 << 0)|(5 << 5);//(priority =1);[AIC_SMR\SRCTYPE]=0 (Level sensitive)
AT91C_BASE_AIC -> AIC_ICCR = (1 << AT91C_ID_TC0);//[AIC_ICCR\PID12 {p146}]Clear the interrupt
AT91C_BASE_TC0 -> TC_IER = AT91C_TC_CPCS; //[TC_IER\CPCS[4]]=1 (RC Compare IRQ enable)
AT91C_BASE_AIC ->AIC_IECR = (1<<AT91C_ID_TC0);//Interrupt enable [AIC_IECR\PID12 {p145}]=1
AT91C_BASE_AIC -> AIC_ISCR = (1 << AT91C_ID_TC0);//Generate interrupt by software [AIC_ISCR\PID12 {p147}]=1
AT91C_BASE_TC0 -> TC_CCR = AT91C_TC_SWTRG;//Start timer [TC_CCR\SWTRG {p366}] =1
}

void timer0_irq_handler(void){
unsigned int dummy;
dummy = AT91C_BASE_TC0 -> TC_SR;//Acknowledge interrupt status
dummy = dummy;//Suppress warning <<variable "dummy" was set but never used>>
.
.
.
AT91C_BASE_AIC -> AIC_EOICR = AT91C_ID_TC0;
}
aaarrr
Цитата(RuZaKi @ Mar 12 2008, 15:59) *
этот код не робит , да помоему он и не полный(для настройки прерывания от таймера).
Нуно же еще настраивать разрешение на прерывание - AIC_IECR, а как же остальные настройки типо
TC_BMR, TC_BCR и т.п.

Угу, IECR отсутствует - вырывал из живого проекта, а там он включается в другом месте.
Код
AT91C_BASE_AIC->AIC_IECR = (0x01 << AT91C_ID_TC0);


Какой смысл писать BMR и BCR, если использованы внутренние клоки и таймеры используются независимо?

Цитата(RuZaKi @ Mar 12 2008, 15:59) *
+ не до конца ясно что должно быть обязательно в функции прирывания, типо обнуление AIC_EOICR , считывание в пустую регистр статуса таймера. Можете поподробнее это расписать.

Приведите плиз полный код для настройки прирываний от таймера.

Вы сами и написали все, что нужно для прерывания - чтение SR и запись EOICR.
Kirill Frolov
Цитата(aaarrr @ Mar 12 2008, 15:07) *
Код
void timer_tick10ms(void)

У Вас прерывание сделано как простая функция.


У меня все прерывания сделаны как простыв функции -- и это работает... Что я делаю не так? ©
Нет, есть конечно ассемблерный кусок для вектора IRQ...

Вдогонку. Проблемы с подачей клока на нужный модуль MCU, правильное программирование вектора и разрешение прерывания в AIC -- это основное.
aaarrr
Цитата(Kirill Frolov @ Mar 12 2008, 21:39) *
У меня все прерывания сделаны как простыв функции -- и это работает... Что я делаю не так? ©
Нет, есть конечно ассемблерный кусок для вектора IRQ...

У меня тоже, только куски на каждое прерывание свои.

Просто так как решение не очевидное, нужно явно и подробно все описывать. С телепатией далеко не у всех хорошо дела обстоят.
RuZaKi
KAlex спасибо большое за код , ЗАРАБОТАЛО (после подрисовки ctl_global_interrupts_enable()wink.gif.
Ни ужели все дело в последовательности команд(своибразный танец с бубном)?
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.