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

 
 
> Bugfix для AT91SAM7X's SSC ( с кодеком AD73322L ), Обход граблей, заботливо разложенных Atmel-ом
_dem
сообщение Mar 27 2008, 10:43
Сообщение #1


Местный
***

Группа: Свой
Сообщений: 263
Регистрация: 2-02-07
Из: CN, Ukraine
Пользователь №: 24 970



Делюсь опытом, может кто столкнется или укажет на кривизну рук smile.gif

Проблема - на плате стоит кодек AD73322l, подключен по SSC к SAM7X.
SSC работает в слейв-режиме, клокится от кодека.

Кодек двухканальный, формат данных потока ...[ 16 bit канал 1 ][ 16 bit канал 2 ]...
Проблема в том, что после некоторого времени работы теста (10-30 минут) SSC передатчик теряет один фрейм и каналы на выходе кодека "меняются местами". Через некоторое время ситуается повторяется и все возвращается в норму.
Приемник всегда работает четко.

Работаю через DMA, переключение буферов в прерывании.

Проверка времени реакции на прерывание, чтение свежей errata, различные телодвижения с бубном и выключением SPORT интерфейса кодека результата не дали.

Проблему удалось (тьфу-тьфу-тьфу) решить (тьфу-тьфу-тьфу) только сбросом (SWRST) и переинициализацией SSC модуля при каждом входе в прерывание.

Еще раз тьфу-тьфу-тьфу, ибо ловить такой баг в тестовой стойке с платами - занятие, несомненно, интересное, но крайне выматывающее... sad.gif

Вот код рабочего обработчика :
Код
__arm void PSSC_InterruptHandler(void)
{

    unsigned long STATUS = AT91C_BASE_SSC->SSC_SR;
    /////////    //////////////////

    // first, updating buffer count
    if (sscProcessor->mainBuffer == FIRST_BUFFER)
        {
        sscProcessor->mainBuffer = SECOND_BUFFER;
        sscProcessor->shadowBuffer = FIRST_BUFFER;
        }
    else
        {
        sscProcessor->mainBuffer = FIRST_BUFFER;
        sscProcessor->shadowBuffer = SECOND_BUFFER;
        }
    
    if (STATUS & AT91C_SSC_RXBUFF)
    {
        
        #ifdef SSC_ENABLE_IRQ_RESETS_SSC
        __SSC_PeripheryInit();

        // forcibly enable IRQ
        AT91C_BASE_SSC->SSC_IER = AT91C_SSC_ENDRX | AT91C_SSC_RXBUFF;
        #endif
        
        // we've lost both buffers, need to reprogram all and to restart transfer
        // restarting Xchange

        // disable transmitter and PDC

        #ifdef SSC_ENABLE_IRQ_RESETS_SSC
        AT91C_BASE_SSC->SSC_CR = AT91C_SSC_RXDIS | AT91C_SSC_TXDIS;        
        #endif
        
        AT91C_BASE_SSC->SSC_PTCR = AT91C_PDC_RXTDIS | AT91C_PDC_TXTDIS;
        //
        unsigned short read = AT91C_BASE_SSC->SSC_RHR; // reading that shit for SSC clears itself
      
        read = AT91C_BASE_SSC->SSC_RHR; // reading that shit !
               read = AT91C_BASE_SSC->SSC_RHR; // reading that shit !

        // current TX buffer
        AT91C_BASE_SSC->SSC_TPR      = (unsigned long)(sscProcessor->TXbuffers[ sscProcessor->mainBuffer ]);
        AT91C_BASE_SSC->SSC_TCR      = sscProcessor->buffersLength;        
        
        // current RX buffer
        AT91C_BASE_SSC->SSC_RPR      = (unsigned long)(sscProcessor->RXbuffers[ sscProcessor->mainBuffer ]);
        AT91C_BASE_SSC->SSC_RCR      = sscProcessor->buffersLength;        

            
        // starting RC/TM
            AT91C_BASE_SSC->SSC_PTCR = AT91C_PDC_RXTEN | AT91C_PDC_TXTEN;
        
            #ifdef SSC_ENABLE_IRQ_RESETS_SSC
        AT91C_BASE_SSC->SSC_CR = AT91C_SSC_RXEN | AT91C_SSC_TXEN;    
        #endif
        
        // posting semaphore to signal codec 'bout buffers switched
        OSSemPost( sscProcessor->buffersSwitchSemaphore );
    }


    ///////////////////////////    ///////////////////////////    ///////////////////////////
    AT91C_BASE_AIC->AIC_IVR = 0;                          
    
    AT91C_BASE_AIC->AIC_ICCR    =  (1 << AT91C_ID_SSC);    
    AT91C_BASE_AIC->AIC_EOICR   = 0;                      
    
}


И код инициализации :
Код
void __SSC_PeripheryInit( void )
{
    // SSC Control Register
    AT91C_BASE_SSC->SSC_CR = AT91C_SSC_SWRST;                                       /* (SSC) Software Reset */

    // SSC Receive Clock Mode Register
    AT91C_BASE_SSC->SSC_RCMR = ((0x2 << 0) & AT91C_SSC_CKS) | ((0x4 << 8) & AT91C_SSC_START);
//    AT91C_BASE_SSC->SSC_RCMR = ((0x2 << 0) & AT91C_SSC_CKS) | AT91C_SSC_CKI | ((0x3 << 8) & AT91C_SSC_START);    
    // SSC Receive Frame Mode Register
    AT91C_BASE_SSC->SSC_RFMR = ((15 << 0) & AT91C_SSC_DATLEN) | AT91C_SSC_MSBF;
    // SSC Transmit Clock Mode Register
    AT91C_BASE_SSC->SSC_TCMR = ((0x2 << 0) & AT91C_SSC_CKS) | AT91C_SSC_CKI | ((0x4 << 8) & AT91C_SSC_START);;

    // SSC Transmit Frame Mode Register
    AT91C_BASE_SSC->SSC_TFMR = ((15 << 0) & AT91C_SSC_DATLEN) | AT91C_SSC_MSBF;    
}
Go to the top of the page
 
+Quote Post

Сообщений в этой теме


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

 


RSS Текстовая версия Сейчас: 21st July 2025 - 21:22
Рейтинг@Mail.ru


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