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

 
 
4 страниц V   1 2 3 > »   
Reply to this topicStart new topic
> real time timer - прерывание по переполнению
srm
сообщение May 25 2010, 15:42
Сообщение #1


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

Группа: Участник
Сообщений: 144
Регистрация: 27-12-09
Из: Пермь
Пользователь №: 54 501



Не нашёл как установить обработчик прерывания по переполнению для таймера реального времени. Нужно ведь как-то так:
Код
AT91F_AIC_ConfigureIt(AT91C_BASE_AIC, ???, m_interrupt_priority, AT91C_AIC_SRCTYPE_INT_HIGH_LEVEL, (void(*)())interrupt_handler);

А я не знаю какой у него ID..
Go to the top of the page
 
+Quote Post
srm
сообщение May 25 2010, 17:12
Сообщение #2


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

Группа: Участник
Сообщений: 144
Регистрация: 27-12-09
Из: Пермь
Пользователь №: 54 501



Забыл указать контроллер. at91sam7s256.
Можно ли вообще зарегистрировать обработчик на переполнение RTTC таймера?

Сообщение отредактировал srm - May 25 2010, 17:13
Go to the top of the page
 
+Quote Post
injen-d
сообщение May 25 2010, 17:32
Сообщение #3


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

Группа: Свой
Сообщений: 91
Регистрация: 10-10-07
Из: Воронежа
Пользователь №: 31 250



Таймер RTT входит в системную периферию (идентификатор: AT91C_ID_SYS).
должно быть примерно так:AIC_ConfigureIT(AT91C_ID_SYS, AT91C_AIC_PRIOR_HIGHEST | AT91C_AIC_SRCTYPE_POSITIVE_EDGE, SYS_handler),
где функция void SYS_handler(void) - обработчик прерывания от системной периферии, и уже в нем Вы должны выяснить, что именно вызвало данное прерывание: RTT или/и PIT или/и PMC или/и DBGU и т.д.


--------------------
- Бендер, ты же робот, зачем тебе пить пиво?
- Незачем! Я могу бросить в любой момент!
Go to the top of the page
 
+Quote Post
srm
сообщение May 25 2010, 17:54
Сообщение #4


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

Группа: Участник
Сообщений: 144
Регистрация: 27-12-09
Из: Пермь
Пользователь №: 54 501



injen-d, спасибо.
Go to the top of the page
 
+Quote Post
aaarrr
сообщение May 25 2010, 19:19
Сообщение #5


Гуру
******

Группа: Свой
Сообщений: 10 713
Регистрация: 11-12-04
Пользователь №: 1 448



Еще обратите внимание, что что флаги RTT сбрасываются через 2 периода SCLK (~61us) после чтения статусного регистра. Поэтому попасть в прерывание просто, а вот выйти из него - не очень sad.gif
Go to the top of the page
 
+Quote Post
srm
сообщение May 26 2010, 13:45
Сообщение #6


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

Группа: Участник
Сообщений: 144
Регистрация: 27-12-09
Из: Пермь
Пользователь №: 54 501



Столкнулся с такой проблемой. Я поставил делитель 3. Это примерно 10 тактов за мс. Если запрашивать показания таймера на больших временах (>10 ms), то всё правильно (разница тиков соответствует прошедшему времени). Но если запрашивать показания через ~1ms, то значения получаются одинаковыми. Почему так происходит, ведь таймер за 1мс должен протикать 10 раз?

Причём, интересная особенность. Если сделать так:
Код
  uint32_t x = AT91F_RTTReadValue(AT91C_BASE_RTTC);
  for (volatile uint32_t i = 0; i < 1000; i ++);
  x = AT91F_RTTReadValue(AT91C_BASE_RTTC) - x;

то всё правильно. Если же вызывать AT91F_RTTReadValue(AT91C_BASE_RTTC) по таймеру, то разность получается 0.

Сообщение отредактировал srm - May 26 2010, 13:03
Go to the top of the page
 
