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

 
 
2 страниц V   1 2 >  
Reply to this topicStart new topic
> AT91sam7s64 tc1 tc2 interrupt, вопрос знатокам
D!m@
сообщение Jun 28 2010, 18:17
Сообщение #1


Участник
*

Группа: Участник
Сообщений: 74
Регистрация: 10-04-07
Пользователь №: 26 901



Здравствуйте!

Пишу под AT91sam7s64.

Столкнулся с такой проблемой:
Я пользуюсь 2 таймерами TC1 и TC2 в режиме захвата.
Таймера настроены на захват регистра А и рестарт по сравнению с регистром С .
Таймера запущены синхронно и значения регистра С одинаковы.

На таймера есть прерывания по захвату А и сравнению С, по сравнению прерывания возникают одновримено.

Все вроде работает неоприледен время, а потом тупо перестает заходить в обработчик прерываний одного из таймеров (рас 1 рас 2 ..) .

Не заходит, пока не поставлю в дебаге точку останова, непосредственно в том обработчике.
После чего все начинает снова работать не оприделеное время и так по колу.

Код
static void ISR_TC1(void)
{
   unsigned int uiSR = AT91C_BASE_TC1->TC_SR;
    if( (uiSR & AT91C_TC_CPCS) )
   {
       uiOverTC1++;
   }
   if( uiSR & AT91C_TC_LDRAS )
   {
       unsigned int uiRA = AT91C_BASE_TC1->TC_RA;  
       if (uiStartT1 <3 )
         {
             Timer1[uiStartT1].uiRA = uiRA;
             Timer1[uiStartT1].uiOver = uiOverTC1;
             Timer1[uiStartT1].bZap = true;
             uiStartT1++;
         }
   }
  
}
void InitTC1ForFreq()
{
  
    //AIC configure.
    AT91C_BASE_AIC->AIC_IDCR = 1 << AT91C_ID_TC1;     // Disable the interrupt first
    AT91C_BASE_AIC->AIC_SMR[AT91C_ID_TC1] = AT91C_AIC_SRCTYPE_POSITIVE_EDGE | AT91C_AIC_PRIOR_HIGHEST;
    AT91C_BASE_AIC->AIC_SVR[AT91C_ID_TC1] = (unsigned int) ISR_TC1;
    AT91C_BASE_AIC->AIC_ICCR = 1 << AT91C_ID_TC1;     // Clear interrupt
    AT91C_BASE_AIC->AIC_IECR = 1 << AT91C_ID_TC1;     // Enables interrupts
    
  
    
    // Enable PWMC peripheral clock
    AT91C_BASE_PMC->PMC_PCER = 1 << AT91C_ID_TC1;
    
    // Disable TC clock
    AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKDIS;

    // Disable interrupts
    AT91C_BASE_TC1->TC_IDR = 0xFFFFFFFF;

    // Clear status register
    AT91C_BASE_TC1->TC_SR;

    // Set mode
    AT91C_BASE_TC1->TC_CMR = AT91C_TC_CLKS_TIMER_DIV1_CLOCK | // MCK/2
                             AT91C_TC_BURST_NONE |
                             AT91C_TC_EEVTEDG_NONE |
                             AT91C_TC_CPCTRG |
                             AT91C_TC_ABETRG |    
                             AT91C_TC_LDRA_RISING; // each edge of TIOA
                        
    AT91C_BASE_TC1->TC_RC = 0xffff;
    
    // Enable interrpt
    AT91C_BASE_TC1->TC_IER = AT91C_TC_CPCS | // Counter compare CR
                             AT91C_TC_LDRAS;  // RA Loading
    
    // Start TC1  
    AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKEN | AT91C_TC_SWTRG;
    
    // Atach to PIO for TIOA1
    AT91C_BASE_PIOA->PIO_BSR = AT91C_PA15_TIOA1;
    AT91C_BASE_PIOA->PIO_PER = AT91C_PA15_TIOA1;
}
////////////////////////////////////////////////////////////////////////////////
// Timer 2  IntL
////////////////////////////////////////////////////////////////////////////////

unsigned int uiOverTC2 = 0;       //  ïåðåïîâíåííÿ òàéìåðà
unsigned int uiTC2LastRA = 0;
static void ISR_TC2(void)
{
   unsigned int uiSR = AT91C_BASE_TC2->TC_SR;
    if( (uiSR & AT91C_TC_CPCS) )
   {
       uiOverTC2++;
   }
   if( (uiSR & AT91C_TC_LDRAS) )
   {
       unsigned int uiRA = AT91C_BASE_TC2->TC_RA;  
       if (uiStartT2 <3 )
       {
           Timer2[uiStartT2].uiRA = uiRA;
           Timer2[uiStartT2].uiOver = uiOverTC2;
           Timer2[uiStartT2].bZap = true;
           uiStartT2++;
       }
   }
  
}
void InitTC2ForFreq()
{
  

    //AIC configure.
    AT91C_BASE_AIC->AIC_IDCR = 1 << AT91C_ID_TC2;     // Disable the interrupt first
    AT91C_BASE_AIC->AIC_SMR[AT91C_ID_TC2] = AT91C_AIC_SRCTYPE_POSITIVE_EDGE | AT91C_AIC_PRIOR_HIGHEST;
    AT91C_BASE_AIC->AIC_SVR[AT91C_ID_TC2] = (unsigned int) ISR_TC2;
    AT91C_BASE_AIC->AIC_ICCR = 1 << AT91C_ID_TC2;     // Clear interrupt
    AT91C_BASE_AIC->AIC_IECR = 1 << AT91C_ID_TC2;     // Enables interrupts
    
  
    
    // Enable PWMC peripheral clock
    AT91C_BASE_PMC->PMC_PCER = 1 << AT91C_ID_TC2;
    
    // Disable TC clock
    AT91C_BASE_TC2->TC_CCR = AT91C_TC_CLKDIS;

    // Disable interrupts
    AT91C_BASE_TC2->TC_IDR = 0xFFFFFFFF;

    // Clear status register
    AT91C_BASE_TC2->TC_SR;

    // Set mode
    AT91C_BASE_TC2->TC_CMR = AT91C_TC_CLKS_TIMER_DIV1_CLOCK | // MCK/2
                             AT91C_TC_BURST_NONE |
                             AT91C_TC_EEVTEDG_NONE |
                             AT91C_TC_CPCTRG |
                             AT91C_TC_ABETRG |    
                             AT91C_TC_LDRA_RISING; // each edge of TIOA
                        
    AT91C_BASE_TC2->TC_RC = 0xffff;
                        
    // Enable interrpt
    AT91C_BASE_TC2->TC_IER = AT91C_TC_CPCS | // Counter
                            AT91C_TC_LDRAS;  // RA Loading
    
    // Start TC1  
    AT91C_BASE_TC2->TC_CCR = AT91C_TC_CLKEN | AT91C_TC_SWTRG;
    
    //synhron timers
    AT91C_BASE_TCB->TCB_BCR = AT91C_TCB_SYNC;
    
    // Atach to PIO for TIOA2
    AT91C_BASE_PIOA->PIO_BSR = AT91C_PA26_TIOA2;
    AT91C_BASE_PIOA->PIO_PER = AT91C_PA26_TIOA2;
}
Go to the top of the page
 
+Quote Post
D!m@
сообщение Jun 29 2010, 10:39
Сообщение #2


Участник
*

Группа: Участник
Сообщений: 74
Регистрация: 10-04-07
Пользователь №: 26 901



Заметил что когда перестает заходить в прерывание ТС1 то сбрасывается флаг AIC_IPR но AIC_IMR остается установленным соответствующего таймера. Почему не знаю.

Да и не всегда точка останова спасает.


Почему прерывание T1 перестает обрабатываться и почему? help.gif
Go to the top of the page
 
+Quote Post
aaarrr
сообщение Jun 29 2010, 11:02
Сообщение #3


Гуру
******

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



