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

 
 
> Непонятки с SPI в sam7, PDC...
Terminator
сообщение Oct 22 2007, 02:38
Сообщение #1


Местный
***

Группа: Участник
Сообщений: 209
Регистрация: 7-12-04
Из: Томск
Пользователь №: 1 382



Написал "драйвер" SPI master для FreeRTOS с использованием PDC (at91sam7x256).
Передача работает замечательно, а приём частенько "виснет".
Обработчик прерывания
Код
static void __attribute__((naked)) SPI0_ISR( void )
{
    portENTER_SWITCHING_ISR();
        
        tSPI *spi = &all_spi[spi_num];

    unsigned int stat = spi->spi->SPI_SR;
    unsigned int imr = spi->spi->SPI_IMR;
    stat &= imr;
        
    portBASE_TYPE res = pdFALSE;
    if (stat & (AT91C_SPI_ENDRX | AT91C_SPI_ENDTX))
    {
        // сигналим задаче
        res = xSemaphoreGiveFromISR( spi->sem, res);
    }
    
    // запрещаем прерывания
    //spi->spi->SPI_IDR = SPI_INT;
    spi->spi->SPI_IDR = 0xFFFFFFFF;
    
    /* Clear the interrupt. */
    AT91C_BASE_AIC->AIC_EOICR = 0;
    
        portEXIT_SWITCHING_ISR( res );
}


Функция чтения.
Код
// читает из SPI буфер buf размером count
// @param spi_num - номер SPI
// @param buf - куда писать
// @param count - сколько писать
void SPI_Read(unsigned char spi_num, void *buf, unsigned int count)
{
    tSPI *spi = &all_spi[spi_num];

    // чтобы сбросить флаг приёма байта, возможно оставленный прошлой
    // передачей
    spi_num = spi->spi->SPI_RDR;
    
    // готовим PDC
    AT91PS_PDC pPDC = ((AT91PS_PDC) &(spi->spi->SPI_RPR));
    AT91F_PDC_SetRx(pPDC, (char *) buf, count);
    AT91F_PDC_SetTx(pPDC, (char *) buf, count);
    
    // включаем PDC
    AT91F_PDC_EnableTx(pPDC);
    AT91F_PDC_EnableRx(pPDC);

    // разрешаем прерывание
    spi->spi->SPI_IER = AT91C_SPI_ENDRX;
    
    // ждём семафор
    xSemaphoreTake(spi->sem, MAX_BlockTime);
    
    // выключаем PDC
    AT91F_PDC_DisableTx(pPDC);
    AT91F_PDC_DisableRx(pPDC);
}


Вставлял отладочные printf в разных местах, выяснилось, что иногда прерывание не срабатывает. Почему так происходит для меня остаётся загадкой sad.gif

Этот код в основном используется для чтения из флешки, нормально работает пока не попытаюсь прочитать сразу много, под 500кб.
В случайном месте падает. Чтение производится порциями по 530 байт.

Реализация без PDC нормально работает.

Может есть какие-то тонкие моменты при использовании PDC, которые я упустил? help.gif
Go to the top of the page
 
+Quote Post
 
Start new topic
Ответов
_dem
сообщение Oct 22 2007, 10:23
Сообщение #2


Местный
***

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



Попробуйте перед запуском PDC прочитать регистр статуса у SPI
Go to the top of the page
 
+Quote Post
Terminator
сообщение Oct 23 2007, 04:17
Сообщение #3


Местный
***

Группа: Участник
Сообщений: 209
Регистрация: 7-12-04
Из: Томск
Пользователь №: 1 382



Цитата(_dem @ Oct 22 2007, 17:23) *
Попробуйте перед запуском PDC прочитать регистр статуса у SPI

Перед запуском всё нормально. А вот после запуска, в момент "смерти", стоит флаг OVRES ...
Смотрел сразу после AT91F_PDC_Enable. Откуда взялся?

Методом научного тыка определил, что достаточно было поменять местами строки
Код
AT91F_PDC_EnableTx(pPDC);
AT91F_PDC_EnableRx(pPDC);

На
Код
AT91F_PDC_EnableRx(pPDC);
AT91F_PDC_EnableTx(pPDC);


Спасибо за наводку.

Сообщение отредактировал Terminator - Oct 23 2007, 04:20
Go to the top of the page
 
+Quote Post
ljerry
сообщение Oct 23 2007, 08:23
Сообщение #4


Участник
*

Группа: Участник
Сообщений: 26
Регистрация: 7-02-06
Из: Зеленоград
Пользователь №: 14 071



Цитата(Terminator @ Oct 23 2007, 08:17) *
Перед запуском всё нормально. А вот после запуска, в момент "смерти", стоит флаг OVRES ...
Смотрел сразу после AT91F_PDC_Enable. Откуда взялся?

Методом научного тыка определил, что достаточно было поменять местами строки
Код
AT91F_PDC_EnableTx(pPDC);
AT91F_PDC_EnableRx(pPDC);

На
Код
AT91F_PDC_EnableRx(pPDC);
AT91F_PDC_EnableTx(pPDC);


Если, например, между вызовами EnableTx и последующим EnableRx вклинивается прерывание, то может получиться так, что передача (и соответственно прием) уже вовсю идет, буфер приемника переполнен, а приемный PDC еще не запущен. EnableTx обязательно должен выставляться последним.
Go to the top of the page
 
+Quote Post



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

 


RSS Текстовая версия Сейчас: 23rd June 2025 - 09:41
Рейтинг@Mail.ru


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