Записная книжка разработчика

Мои проекты

Repetitive Interrupt Timer

| Comments

Repetitive Interrupt Timer (RIT) является ещё одним таймером, которого не было в ARM7, и который появился в Cortex M3. Как следует из названия, он предназначен для генерации прерываний, повторяющихся через определённые промежутки времени. Его структура намного проще, чем у обычного таймера-счётчика, но несколько сложнее, чем у SysTick, рассмотренного здесь: http://32bit.me/?p=796. В большинстве практических случаев эти таймеры взаимозаменяемы.
Ниже будет рассмотрено применение таймера RIT.

Итак, RIT содержит 4 регистра:
RICOMPVAL - в этом регистре должно быть записано значение, с которым производится сравнение значения счётчика.
RIMASK - в этом регистре записывается значение маски, которая применяется к результату сравнения. По умолчанию равен 0. Практическая польза от применения этого регистра неочевидна, поэтому оставим его в нулевом состоянии.
RICTRL - регистр управления. Содержит следующие биты:

  • RITINT - флаг прерывания. Нужен в обработчике прерывания.
  • RITENCLR -1 означает, что таймер будет обнуляться по достижении совпадения RICOUNTER и RICOMPVAL. Начальное значение 0. Для генерации периодических прерываний должен быть 1.
  • RITENBR - 1 в этом разряде означает, что таймер будет останавливаться, когда микроконтроллер остановлен в отладчике. Значение по умолчанию: 1
  • RITEN - 1 - работа таймера разрешена. Значение по умолчанию: 1

RICOUNTER - собственно счётчик. Значение после сброса: 0, запись в этот регистр, как правило, не требуется (хотя возможна).

Таймер тактируется периферийной тактовой частотой (PCLK).

Пусть нам нужно получить прерывание, возникающее периодически с частотой 10 кГц, а тактовая частота микроконтроллера cclk = 100 МГц, периферийная тактовая частота pclk = cclk/4 = 25 МГц.

Инициализация таймера RIT в этом случае выглядит так:

void InitRepetitiveTimer(void)
{
  PCONP_bit.PCRIT = 1; // включаем тактирование и питание
  RICOMPVAL = 2500;//25МГц/10кГц = 2500
  RICTRL_bit.RITENCLR = 1;
  RICTRL_bit.RITENBR  = 1;
  RICTRL_bit.RITEN    = 1;
}

Обработчик прерывания:

void RIT_IRQHandler(void)
{
  //сообщаем контроллеру прерываний, что прерывание обрабатывается
  RICTRL_bit.RITINT = 1;
  //...do something
}

Из приведённого кода видно, что прерывание снимается с обработки другим способом, чем прерывание SysTick или Timer0-3. Обычно для этой цели используется функция, которая может выглядеть, например, так:

void NVIC_ClrPend(Int32U IntNumber)
{
  volatile unsigned long * pNVIC_ClrPend = &CLRPEND0;

  assert((NVIC_WDT <= IntNumber) && (NVIC_PLL1 >= IntNumber));
  IntNumber -= NVIC_WDT;
  pNVIC_ClrPend += IntNumber/32;
  *pNVIC_ClrPend = (1UL<<(IntNumber%32));
}

Однако в данном случае достаточно всего лишь установить бит RITINT регистра RICTRL в 1, этого достаточно для сброса прерывания.

Полное описание таймера Repetitive Interrupt Timer приведено в [1], в разделе "Chapter 22: LPC17xx Repetitive Interrupt Timer (RIT)"

Литература:

1. UM10360. LPC17xx User Manual. Rev 01 — 4 January 2010.