Микроконтроллер выступает SSI слейвом. Мастер - GSM-модем Cinterion MC55i.
ОС - uCOS-II. Частота MCLK 48МГц. IDE - IAR 4.41A
От модема к контроллеру идут выходы - TSFDAI, TXDDAI, SCLK. вход - RXDDAI.
Передача осуществляется в режиме Long Frame Sync по 16 байт за фрейм. Период следования фреймов - 125мкс.
PDC я настроил таким образом, чтобы за один раз передавалось 160 байт звука в PCM16 т.е. 10 раз по 16 фреймов от модема к контроллеру. Во время получения 160 байт PCM16 контроллер должен выполнять отправку своих 160 байт звука на модем.
Получение данных от модема к микроконтроллеру происходит правильно, а вот прерывания окончания отправки вызывается постоянно.
Прерывания получения и отправки блока данных PDC по умолчанию всегда запрещены.
Когда нужно прочитать звук из модема - вызываю функцию, которая разрешает прерывание конца чтения (ENDRX) или записи (ENDTX). В хэндлере прерывания, прерывание, которое вызвалось запрещается. т.е. если функцией разрешили прием 160 байт звука, то когда выполнится прерывание ENDRX, в регистре
Код
AT91C_BASE_SSC->SSC_IDR = AT91C_SSC_ENDRX;
прерывание приема блока 160 байт запретится.
Почему может вызываться постоянно прерывание конца отправки данных, даже когда сигнал TXDDAI не приходил от модема?
CODE
// Configure PIO controllers to drive SSC0 signals
AT91C_BASE_PIOA->PIO_ASR = AT91C_PA21_TF | AT91C_PA22_TK | AT91C_PA23_TD
| AT91C_PA24_RD | AT91C_PA25_RK | AT91C_PA26_RF;
AT91C_BASE_PIOA->PIO_PDR = AT91C_PA21_TF | AT91C_PA22_TK | AT91C_PA23_TD
| AT91C_PA24_RD | AT91C_PA25_RK | AT91C_PA26_RF;
AT91C_BASE_PIOA->PIO_PPUDR = AT91C_PA23_TD;
// Enable Peripheral clock in PMC for SSC0
AT91C_BASE_PMC->PMC_PCER = ((unsigned int) 1 << AT91C_ID_SSC);
// Reset SSC0
AT91C_BASE_SSC->SSC_CR = AT91C_SSC_SWRST; // Reset peripheral
// Interrupt Handler Initialization in AIC first (as told in datasheet)
AT91C_BASE_SSC->SSC_CR = (unsigned int) -1; // Disable peripheral interrupts
// Disable the interrupt on the interrupt controller
AT91C_BASE_AIC->AIC_IDCR = ((unsigned int) 1 << AT91C_ID_SSC);
// Save the interrupt handler routine pointer and the interrupt priority
AT91C_BASE_AIC->AIC_SVR[AT91C_ID_SSC] = ((unsigned int) periphery_ssc_interrupt_handler);
// Store the Source Mode Register
AT91C_BASE_AIC->AIC_SMR[AT91C_ID_SSC] = AT91C_AIC_SRCTYPE_INT_HIGH_LEVEL
| AT91C_AIC_PRIOR_HIGHEST;
// Clear the interrupt on the interrupt controller
AT91C_BASE_AIC->AIC_ICCR = ((unsigned int) 1 << AT91C_ID_SSC);
AT91C_BASE_AIC->AIC_IECR = ((unsigned int) 1 << AT91C_ID_SSC);
// Configure SSC Control Register
AT91C_BASE_SSC->SSC_CR = AT91C_SSC_RXEN | AT91C_SSC_TXEN; // SSC receive and transmit enable 3
// Configure Clock Mode Register
AT91C_BASE_SSC->SSC_CMR = 0;
// Configure Receive Clock Mode Register
AT91C_BASE_SSC->SSC_RCMR = AT91C_SSC_CKS_RK // use RK pin for clock input
| AT91C_SSC_CKO_NONE // SCLK is used for input only
| AT91C_SSC_CKG_NONE //AT91C_SSC_CKG_HIGH
// receive clock enabled only if TSFDAI is high
| AT91C_SSC_START_RISE_RF // rising edge of TSFDAI activates frame receiving
;
// Configure Receive Frame Mode Register
AT91C_BASE_SSC->SSC_RFMR = (15 & AT91C_SSC_DATLEN) // data length will be (15 + 1 = 16) bits per frame
| AT91C_SSC_MSBF // most significant bit transmitted and received first
| 15 << 16 // fslen is 15 for (15 + 1 = 16) clks per frame signal
;
AT91C_BASE_SSC->SSC_RNPR = 0;
AT91C_BASE_SSC->SSC_RNCR = 0;
AT91C_BASE_SSC->SSC_TNPR = 0;
AT91C_BASE_SSC->SSC_TNCR = 0;
AT91C_BASE_SSC->SSC_RPR = 0;
AT91C_BASE_SSC->SSC_RCR = 0;
AT91C_BASE_SSC->SSC_TPR = 0;
AT91C_BASE_SSC->SSC_TCR = 0;
AT91C_BASE_SSC->SSC_PTCR = AT91C_PDC_RXTEN | AT91C_PDC_TXTEN;
AT91C_BASE_SSC->SSC_IDR = (Xuint32)-1; /** Disable all SSC interrupts */
Сообщение отредактировал aaarrr - Apr 19 2010, 16:39
Причина редактирования: Уменьшение видимого размера цитаты исходника