D!m@ 0 28 июня, 2010 Опубликовано 28 июня, 2010 · Жалоба Здравствуйте! Пишу под 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; } Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
D!m@ 0 29 июня, 2010 Опубликовано 29 июня, 2010 · Жалоба Заметил что когда перестает заходить в прерывание ТС1 то сбрасывается флаг AIC_IPR но AIC_IMR остается установленным соответствующего таймера. Почему не знаю. Да и не всегда точка останова спасает. Почему прерывание T1 перестает обрабатываться и почему? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
aaarrr 69 29 июня, 2010 Опубликовано 29 июня, 2010 · Жалоба Почему прерывание T1 перестает обрабатываться и почему? JTAG отключить не пробовали? Ну и до кучи поставьте AT91C_AIC_SRCTYPE_INT_HIGH_LEVEL вместо AT91C_AIC_SRCTYPE_POSITIVE_EDGE. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
D!m@ 0 29 июня, 2010 Опубликовано 29 июня, 2010 · Жалоба Ну и до кучи поставьте AT91C_AIC_SRCTYPE_INT_HIGH_LEVEL вместо AT91C_AIC_SRCTYPE_POSITIVE_EDGE. Вроде помогло. Но обясните почему не работало с AT91C_AIC_SRCTYPE_POSITIVE_EDGE ? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
aaarrr 69 29 июня, 2010 Опубликовано 29 июня, 2010 · Жалоба Но обясните почему не работало с AT91C_AIC_SRCTYPE_POSITIVE_EDGE ? Чисто теоретически это возможно, если при обработке прерывания от TC по какой-либо причине не считывается TC_SR - линия прерывания останется в активном состоянии, логика AIC будет сброшена, прерывания работать перестанут. К такому же эффекту может привести и запись ICCR. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
EugenB2 0 17 июля, 2010 Опубликовано 17 июля, 2010 · Жалоба Вроде помогло. Но обясните почему не работало с 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: : 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 ); Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
aaarrr 69 17 июля, 2010 Опубликовано 17 июля, 2010 · Жалоба А у меня была обратная проблема с USART - возникало Spurious Interrupt из-за AT91C_AIC_SRCTYPE_INT_LEVEL_SENSITIVE пришлось сменить на AT91C_AIC_SRCTYPE_POSITIVE_EDGE. Spurious Interrupt возникает по вполне определенным причинам и не является проблемой, если, конечно, не снабжено зависающей заглушкой (в атмеловских примерах встречался такой маразм). Да... и, если в IAR пишется, то почему бы не пользоваться стандарными библиотечными функциями :rolleyes: : К 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; } Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
EugenB2 0 20 июля, 2010 Опубликовано 20 июля, 2010 (изменено) · Жалоба 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. Изменено 20 июля, 2010 пользователем EugenB2 Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
aaarrr 69 20 июля, 2010 Опубликовано 20 июля, 2010 · Жалоба ЧЕМ вот это нагромождение: Зато в этом нагромождении видно что и как делается. Тем более, к примеру, короткие функции все 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 можно далеко не всегда. А по названию функции нельзя догадаться об особенностях ее работы. Когда вы пользуетесь вызовами функций драйверов сети, i2c например, вы же не обращаетесь в регистры каждый раз напрямую игнорируя библиотечные вызовы. Есть библиотека(не важно эта или другая) и если что-то исправить надо в вызываемых функциях, то можно подправить исходник. Чем сложнее процессор или контроллер, тем больше кода инита периферии и т.д., если сравнить с AVR, где раз два и сделал все что надо ). Если вы заметили, в этой "библиотеке" совершенно проигнорирована хоть сколько-нибудь сложная периферия (EMAC, UDP, CAN). А использовать библиотечные функции для установки бита в регистре - это, по-моему, совершенный маразм, только усложняющий чтение программы. P.S. Я совсем не против написания библиотек для периферии, просто at91lib - это отличный пример того, как этого делать не надо. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Waso 1 10 августа, 2010 Опубликовано 10 августа, 2010 · Жалоба JTAG отключить не пробовали? Здравствуйте! Какраз столкнулся с такой проблемой - когда прошиваю программу через J-Link, и запускаю в С-SPY, то почему-то отказываются работать прерывания. Зато если тут-же нажать Reset на плате - все начинает работать как надо. IAR 4.40, отладочная плата AT91SAM7X-ЕК. С чем это может быть связано? Программу гружу во флеш. В mac файле никакой работы с прерываниями не обнаружил... Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
aaarrr 69 10 августа, 2010 Опубликовано 10 августа, 2010 · Жалоба Сброс логики AIC'а (8 последовательных чтений AIC_IVR, если не в protect mode записей EOICR) при инициализации делаете? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Waso 1 10 августа, 2010 Опубликовано 10 августа, 2010 · Жалоба Нет. Не делаю. Первый раз такой способ вижу. Но мне идея понравилась. Написал такое: 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 от объявления процедуры прерывания - и заработало!! )) Что я делаю не так? (с) Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
aaarrr 69 10 августа, 2010 Опубликовано 10 августа, 2010 · Жалоба Заработало. Правда работает и если оставлять лишь последнюю строку. Торопился и наврал в предыдущем посте: конечно, надо писать EOICR. IVR трогать не надо. В основной проге убрал модификаторы __irq __arm от объявления процедуры прерывания - и заработало!! )) Что я делаю не так? (с) Со стартапом своим разбирайтесь. Наверняка в нем присутствует обертка для прерываний, поэтому и заработало. Помимо модификаторов, скорее всего, придется ликвидировать записи EOICR. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Waso 1 10 августа, 2010 Опубликовано 10 августа, 2010 · Жалоба Да. Точно. За основу то взял пример стандартный... Когда не знаешь, да еще и забудешь.. таких делов можно наворотить. =P И все-таки после брейкпоинта прерывания иногда умирают. Хотя флаги в AIC_IPR и AIC_IMR стоят. CPSR_I=0. Ну ладно, это не критично - отлажусь на осциллографе и консоли. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
aaarrr 69 10 августа, 2010 Опубликовано 10 августа, 2010 · Жалоба И все-таки после брейкпоинта прерывания иногда умирают. А protect mode используете? Ну ладно, это не критично - отлажусь на осциллографе и консоли. Это хороший, правильный способ. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться