Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: TCO в AT91SAM9261
Форум разработчиков электроники ELECTRONIX.ru > Микроконтроллеры (MCs) > ARM
chernenko
Здравствуйте! Столкнулся вот с такой проблемой в AT91SAM9261.

Мне необходимо обрабатывать событие в прерывание таймера с частотой 2 - 4 МГц

Но столкнулся с такой проблемой:

Выставляю Processor clock = 235929600 Гц, Master clock = 117964800 Гц.
Настраиваю таймер на генерацию прерывания при достижении значения счетного регистра = RC.
Предделитель таймера = 2.
При таких параметрах для генерации прерывания с частотой приблизительно 2 МГц мне нужно записать число 30 в регистр RC.
Записываю, проверяю осцилографом (во время прерывания "дергаю" уровень вывода контроллера) - частота около 968 кГц. То есть меньше чем положено...

Записываю в регистр RC значение 64, осцилографом как и положено наблюдаю частоту 921600.
Записываю в регистр RC значения > 64, осцилографом наблюдаю то, что и должен.
Записываю в регистр RC значения < 64, осцилографом наблюдаю частоту не выше 968 кГц. При этом импулсь дергается по временной оси. (осцилограф адекватный для сигнала).

Что это? Проблема контроллера? Она известна? Или имеется ошибка?

Ниже привожу код инициализации PLL, таймера и обработчик прерывания таймера.
Фрагмент lowlevelinit
Код
// PLLA 235.9296 MHz
#define MUL_PLLA                      (128UL)
#define DIV_PLLA                      (10UL)
#define PLLA_FREQ                     ((MAIN_OSC_CLK*MUL_PLLA)/DIV_PLLA)
#define Pclk                          (PLLA_FREQ) // 235.9296 MHz
#define Fmclk                         (Pclk/2)  //  117.9648 MHz
#define    DELAY_PLL                  100000
#define DELAY_MAIN_FREQ                  100000


AT91C_BASE_PMC->PMC_MOR = (((AT91C_CKGR_OSCOUNT & (0x40 << 8)) | AT91C_CKGR_MOSCEN));
  while (!(AT91C_BASE_PMC->PMC_SR & AT91C_PMC_MOSCS));
  
  if (PLLA_FREQ >= 190000000)
  {
    AT91C_BASE_PMC->PMC_PLLAR = AT91C_CKGR_SRCA                          |
                                AT91C_CKGR_OUTA_2                        |
                                (AT91C_CKGR_DIVA & ( DIV_PLLA <<  0))    |
                                (AT91C_CKGR_MULA & ((MUL_PLLA-1) << 16)) |
                                (AT91C_CKGR_PLLACOUNT & (6 << 8));
  }
  else
  {
    AT91C_BASE_PMC->PMC_PLLAR = AT91C_CKGR_SRCA                          |
                                AT91C_CKGR_OUTA_0                        |
                                (AT91C_CKGR_DIVA & ( DIV_PLLA <<  0))    |
                                (AT91C_CKGR_MULA & ((MUL_PLLA-1) << 16)) |
                                (AT91C_CKGR_PLLACOUNT & (6 << 8));        
      }
  while (!(AT91C_BASE_PMC->PMC_SR & AT91C_PMC_LOCKA));
  while (!(AT91C_BASE_PMC->PMC_SR & AT91C_PMC_MCKRDY));

  AT91C_BASE_PMC->PMC_MCKR = AT91C_PMC_PRES_CLK | AT91C_PMC_MDIV_2;
  while (!(AT91C_BASE_PMC->PMC_SR & AT91C_PMC_MCKRDY));
  
  AT91C_BASE_PMC->PMC_MCKR |= AT91C_PMC_CSS_PLLA_CLK;


Инициализация таймера
Код
void init_tc0(unsigned int tc0_rc_value, unsigned int tc0_clks_timer_div, unsigned int tc0_interrupt_level)
{
  volatile unsigned long dummy;

  AT91C_BASE_PMC->PMC_PCER = (1 << AT91C_ID_TC0);
  
  AT91C_BASE_TC0->TC_CCR = AT91C_TC_CLKDIS;
  AT91C_BASE_TC0->TC_IDR = 0xFFFFFFFF;
  
  dummy = AT91C_BASE_TC0->TC_SR;
  AT91C_BASE_TC0->TC_CMR = tc0_clks_timer_div | AT91C_TC_CPCTRG;
  AT91C_BASE_TC0->TC_CCR = AT91C_TC_CLKEN;
  AT91C_BASE_TC0->TC_IER = AT91C_TC_CPCS;
  AT91C_BASE_AIC->AIC_IDCR = (1 << AT91C_ID_TC0);
  AT91C_BASE_AIC->AIC_SVR[AT91C_ID_TC0] = (unsigned long) tc0_irq_handler;
  AT91C_BASE_AIC->AIC_SMR[AT91C_ID_TC0] = AT91C_AIC_SRCTYPE_INT_HIGH_LEVEL | tc0_interrupt_level;
  AT91C_BASE_AIC->AIC_ICCR = (1 << AT91C_ID_TC0);
  AT91C_BASE_AIC->AIC_IECR = (1 << AT91C_ID_TC0);
  AT91C_BASE_TC0->TC_RC = tc0_rc_value;
  AT91C_BASE_TC0->TC_CCR = AT91C_TC_SWTRG;
  }


Обработчик прерывания таймера
Код
__inline void tc0_irq_handler(void)
{
  volatile unsigned long dummy;

  dummy = AT91C_BASE_TC0->TC_SR;

    AT91C_BASE_PIOA->PIO_SODR = AT91C_PIO_PA7;
    AT91C_BASE_PIOA->PIO_CODR = AT91C_PIO_PA7;

}


Подскажите из-за чего такая проблема.
scifi
Насчёт обработки прерываний с частотой 2-4 МГц - это слишком оптимистично.
Обработка одного прерывания занимает определённое время. Максимальная частота обработки этих прерываний равна F=1/T. Из того факта, что максимальная частота равна 968000 Гц, можно сделать вывод, что время обработки одного прерывания приблизительно равно 1 мкс.
Кстати, не совсем ясно, зачем обработчик прерывания объявлен как __inline - то ли по недосмотру, то ли от непонимания.
chernenko
Цитата(scifi @ Apr 10 2007, 12:45) *
Кстати, не совсем ясно, зачем обработчик прерывания объявлен как __inline - то ли по недосмотру, то ли от непонимания.

По недосмотру

Что же так всё плохо? Неужели обработка прерывания таймера занимает >200 тактов? И другой альтернативы обойти это нет? Может кто-то запускал таймер на такой частоте?
Почему такое большое время обработки прерывания?

А FIQ с какой максимальной частотой можно обрабатывать?
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.