Цитата(D!m@ @ Jun 29 2010, 14:39) *
Почему прерывание T1 перестает обрабатываться и почему? help.gif

JTAG отключить не пробовали? Ну и до кучи поставьте AT91C_AIC_SRCTYPE_INT_HIGH_LEVEL вместо AT91C_AIC_SRCTYPE_POSITIVE_EDGE.
Go to the top of the page
 
+Quote Post
D!m@
сообщение Jun 29 2010, 12:47
Сообщение #4


Участник
*

Группа: Участник
Сообщений: 74
Регистрация: 10-04-07
Пользователь №: 26 901



Цитата(aaarrr @ Jun 29 2010, 14:02) *
Ну и до кучи поставьте AT91C_AIC_SRCTYPE_INT_HIGH_LEVEL вместо AT91C_AIC_SRCTYPE_POSITIVE_EDGE.


Вроде помогло.
Но обясните почему не работало с AT91C_AIC_SRCTYPE_POSITIVE_EDGE ?
Go to the top of the page
 
+Quote Post
aaarrr
сообщение Jun 29 2010, 13:17
Сообщение #5


Гуру
******

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



Цитата(D!m@ @ Jun 29 2010, 16:47) *
Но обясните почему не работало с AT91C_AIC_SRCTYPE_POSITIVE_EDGE ?

Чисто теоретически это возможно, если при обработке прерывания от TC по какой-либо причине не считывается TC_SR - линия прерывания останется в активном состоянии, логика AIC будет сброшена, прерывания работать перестанут. К такому же эффекту может привести и запись ICCR.
Go to the top of the page
 
+Quote Post
EugenB2
сообщение Jul 17 2010, 21:41
Сообщение #6





Группа: Участник
Сообщений: 13
Регистрация: 14-01-10
Пользователь №: 54 820



Цитата(D!m@ @ Jun 29 2010, 15:47) *
Вроде помогло.
Но обясните почему не работало с AT91C_AIC_SRCTYPE_POSITIVE_EDGE ?

А у меня была обратная проблема с USART - возникало Spurious Interrupt из-за AT91C_AIC_SRCTYPE_INT_LEVEL_SENSITIVE пришлось сменить на AT91C_AIC_SRCTYPE_POSITIVE_EDGE.
Но в таймерах я всегда AT91C_AIC_SRCTYPE_INT_LEVEL_SENSITIVE использовал изначально и проблем не было таких.

А вообще SAM7S довольно глючный контроллер... errata "радует", хотя по TC там нет ничего.

Да... и, если в IAR пишется, то почему бы не пользоваться стандарными библиотечными функциями rolleyes.gif :
AT91F_PMC_EnablePeriphClock ( AT91C_BASE_PMC, 1<< AT91C_ID_TC1 );
AT91F_AIC_ConfigureIt ( AT91C_BASE_AIC, AT91C_ID_TC1, TIMER1_INTERRUPT_LEVEL,AT91C_AIC_SRCTYPE_INT_LEVEL_SENSITIVE, TimerIRQHandler1 );
Go to the top of the page
 
+Quote Post
aaarrr
сообщение Jul 17 2010, 22:09
Сообщение #7


Гуру
******

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



Цитата(EugenB2 @ Jul 18 2010, 01:41) *
А у меня была обратная проблема с USART - возникало Spurious Interrupt из-за AT91C_AIC_SRCTYPE_INT_LEVEL_SENSITIVE пришлось сменить на AT91C_AIC_SRCTYPE_POSITIVE_EDGE.

Spurious Interrupt возникает по вполне определенным причинам и не является проблемой, если, конечно, не снабжено зависающей заглушкой (в атмеловских примерах встречался такой маразм).

Цитата(EugenB2 @ Jul 18 2010, 01:41) *
Да... и, если в IAR пишется, то почему бы не пользоваться стандарными библиотечными функциями rolleyes.gif :

