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

 
 
 
Reply to this topicStart new topic
chernenko
сообщение Apr 10 2007, 11:24
Сообщение #1


Частый гость
**

Группа: Свой
Сообщений: 170
Регистрация: 8-02-06
Из: Москва
Пользователь №: 14 116



Здравствуйте! Столкнулся вот с такой проблемой в 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;

}


Подскажите из-за чего такая проблема.

Сообщение отредактировал chernenko - Apr 10 2007, 11:27
Go to the top of the page
 
+Quote Post
scifi
сообщение Apr 10 2007, 11:45
Сообщение #2


Гуру
******

Группа: Свой
Сообщений: 3 020
Регистрация: 7-02-07
Пользователь №: 25 136



Насчёт обработки прерываний с частотой 2-4 МГц - это слишком оптимистично.
Обработка одного прерывания занимает определённое время. Максимальная частота обработки этих прерываний равна F=1/T. Из того факта, что максимальная частота равна 968000 Гц, можно сделать вывод, что время обработки одного прерывания приблизительно равно 1 мкс.
Кстати, не совсем ясно, зачем обработчик прерывания объявлен как __inline - то ли по недосмотру, то ли от непонимания.
Go to the top of the page
 
+Quote Post
chernenko
сообщение Apr 10 2007, 11:50
Сообщение #3


Частый гость
**

Группа: Свой
Сообщений: 170
Регистрация: 8-02-06
Из: Москва
Пользователь №: 14 116



Цитата(scifi @ Apr 10 2007, 12:45) *
Кстати, не совсем ясно, зачем обработчик прерывания объявлен как __inline - то ли по недосмотру, то ли от непонимания.

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

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

А FIQ с какой максимальной частотой можно обрабатывать?

Сообщение отредактировал chernenko - Apr 10 2007, 12:00
Go to the top of the page
 
+Quote Post

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

 


RSS Текстовая версия Сейчас: 23rd July 2025 - 11:31
Рейтинг@Mail.ru


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