+Quote Post
aaarrr
сообщение May 26 2010, 13:58
Сообщение #7


Гуру
******

Группа: Свой
Сообщений: 10 713
Регистрация: 11-12-04
Пользователь №: 1 448



Цитата(srm @ May 26 2010, 17:45) *
Если же вызывать AT91F_RTTReadValue(AT91C_BASE_RTTC) по таймеру, то разность получается 0.

Тогда покажите, как вы это делаете по таймеру.
Go to the top of the page
 
+Quote Post
srm
сообщение May 26 2010, 14:17
Сообщение #8


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

Группа: Участник
Сообщений: 144
Регистрация: 27-12-09
Из: Пермь
Пользователь №: 54 501



Локализовал проблему. Вот обработчик прерывания:
Код
  static void interrupt_handler()
  {
    uint32_t mask = m_timer->TC_SR;
    m_instance->on_interrupt(mask);
    AT91C_BASE_AIC->AIC_EOICR = 0;
  }

  inline bool on_interrupt(uint32_t mask)
  {
    if (mask & AT91C_TC_CPAS)
      on_event_a();
    if (mask & AT91C_TC_CPBS)
      on_event_b();
    if (mask & AT91C_TC_CPCS)
      on_overflow();

    return (mask & (AT91C_TC_CPAS | AT91C_TC_CPCS | AT91C_TC_CPBS)) != 0;
  }

Почему-то mask при каждом срабатывании содержит биты AT91C_TC_CPAS | AT91C_TC_CPBS (хотя значения регистров А = 0x2EED, B = 0x8CC9, C = 0xBBB6). Поэтому при каждом срабатывании вызываются оба метода:
Код
  virtual void on_event_a()
  {
    m_time = CWatch::get_instance()->get_time_us();
  }

  virtual void on_event_b()
  {
    m_time = CWatch::get_instance()->get_time_us() - m_time;
    m_time ++;
  }

почему регистр статуса не чистится?
--------------------------------------------------
Что-то с форматом вызова.. если __irq static void interrupt_handler() - вроде, правильно, работает. Только почему-то через некоторое время после старта выполнение уходит в UndefinedHandler. Мой обработчик перестаёт вызываться. IRQ стек не переполнен...

Сообщение отредактировал srm - May 26 2010, 14:29
Go to the top of the page
 
+Quote Post
aaarrr
сообщение May 26 2010, 14:39
Сообщение #9


Гуру
******

Группа: Свой
Сообщений: 10 713
Регистрация: 11-12-04
Пользователь №: 1 448



Цитата(srm @ May 26 2010, 18:17) *
Почему-то mask при каждом срабатывании содержит биты AT91C_TC_CPAS | AT91C_TC_CPBS (хотя значения регистров А = 0x2EED, B = 0x8CC9, C = 0xBBB6).

Может, просто прерывание по CPA забыли разрешить?

Цитата(srm @ May 26 2010, 18:17) *
Что-то с форматом вызова.. если __irq static void interrupt_handler() - вроде, правильно, работает. Только почему-то через некоторое время после старта выполнение уходит в UndefinedHandler. Мой обработчик перестаёт вызываться. IRQ стек не переполнен...

Как обрабатывается вектор прерывания в стартапе?
Go to the top of the page
 
+Quote Post
srm
сообщение May 26 2010, 14:46
Сообщение #10


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

Группа: Участник
Сообщений: 144
Регистрация: 27-12-09
Из: Пермь
Пользователь №: 54 501



Цитата
Может, просто прерывание по CPA забыли разрешить?
нет, там всё норм.

Цитата
Как обрабатывается вектор прерывания в стартапе?
там стандартный IAR'овский обработчик:
Код
irqHandler:
        /* Save interrupt context on the stack to allow nesting */
        SUB     lr, lr, #4
        STMFD   sp!, {lr}
        MRS     lr, SPSR
        STMFD   sp!, {r0, lr}

        /* Write in the IVR to support Protect Mode */
        LDR     lr, =AT91C_BASE_AIC
        LDR     r0, [r14, #AIC_IVR]
        STR     lr, [r14, #AIC_IVR]

        /* Branch to interrupt handler in Supervisor mode */
        MSR     CPSR_c, #ARM_MODE_SYS
        STMFD   sp!, {r1-r3, r4, r12, lr}
        MOV     lr, pc
        BX      r0
        LDMIA   sp!, {r1-r3, r4, r12, lr}
        MSR     CPSR_c, #ARM_MODE_IRQ | I_BIT

        /* Acknowledge interrupt */
        LDR     lr, =AT91C_BASE_AIC
        STR     lr, [r14, #AIC_EOICR]

        /* Restore interrupt context and branch back to calling code */
        LDMIA   sp!, {r0, lr}
        MSR     SPSR_cxsf, lr
        LDMIA   sp!, {pc}^


Сообщение отредактировал srm - May 26 2010, 14:46
Go to the top of the page
 
+Quote Post
aaarrr
сообщение May 26 2010, 14:51
Сообщение #11


Гуру
******

Группа: Свой
Сообщений: 10 713
Регистрация: 11-12-04
Пользователь №: 1 448



Цитата(srm @ May 26 2010, 18:46) *
там стандартный IAR'овский обработчик:

Раз так, то никаких __irq не нужно. Как и записи EOICR в вашем обработчике.
Go to the top of the page
 
+Quote Post
srm
сообщение May 26 2010, 15:01
Сообщение #12


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

Группа: Участник
Сообщений: 144
Регистрация: 27-12-09
Из: Пермь
Пользователь №: 54 501



Цитата
Раз так, то никаких __irq не нужно. Как и записи EOICR в вашем обработчике.
запускаю на выполнение. ставлю бряк на обработчик прерывания: mask == 0x1001C, т.е. содержит все три флага: AT91C_TC_CPCS | AT91C_TC_CPAS | AT91C_TC_CPBS.

если же сначала поставлю бряк и поймаю самое первое прерывание, то всё нормально: mask == 0x10008, т.е. содержит только флаг AT91C_TC_CPBS.

magic
Go to the top of the page
 
+Quote Post
aaarrr
сообщение May 26 2010, 15:19
Сообщение #13


Гуру
******

Группа: Свой
Сообщений: 10 713
Регистрация: 11-12-04
Пользователь №: 1 448



Проверьте, что в прерывании действительно читается SR (в дизассемблере). Убедитесь, что обработка прерывания не длится слишком долго.
Ну и уберите __irq и EOICR, если они еще остались.
Go to the top of the page
 
+Quote Post
srm
сообщение May 26 2010, 15:42
Сообщение #14


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

Группа: Участник
Сообщений: 144
Регистрация: 27-12-09
Из: Пермь
Пользователь №: 54 501



aaarrr, да, вроде, всё правильно.. может что-нибудь с режимом..

Код
m_timer->TC_CMR = calculate_optimal_divider(max_time_ms) | AT91C_TC_WAVESEL_UP_AUTO | AT91C_TC_WAVE | AT91C_TC_EEVT_XC0;


Сообщение отредактировал srm - May 26 2010, 15:42
Go to the top of the page
 
+Quote Post
aaarrr
сообщение May 26 2010, 16:02
Сообщение #15


Гуру
******

Группа: Свой
Сообщений: 10 713
Регистрация: 11-12-04
Пользователь №: 1 448



Цитата(srm @ May 26 2010, 19:42) *
может что-нибудь с режимом.

Может. Выложите всю инициализацию, включая calculate_optimal_divider() и т.п., иначе можно только гадать.
Go to the top of the page
 
+Quote Post

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

 


RSS Текстовая версия Сейчас: 20th July 2025 - 01:07
Рейтинг@Mail.ru


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