К IAR'у, слава богу, данные функции никакого отношения не имеют. Для записи значения в регистр можно обойтись и без "библиотек".
А если нужно что-то сложнее, то надежнее использовать собственную голову, дабы не украшать программу подобными чудесами программистской мысли:
Код
//*----------------------------------------------------------------------------
//* \fn    AT91F_SSC_SetBaudrate
//* \brief Set the baudrate according to the CPU clock
//*----------------------------------------------------------------------------
__inline void AT91F_SSC_SetBaudrate (
        AT91PS_SSC pSSC,        // \arg pointer to a SSC controller
        unsigned int mainClock, // \arg peripheral clock
        unsigned int speed)     // \arg SSC baudrate
{
        unsigned int baud_value;
        //* Define the baud rate divisor register
        if (speed == 0)
           baud_value = 0;
        else
        {
           baud_value = (unsigned int) (mainClock * 10)/(2*speed);
           if ((baud_value % 10) >= 5)
                  baud_value = (baud_value / 10) + 1;
           else
                  baud_value /= 10;
        }

        pSSC->SSC_CMR = baud_value;
}

Go to the top of the page
 
+Quote Post
EugenB2
сообщение Jul 20 2010, 07:45
Сообщение #8





Группа: Участник
Сообщений: 13
Регистрация: 14-01-10
Пользователь №: 54 820



Цитата(aaarrr @ Jul 18 2010, 01:09) *
Spurious Interrupt возникает по вполне определенным причинам и не является проблемой, если, конечно, не снабжено зависающей заглушкой (в атмеловских примерах встречался такой маразм).


К IAR'у, слава богу, данные функции никакого отношения не имеют. Для записи значения в регистр можно обойтись и без "библиотек".
А если нужно что-то сложнее, то надежнее использовать собственную голову, дабы не украшать программу подобными чудесами программистской мысли:
Код
//*----------------------------------------------------------------------------
//* \fn    AT91F_SSC_SetBaudrate
//* \brief Set the baudrate according to the CPU clock
//*----------------------------------------------------------------------------
__inline void AT91F_SSC_SetBaudrate (
        AT91PS_SSC pSSC,        // \arg pointer to a SSC controller
        unsigned int mainClock, // \arg peripheral clock
        unsigned int speed)     // \arg SSC baudrate
{
...
}


Проблему с Spurious Interrupt я и решил убиранием заглушки плюс AT91C_AIC_SRCTYPE_POSITIVE_EDGE.

Согласен, что не все функции библиотечные хороши, что там может быть заложена "бомба" ))), но куда нагляднее и красив код:

AT91F_AIC_Configure(AT91C_BASE_AIC, irq_id, DEBUG_INTERRUPT_LEVEL,DEBUG_INTERRUPT_LEVEL, AT91C_AIC_SRCTYPE_INT_LEVEL_SENSITIVE, newHandler );
AT91F_AIC_EnableIt (AT91C_BASE_AIC, irq_id);

ЧЕМ вот это нагромождение:
/////////// AIC

unsigned int mask ;

mask = 0x1 << irq_id ;
//* Disable the interrupt on the interrupt controller
pAic->AIC_IDCR = mask ;
//* Save the interrupt handler routine pointer and the interrupt priority
pAic->AIC_SVR[irq_id] = (unsigned int) newHandler ;
//* Store the Source Mode Register
pAic->AIC_SMR[irq_id] = src_type | priority ;
//* Clear the interrupt on the interrupt controller
pAic->AIC_ICCR = mask ;

// AT91F_AIC_EnableIt
//* Enable the interrupt on the interrupt controller
pAic->AIC_IECR = 0x1 << irq_id ;

Тем более, к примеру, короткие функции все inline и очень наглядны для работы, чем вписывать регистры:

//*----------------------------------------------------------------------------
//* \fn AT91F_UDP_EpSet
//* \brief Set flag in the endpoint CSR register
//*----------------------------------------------------------------------------
__inline void AT91F_UDP_EpSet(
AT91PS_UDP pUDP, // \arg pointer to a UDP controller
unsigned char endpoint, // \arg endpoint number
unsigned int flag) // \arg flag to be cleared
{
pUDP->UDP_CSR[endpoint] |= flag;
}

//*----------------------------------------------------------------------------
//* \fn AT91F_UDP_EpStatus
//* \brief Return the endpoint CSR register
//*----------------------------------------------------------------------------
__inline unsigned int AT91F_UDP_EpStatus(
AT91PS_UDP pUDP, // \arg pointer to a UDP controller
unsigned char endpoint) // \arg endpoint number
{
return pUDP->UDP_CSR[endpoint];
}

//*----------------------------------------------------------------------------
//* \fn AT91F_UDP_GetInterruptMaskStatus
//* \brief Return UDP Interrupt Mask Status
//*----------------------------------------------------------------------------
__inline unsigned int AT91F_UDP_GetInterruptMaskStatus( // \return UDP Interrupt Mask Status
AT91PS_UDP pUdp) // \arg pointer to a UDP controller
{
return pUdp->UDP_IMR;
}

А если в 10 местах использовать инит AIC, то совсем некрасиво.

Когда вы пользуетесь вызовами функций драйверов сети, i2c например, вы же не обращаетесь в регистры каждый раз напрямую игнорируя библиотечные вызовы. Есть библиотека(не важно эта или другая) и если что-то исправить надо в вызываемых функциях, то можно подправить исходник.
Чем сложнее процессор или контроллер, тем больше кода инита периферии и т.д., если сравнить с AVR, где раз два и сделал все что надо ).

Если данные библиотека не так удачна, то можно свою написать с основными для себя функциями и потом их везде использовать.

PS: Впрочем, я уж очень сгустил краски в ответе. Но я при написании стараюсь сразу убрать все прямые обращения к регистрам в свои библиотеки ))).
Если места не хватает, то да... приходиться потрошить все и убирать лишние библиотечные вызовы, но с такими объемами FLASH на ARM такие проблемы только на AVR мелких решать приходится ))).

Так что никак не могу сказать, что вы правы на все 100.

Сообщение отредактировал EugenB2 - Jul 20 2010, 07:50
Go to the top of the page
 
+Quote Post
aaarrr
сообщение Jul 20 2010, 14:03
Сообщение #9


Гуру
******

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



Цитата(EugenB2 @ Jul 20 2010, 11:45) *
ЧЕМ вот это нагромождение:

Зато в этом нагромождении видно что и как делается.

Цитата(EugenB2 @ Jul 20 2010, 11:45) *
Тем более, к примеру, короткие функции все inline и очень наглядны для работы, чем вписывать регистры:

//*----------------------------------------------------------------------------
//* \fn AT91F_UDP_EpSet
//* \brief Set flag in the endpoint CSR register
//*----------------------------------------------------------------------------
__inline void AT91F_UDP_EpSet(
AT91PS_UDP pUDP, // \arg pointer to a UDP controller
unsigned char endpoint, // \arg endpoint number
unsigned int flag) // \arg flag to be cleared
{
pUDP->UDP_CSR[endpoint] |= flag;
}

Хороший пример "бомбы". Так работать с CSR можно далеко не всегда. А по названию функции нельзя догадаться об особенностях ее работы.

Цитата(EugenB2 @ Jul 20 2010, 11:45) *
Когда вы пользуетесь вызовами функций драйверов сети, i2c например, вы же не обращаетесь в регистры каждый раз напрямую игнорируя библиотечные вызовы. Есть библиотека(не важно эта или другая) и если что-то исправить надо в вызываемых функциях, то можно подправить исходник.
Чем сложнее процессор или контроллер, тем больше кода инита периферии и т.д., если сравнить с AVR, где раз два и сделал все что надо ).

Если вы заметили, в этой "библиотеке" совершенно проигнорирована хоть сколько-нибудь сложная периферия (EMAC, UDP, CAN). А использовать библиотечные функции для установки бита в регистре - это, по-моему, совершенный маразм, только усложняющий чтение программы.

P.S. Я совсем не против написания библиотек для периферии, просто at91lib - это отличный пример того, как этого делать не надо.
Go to the top of the page
 
+Quote Post
Waso
сообщение Aug 10 2010, 09:25
Сообщение #10


Местный
***

Группа: Свой
Сообщений: 268
Регистрация: 4-11-05
Пользователь №: 10 470



Цитата(aaarrr @ Jun 29 2010, 18:02) *
JTAG отключить не пробовали?

Здравствуйте! Какраз столкнулся с такой проблемой - когда прошиваю программу через J-Link, и запускаю в С-SPY, то почему-то отказываются работать прерывания. Зато если тут-же нажать Reset на плате - все начинает работать как надо. IAR 4.40, отладочная плата AT91SAM7X-ЕК. С чем это может быть связано? Программу гружу во флеш. В mac файле никакой работы с прерываниями не обнаружил...
Go to the top of the page
 
+Quote Post
aaarrr
сообщение Aug 10 2010, 09:36
Сообщение #11


Гуру
******

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



Сброс логики AIC'а (8 последовательных чтений AIC_IVR, если не в protect mode записей EOICR) при инициализации делаете?
Go to the top of the page
 
+Quote Post
Waso
сообщение Aug 10 2010, 11:14
Сообщение #12


Местный
***

Группа: Свой
Сообщений: 268
Регистрация: 4-11-05
Пользователь №: 10 470



Нет. Не делаю. Первый раз такой способ вижу. Но мне идея понравилась. Написал такое:
Код
   for(char i=8; i--;  )
   {
     tim = AT91C_BASE_AIC->AIC_IVR;
     AT91C_BASE_AIC->AIC_EOICR = tim;
   }
  tim = AT91C_BASE_AIC->AIC_FVR;
  AT91C_BASE_AIC->AIC_EOICR = tim;
Заработало. Правда работает и если оставлять лишь последнюю строку. Но к сожалению это все работает в простой тестовой проге, а в нужной мне - грабли остались. Теперь вылетает в dabt или pabt. Буду искать дальше. Спасибо!
=====================================UPDATED================================
В основной проге убрал модификаторы __irq __arm от объявления процедуры прерывания - и заработало!! ))
Что я делаю не так? (с)
Go to the top of the page
 
+Quote Post
aaarrr
сообщение Aug 10 2010, 12:04
Сообщение #13


Гуру
******

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



Цитата(Waso @ Aug 10 2010, 15:14) *
Заработало. Правда работает и если оставлять лишь последнюю строку.

Торопился и наврал в предыдущем посте: конечно, надо писать EOICR. IVR трогать не надо.

Цитата(Waso @ Aug 10 2010, 15:14) *
В основной проге убрал модификаторы __irq __arm от объявления процедуры прерывания - и заработало!! ))
Что я делаю не так? (с)

Со стартапом своим разбирайтесь. Наверняка в нем присутствует обертка для прерываний, поэтому и заработало.
Помимо модификаторов, скорее всего, придется ликвидировать записи EOICR.
Go to the top of the page
 
+Quote Post
Waso
сообщение Aug 10 2010, 12:46
Сообщение #14


Местный
***

Группа: Свой
Сообщений: 268
Регистрация: 4-11-05
Пользователь №: 10 470



Да. Точно. За основу то взял пример стандартный... Когда не знаешь, да еще и забудешь.. таких делов можно наворотить. =P
И все-таки после брейкпоинта прерывания иногда умирают. Хотя флаги в AIC_IPR и AIC_IMR стоят. CPSR_I=0. Ну ладно, это не критично - отлажусь на осциллографе и консоли.
Go to the top of the page
 
+Quote Post
aaarrr
сообщение Aug 10 2010, 13:21
Сообщение #15


Гуру
******

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



Цитата(Waso @ Aug 10 2010, 16:46) *
И все-таки после брейкпоинта прерывания иногда умирают.

А protect mode используете?

Цитата(Waso @ Aug 10 2010, 16:46) *
Ну ладно, это не критично - отлажусь на осциллографе и консоли.

Это хороший, правильный способ.
Go to the top of the page
 
+Quote Post

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

 


RSS Текстовая версия Сейчас: 10th June 2024 - 04:22
Рейтинг@Mail.ru


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