athlon64 0 2 августа, 2014 Опубликовано 2 августа, 2014 · Жалоба Добрый день У меня в проекте на BlackFin BF523 используются 3 таймера общего назначения с генерацией прерывания по достижению значения из TIMERx_PERIOD. Случайно обнаружил что периодически происходит пропуск обработки интервала счёта. Пересмотрел ещё раз даташит на тему таймеров и не нашёл у себя ничего криминального. Функции настройки таймера: uint32_t Timer_Get_SICmask(uint8_t TimerNum) { uint32_t SIC_IAR_Mask = 0xFFFFFFFF; SIC_IAR_Mask &= ~(0xF << (TimerNum << 2)); return SIC_IAR_Mask; } int8_t Timer7_Start(uint32_t FreqHz) { if (!FreqHz) return -1; // Выключаем таймер *pTIMER_DISABLE = TIMDIS7; // Настраиваем таймер *pTIMER7_CONFIG = OUT_DIS | PWM_OUT | PERIOD_CNT | IRQ_ENA; // Выход ШИМ отключен, режим PWM_OUT, счёт до периода, прерывание включено, сброс таймера в 1 (не в 0) // Ширина испульса ШИМ (в данном случае не важно) *pTIMER7_WIDTH = 1; // Период счёта таймера до обнуления с формированием запроса на прерывание *pTIMER7_PERIOD = (TMR_SCLK / FreqHz);// - 1; // Приоритет *pSIC_IAR4 = (*pSIC_IAR4 & Timer_Get_SICmask(7)) | P39_IVG(12); // Присваиваем вектор прерывания для IVG 14 REGISTER_ISR(12, ivg12_isr); // Включаем у SIC вход от периферии *pSIC_IMASK1 |= IRQ_TIMER7; // Обнуляем регистр-счётчик *pTIMER7_COUNTER = 0; // Запускаем таймер *pTIMER_ENABLE = TIMEN7; return 0; } Обработчик прерываний, общий для всех таймеров: ISR(ivg12_isr) { ssync(); uint32_t timer_status = *pTIMER_STATUS; // Снимаем флаги TIMILx и TOVF_ERRx с помощью W1C *pTIMER_STATUS = 0x00FF00FF; if (timer_status & TIMIL0) { } if (timer_status & TIMIL1) { } if (timer_status & TIMIL2) { } if (timer_status & TIMIL3) { } if (timer_status & TIMIL4) { } if (timer_status & TIMIL5) { } if (timer_status & TIMIL6) { } if (timer_status & TIMIL7) { } } Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
athlon64 0 3 августа, 2014 Опубликовано 3 августа, 2014 · Жалоба Видимо пропуск прерывания происходит из-за того, что при обработке прерывания от одного таймера между строками uint32_t timer_status = *pTIMER_STATUS; и *pTIMER_STATUS = 0x00FF00FF; устанавливается флаг TIMIL другого таймера и, соответственно, сразу сбрасывается без обработки. Хотя, казалось бы, вероятность такого события чрезвычайно мала) Переписал обработчик следующим образом #define TIMER_STATUS_FLAGS_MASK_T0 0x00000001 #define TIMER_STATUS_FLAGS_MASK_T1 0x00000002 #define TIMER_STATUS_FLAGS_MASK_T2 0x00000004 #define TIMER_STATUS_FLAGS_MASK_T3 0x00000008 #define TIMER_STATUS_FLAGS_MASK_T4 0x00010000 #define TIMER_STATUS_FLAGS_MASK_T5 0x00020000 #define TIMER_STATUS_FLAGS_MASK_T6 0x00040000 #define TIMER_STATUS_FLAGS_MASK_T7 0x00080000 ISR(ivg13_isr) { ssync(); if (*pTIMER_STATUS & TIMIL0) { *pTIMER_STATUS = TIMER_STATUS_FLAGS_MASK_T0; ssync(); } if (*pTIMER_STATUS & TIMIL1) { *pTIMER_STATUS = TIMER_STATUS_FLAGS_MASK_T1; ssync(); } if (*pTIMER_STATUS & TIMIL2) { *pTIMER_STATUS = TIMER_STATUS_FLAGS_MASK_T2; ssync(); } if (*pTIMER_STATUS & TIMIL3) { *pTIMER_STATUS = TIMER_STATUS_FLAGS_MASK_T3; ssync(); } if (*pTIMER_STATUS & TIMIL4) { *pTIMER_STATUS = TIMER_STATUS_FLAGS_MASK_T4; ssync(); } if (*pTIMER_STATUS & TIMIL5) { *pTIMER_STATUS = TIMER_STATUS_FLAGS_MASK_T5; ssync(); } if (*pTIMER_STATUS & TIMIL6) { *pTIMER_STATUS = TIMER_STATUS_FLAGS_MASK_T6; ssync(); } if (*pTIMER_STATUS & TIMIL7) { *pTIMER_STATUS = TIMER_STATUS_FLAGS_MASK_T7; ssync(); } } Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться