|
|
  |
SAM7S + USART PDC + INTS, Зависает AIC??? после сброса по WDT |
|
|
|
Jun 28 2010, 06:06
|

кекс
     
Группа: Свой
Сообщений: 3 825
Регистрация: 17-12-05
Из: Киев
Пользователь №: 12 326

|
Столкнулся с интересной ситуацией, сообщили что девайс иногда перестает работать, с виду вроде все ОК, светодиоды мигают, а коммуникаций с Host'ом - нет, интерфейс связи UART. Начал копать, и вот что накопал: Чип на 55Mhz, UART0 - 115200, работа с UART'ом TX через DMA, RX - посимвольно в режиме 485-го. Заметил что иногда после сброса по WDT - USART подвисает. Подвисает так: После старта первая посылка по DMA уходит без проблем (в терминале вижу правильные данные), но прерывание TXRDY не происходит, поэтому больше девайс ничего не шлет... Хотя флаг TXRDY в статус регистре UART'а есть! Прерываний нет от USART'а вообще никаких, ни RX ни TX, ничего..... Другая периферия после сброса по WDT работает нормально, вчастности таймер (EDGE_TRIGGERED) тикает, I2C (LEVEL_SENSITIVE) прерывания живут, на SPI висит SD карточка обмен через DMA с прерываниями (EDGE_TRIGGERED) работает. Подумал UART глючит, пробовал вывести из ступора повторной инициализацией - не помогло. И не удивительно, UART то по всем признакам живой... Повторный сброс по WDT (иногда второй, иногда третий...) приводит USART в чуства... и USART после этого живет долго и счастливо. До конца не разобрался в чем было дело, но похоже что со сбросом AIC'a через WDT что-то не чисто, на что натолкнуло значение AIC_IMR = 0xFFFFEEE3 после сброса. Следующий код, решает мою проблему с UART'ом: Код static __inline void hal_ClearAIC(void) { AT91PS_AIC pAIC = AT91C_BASE_AIC; int i; pAIC->AIC_IDCR = 0xFFFFFFFF; pAIC->AIC_EOICR = 0; // mark last int as handled for (i = 0; i < 32; i++) pAIC->AIC_SVR[ i ] = 0xDEADBEEF; } вызвать первым при входе в main(). Кто-нибудь сталкивался с чем-то подобным?
|
|
|
|
|
Jun 28 2010, 06:59
|

кекс
     
Группа: Свой
Сообщений: 3 825
Регистрация: 17-12-05
Из: Киев
Пользователь №: 12 326

|
Цитата(aaarrr @ Jun 28 2010, 09:53)  По числу приоритетов. Спасибо, поставлю 8 и себе. Цитата А вот скажите, зачем используется куча edge triggered прерываний - какой-нибудь смысл в этом есть? Думаю все из-за этого: Note that it is not recommended to use the USART interrupt line in edge sensitive mode. был напуган, и наставил везде edge-triggered.  Насколько я понимаю вся разница между sensitive и tiggered в скорости детекта, первый быстрее на 1 цикл, а второй должен быть надежней в виду того, что по идее не должен пропускать короткие IRQn. Может неправильно понимаю?
|
|
|
|
|
Jun 28 2010, 09:01
|
Гуру
     
Группа: Свой
Сообщений: 10 713
Регистрация: 11-12-04
Пользователь №: 1 448

|
Цитата(defunct @ Jun 28 2010, 10:59)  Думаю все из-за этого: Note that it is not recommended to use the USART interrupt line in edge sensitive mode. был напуган, и наставил везде edge-triggered. smile.gif Эмм... То есть сделали наоборот?  Цитата(defunct @ Jun 28 2010, 10:59)  Насколько я понимаю вся разница между sensitive и tiggered в скорости детекта, первый быстрее на 1 цикл, а второй должен быть надежней в виду того, что по идее не должен пропускать короткие IRQn. Может неправильно понимаю? Короткие IRQn у внутренних источников и возникать по хорошему не должны. Но на этот случай предусмотрено spurious irq. Зато в случае работы по фронту есть ненулевая вероятность прошляпить прерывание, если вовремя не сделать запись в ICCR Таким образом, работа по фронту с внутренними источниками никаких преимуществ не имеет, зато имеет недостатки: - латентность на один такт больше - возникает необходимость дополнительного сброса - потенциально может принести проблемы при невнимательном обращении Последний пункт больше относится к начинающим, но именно они почему-то упорно пишут всюду EDGE_TRIGGERED
|
|
|
|
|
Jun 28 2010, 17:25
|

кекс
     
Группа: Свой
Сообщений: 3 825
Регистрация: 17-12-05
Из: Киев
Пользователь №: 12 326

|
Цитата(aaarrr @ Jun 28 2010, 12:01)  Эмм... То есть сделали наоборот?  Не думаю. Если SCR TYPE для UART'а поставить в LEVEL_SENSITIVE то прерывания от UART на 55Mhz глючат. Что наводит на мысль, слово SENSITIVE в ДШ написано верно, а вот слово EDGE - нет, подозреваю что там должно было быть "not recommended to use the USART interrupt line in level sensitive mode", а не "edge sensitive". EDGE_TRIGGERED с UART'ом работает стабильно, на любых частотах. Для байтовых прерываний как I2C - короткая latency необходима, а для DMA'шных и прерываний системного таймера (раз в 1ms) - latency не критично, главное чтоб стабильно работали.
|
|
|
|
|
Jun 29 2010, 10:03
|
Гуру
     
Группа: Свой
Сообщений: 10 713
Регистрация: 11-12-04
Пользователь №: 1 448

|
Цитата(defunct @ Jun 28 2010, 21:25)  Если SCR TYPE для UART'а поставить в LEVEL_SENSITIVE то прерывания от UART на 55Mhz глючат. Как именно они глючат, и какой механизм помогает избежать глюков в edge-sensetive mode? Цитата(defunct @ Jun 28 2010, 21:25)  Что наводит на мысль, слово SENSITIVE в ДШ написано верно, а вот слово EDGE - нет, подозреваю что там должно было быть "not recommended to use the USART interrupt line in level sensitive mode", а не "edge sensitive". Точно такие же "ошибки" присутствуют в описаниях PWM и CAN. P.S. В предыдущем посте я как-то упустил из виду, что edge-triggered источники снимаются автоматически при чтении IVR, так что половиной одного недостатка меньше.
|
|
|
|
|
Jun 29 2010, 11:45
|

кекс
     
Группа: Свой
Сообщений: 3 825
Регистрация: 17-12-05
Из: Киев
Пользователь №: 12 326

|
Цитата(aaarrr @ Jun 29 2010, 13:03)  Как именно они глючат, Перестают работать абсолютно все прерывания, в т.ч. и более приоритетные. Цитата и какой механизм помогает избежать глюков в edge-sensetive mode? Да ничего особенного, обычный обработчик... такой как для всего остального. Код void uart0_ISR(void) __irq { UART_ISR( &u0 ); *AT91C_AIC_EOICR = 0; // signal VIC to end of interrupt activity } Для сравнения - I2C'шный, в level sensitive: Код void i2c_ISR (void) __irq { I2C_ISR(); *AT91C_AIC_EOICR = 0; // signal VIC to end of interrupt activity } Сам UART_ISR вот такой: Код static __inline void UART_ISR( PUART_CONTROL pUART ) { AT91PS_USART pCOM = pUART->pCOM; U32 status = pCOM->US_CSR;
if (status & AT91C_US_ENDTX ) { PRING_BUF pRing = pUART->pTxRing; RingDMAEndOfTransfer( pRing ); pCOM->US_IDR = AT91C_US_ENDTX; // disable Tx int pRing->busy = 0; uart_DispatchPort( pUART ); // <-- эта функция просто перезаряжает DMA если есть чем. pUART->NumTxInts++; } if ( status & AT91C_US_RXRDY) { if (pUART->rx_cb) pUART->rx_cb( AT91F_US_GetChar( pCOM) ); else { AT91F_US_GetChar( pCOM); // dummy read } }
if ( status & AT91C_US_OVRE) { AT91F_US_GetChar( pCOM ); // clear RXRDY }
if ( status & AT91C_US_TIMEOUT) { pCOM->US_CR = AT91C_US_STTTO; } // Reset the status bit pCOM->US_CR = AT91C_US_RSTSTA;
}
|
|
|
|
|
Jun 29 2010, 12:24
|

кекс
     
Группа: Свой
Сообщений: 3 825
Регистрация: 17-12-05
Из: Киев
Пользователь №: 12 326

|
Цитата(aaarrr @ Jun 29 2010, 15:09)  Один глюк вижу: запрет прерывания ENDTX никак не мешает выполняться условию (status & AT91C_US_ENDTX), т.к. на status маска IMR не накладывается. Действительно, спасибо что заметили. Только это безобидный глюк, и он никак не мог "завалить" все прерывания. EndOfTransfer делает следующее Код pRing->head += pRing->CurrFrameSize; if (pRing->head >= pRing->size) pRing->head -= pRing->size; pRing->CurrFrameHead = pRing->head; pRing->CurrFrameSize = 0; Если ничего не отправляли то в CurrFrameSize останется 0, а если отправляли тогда ENDTX будет неустановлен, либо разрешен.
|
|
|
|
|
Jun 29 2010, 13:06
|
Гуру
     
Группа: Свой
Сообщений: 10 713
Регистрация: 11-12-04
Пользователь №: 1 448

|
Цитата(defunct @ Jun 29 2010, 16:45)  Не буду ходить вокруг да около, у Вас UART в LEVEL_SENSITIVE включен? Всегда и все в level-sensetive. Цитата(defunct @ Jun 29 2010, 16:45)  Если да какая частота чипа, бод рейт uart'а, приоритет прерывания и используется ли TX DMA? Хочу попробовать, оставить один только UART и посмотреть будет ли все ОК с level sensitive. В разных проектах 48 и 55МГц, PDC практически всегда используется и на прием и на передачу. Приоритет, если используется, то обычно где-то посередине (есть еще прерывания и с большим и с меньшим приоритетом). Каких-либо проблем не наблюдалось никогда.
|
|
|
|
|
Jul 1 2010, 07:16
|

Дух погибшего транзистора
   
Группа: Свой
Сообщений: 877
Регистрация: 6-09-05
Из: Москва
Пользователь №: 8 288

|
Цитата(defunct @ Jun 28 2010, 10:06)  Столкнулся с интересной ситуацией, сообщили что девайс иногда перестает работать, с виду вроде все ОК, светодиоды мигают, а коммуникаций с Host'ом - нет, интерфейс связи UART. Начал копать, и вот что накопал:
До конца не разобрался в чем было дело, но похоже что со сбросом AIC'a через WDT что-то не чисто, на что натолкнуло значение AIC_IMR = 0xFFFFEEE3 после сброса. Следующий код, решает мою проблему с UART'ом:
вызвать первым при входе в main().
Кто-нибудь сталкивался с чем-то подобным? Я сталкивался. только у меня АЦП подвисал на S256, когда я работал без DMA. Делал он это нерегулярно, причем, если подвисал то и повторные перезапуски оживить процессор не могли. Боролся перезапуском AIC в main: Код /* запрещаем все прерывания */ AT91C_BASE_AIC->AIC_IDCR = AT91C_ALL_INT; /* устанавливаем на все ресурсы edge_triggered mode */ AT91C_BASE_AIC->AIC_SMR[AT91C_ID_FIQ] = AT91C_AIC_SRCTYPE_INT_POSITIVE_EDGE | AT91C_AIC_PRIOR_LOWEST; AT91C_BASE_AIC->AIC_SMR[AT91C_ID_SYS] = AT91C_AIC_SRCTYPE_INT_POSITIVE_EDGE | AT91C_AIC_PRIOR_LOWEST; AT91C_BASE_AIC->AIC_SMR[AT91C_ID_PIOA] = AT91C_AIC_SRCTYPE_INT_POSITIVE_EDGE | AT91C_AIC_PRIOR_LOWEST; AT91C_BASE_AIC->AIC_SMR[AT91C_ID_ADC] = AT91C_AIC_SRCTYPE_INT_POSITIVE_EDGE | AT91C_AIC_PRIOR_LOWEST; AT91C_BASE_AIC->AIC_SMR[AT91C_ID_SPI] = AT91C_AIC_SRCTYPE_INT_POSITIVE_EDGE | AT91C_AIC_PRIOR_LOWEST; AT91C_BASE_AIC->AIC_SMR[AT91C_ID_US0] = AT91C_AIC_SRCTYPE_INT_POSITIVE_EDGE | AT91C_AIC_PRIOR_LOWEST; AT91C_BASE_AIC->AIC_SMR[AT91C_ID_US1] = AT91C_AIC_SRCTYPE_INT_POSITIVE_EDGE | AT91C_AIC_PRIOR_LOWEST; AT91C_BASE_AIC->AIC_SMR[AT91C_ID_SSC] = AT91C_AIC_SRCTYPE_INT_POSITIVE_EDGE | AT91C_AIC_PRIOR_LOWEST; AT91C_BASE_AIC->AIC_SMR[AT91C_ID_TWI] = AT91C_AIC_SRCTYPE_INT_POSITIVE_EDGE | AT91C_AIC_PRIOR_LOWEST; AT91C_BASE_AIC->AIC_SMR[AT91C_ID_PWMC] = AT91C_AIC_SRCTYPE_INT_POSITIVE_EDGE | AT91C_AIC_PRIOR_LOWEST; AT91C_BASE_AIC->AIC_SMR[AT91C_ID_UDP] = AT91C_AIC_SRCTYPE_INT_POSITIVE_EDGE | AT91C_AIC_PRIOR_LOWEST; AT91C_BASE_AIC->AIC_SMR[AT91C_ID_TC0] = AT91C_AIC_SRCTYPE_INT_POSITIVE_EDGE | AT91C_AIC_PRIOR_LOWEST; AT91C_BASE_AIC->AIC_SMR[AT91C_ID_TC1] = AT91C_AIC_SRCTYPE_INT_POSITIVE_EDGE | AT91C_AIC_PRIOR_LOWEST; AT91C_BASE_AIC->AIC_SMR[AT91C_ID_TC2] = AT91C_AIC_SRCTYPE_INT_POSITIVE_EDGE | AT91C_AIC_PRIOR_LOWEST; AT91C_BASE_AIC->AIC_SMR[AT91C_ID_IRQ0] = AT91C_AIC_SRCTYPE_INT_POSITIVE_EDGE | AT91C_AIC_PRIOR_LOWEST; AT91C_BASE_AIC->AIC_SMR[AT91C_ID_IRQ1] = AT91C_AIC_SRCTYPE_INT_POSITIVE_EDGE | AT91C_AIC_PRIOR_LOWEST; /* сбрасываем все прерывания */ AT91C_BASE_AIC->AIC_ICCR = AT91C_ALL_INT; AT91C_BASE_AIC->AIC_SPU = (AT91_REG)spurious_vector; Вобщем, пришел к выводу что разработчики сделали какой-то индусский WDT или AIC, который при определенных фазах луны может подвести.
--------------------
Yes, there are two paths you can go by But in the long run Theres still time to change the road youre on.
|
|
|
|
|
  |
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|