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

 
 
> проблемы с передачей по spi, sam7x+gcc
xelax
сообщение Aug 10 2007, 06:35
Сообщение #1


Местный
***

Группа: Свой
Сообщений: 370
Регистрация: 7-11-06
Пользователь №: 22 035



Начал разбираться с spi на этом контроллере(Evalution Board at91sam7x-ek) и наткнулся на такую проблему.
Есть в нём такой режим, удерживать CS в активном состоянии, после окончания передачи.

Инициализирую SPI слудующим образом
Код

/* Configure PIOs for SPI */
AT91C_BASE_PIOA->PIO_ASR = AT91C_PA12_SPI0_NPCS0 | AT91C_PA16_SPI0_MISO |
                               AT91C_PA17_SPI0_MOSI  | AT91C_PA18_SPI0_SPCK;
AT91C_BASE_PIOA->PIO_BSR = 0;
AT91C_BASE_PIOA->PIO_PDR = AT91C_PA12_SPI0_NPCS0 | AT91C_PA16_SPI0_MISO |
                               AT91C_PA17_SPI0_MOSI  | AT91C_PA18_SPI0_SPCK;                                                      
    
    //enable the clock of SPI
    AT91C_BASE_PMC->PMC_PCER = 1<<AT91C_ID_SPI0;
                
    // инициализация spi
    // сброс и разрешение
    AT91C_BASE_SPI0->SPI_CR = AT91C_SPI_SPIDIS | AT91C_SPI_SWRST;
    // установка моды работы spi master, first peripherial active
    AT91C_BASE_SPI0->SPI_MR    = AT91C_SPI_MSTR | AT91C_SPI_LLB;
    // параметры общения с устройством на CS0  
    // скорость spi 24 МГц, задержка перед выдачей тактовой 300 нс.
    AT91C_BASE_SPI0->SPI_CSR[0] = AT91C_SPI_CPOL | AT91C_SPI_BITS_8 |
                                     (0x02 <<  8) | (0x0F << 16);// | AT91C_SPI_CSAAT;                                   
    // запрещаю все прерывания                                     
    AT91C_BASE_SPI0->SPI_IDR = 0xFFFFFFFF;
AT91C_BASE_SPI0->SPI_CR = AT91C_SPI_SPIEN;


процедура отправки байта, крутится в основном цикле (запускается раз в 1 секунду)
Код
   static unsigned char temp = 0;
       
   temp++;    
   AT91C_BASE_SPI0->SPI_TDR = temp;


так вот в чём проблема, когда добавляю бит AT91C_SPI_CSAAT (чтобы CS оставался активным) у меня передаётся один байт, псоле этого признак того, что передатчик пустой не появляется и запись в регистр SPI_TDR не приносит никакого эффекта.
Как только убираю бит AT91C_SPI_CSAAT всё начинает работать нормально.
Кто-нибудь сталкивался с таким эффектом.?

Что я делаю не так?
Как работать с устройствами, для сеанса обмена с которыми нужно удерживать CS активным (таже атмеловская флэшка на плате)?
И как себя ведёт CS в фиксированной моде, нужен ли ему AT91C_SPI_CSAAT, перестаёт ли он быть активным после передачи?

З.Ы, SPI работает сам на себя по локальной внутренней петле AT91C_SPI_LLB. При работе на внешнее устройство тот же эффект.
Go to the top of the page
 
+Quote Post
 
Start new topic
Ответов
xelax
сообщение Aug 10 2007, 15:11
Сообщение #2


Местный
***

Группа: Свой
Сообщений: 370
Регистрация: 7-11-06
Пользователь №: 22 035



После всех сношений смог добиться странных результатов:

Ведёт себя очень странно. CS на высоких частотах делает неактивным после каждого сеанса связи, уменьшаю тактовую частоту и spi начинает делать cs неактивным через 1 мс. Есть большое подозрение, что просто где-то внутри логика начинает не успевать срабатывать. Так что стрёмно работать в таком режиме. Решил попробовать через DMA контроллер. Заработало так как хотел. Отправляет n байт при одной активности CS. Флэшка на плате ожила и отвечает. 08.gif
Причем DMA контроллеру вообще пофик усьановлен ли бит CSAAT или нет. И с ним и без него работает одинакого.

К стати как Вы умудрились запустить под управлением CS как обыкновенных выходов. Все мои усилия приводили к тому, что выходы начинали работать как надо, но умирал spi напрочь. smile3046.gif Танцы с бубном не помогли и я забил на попытки.

Если не секрет, то поделитесь тайным знанием настройки пинов и spi в таком режиме, так чтобы spi не умирал. smile.gif
Go to the top of the page
 
+Quote Post
_dem
сообщение Aug 14 2007, 09:04
Сообщение #3


Местный
***

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



не секрет. вот прямо из исходника (тут еще может где-то попасться обработка внутреннего протокола, но суть понятна будет)

Код
void SPI_Connect(
        PSPIPort self
         )
{
    // CHECKING AND CONFIGURING
    if (self->BASE_SPI == AT91C_BASE_SPI0)     
        {
        self->SPI_ID = AT91C_ID_SPI0;
        self->BASE_SPI_PDC = AT91C_BASE_PDC_SPI0;
        /// PIO    
        #ifdef SAM7X
        AT91F_PIO_CfgPeriph(
            AT91C_BASE_PIOA, // PIO controller base address
            AT91C_PA17_SPI0_MOSI | AT91C_PA16_SPI0_MISO | AT91C_PA18_SPI0_SPCK ,     // Peripheral A
            0); // Peripheral B
        
        #else
        AT91F_PIO_CfgPeriph(
            AT91C_BASE_PIOA, // PIO controller base address
            AT91C_PA13_MOSI | AT91C_PA14_SPCK |AT91C_PA12_MISO, // Peripheral A
            0); // Peripheral B
        
        #endif
        
        // registering processor
        _spiports [ 0 ] = self;
        }
    
    #ifdef SAM7X
    if (self->BASE_SPI == AT91C_BASE_SPI1)     
        {     
        self->SPI_ID = AT91C_ID_SPI1;     
        self->BASE_SPI_PDC = AT91C_BASE_PDC_SPI1;
        // only SAM7X has 2nd SPI
        AT91F_PIO_CfgPeriph(
            AT91C_BASE_PIOA, // PIO controller base address
            0, // Peripheral A
            AT91C_PA22_SPI1_SPCK | AT91C_PA23_SPI1_MOSI | AT91C_PA24_SPI1_MISO); // Peripheral B
    
        // registering processor
        _spiports [ 1 ] = self;
        }
    #endif
    if (self->SPI_ID == 0) return;
    
    ///////////////////////////////////////////////////////////
    
    // enable clock
    AT91F_PMC_EnablePeriphClock( AT91C_BASE_PMC, ((unsigned int) 1 << self->SPI_ID));
    
    AT91F_SPI_Reset (self->BASE_SPI);
    
    if (self->slavemode)
        {
        AT91F_SPI_CfgMode( self->BASE_SPI,
                              AT91C_SPI_PS_FIXED | AT91C_SPI_MODFDIS |
                              ((unsigned int)(0x00<<16) & AT91C_SPI_PCS));
        }
    else
        {
        AT91F_SPI_CfgMode( self->BASE_SPI,
                              AT91C_SPI_MSTR | AT91C_SPI_PS_FIXED | AT91C_SPI_MODFDIS |
                              ((unsigned int)(0x00<<16) & AT91C_SPI_PCS));
        }
    
    // reset PDC channels
    self->BASE_SPI_PDC->PDC_TPR = 0;
    self->BASE_SPI_PDC->PDC_TCR = 0;    
    self->BASE_SPI_PDC->PDC_RPR = 0;
    self->BASE_SPI_PDC->PDC_RCR = 0;    
    
    self->BASE_SPI_PDC->PDC_PTCR = 0;
    
    // configure
    self->BASE_SPI->SPI_CSR[0]= AT91C_SPI_BITS_8 |
            ((unsigned int) self->clockdivider <<  8)| // (SPI) Serial Clock Baud Rate
            ((unsigned int) 0x00 << 16)| // (SPI) Delay Before SPCK
            ((unsigned int) SPI_DELAY_BETWEEN_TRANSFERS << 24); // (SPI) Delay Between Consecutive Transfers
    
    AT91F_SPI_Enable(self->BASE_SPI);
    
    // Init CS pins
    AT91C_BASE_PIOA->PIO_PER = DEV_CS_ALL_A;
    AT91C_BASE_PIOA->PIO_OER = DEV_CS_ALL_A;

    #ifdef SAM7X
    AT91C_BASE_PIOB->PIO_PER = DEV_CS_ALL_B;
    AT91C_BASE_PIOB->PIO_OER = DEV_CS_ALL_B;
    #endif
    
    // clearing remote side buffers
    #ifdef SPI_CLEAR_REMOTE_BUFFERS
    #ifndef SPI_SLAVE
    
    if (! self->slavemode )
        {
        memset( self->TXdata, SPI_CLEAR_BUFFERS, SPI_BUFFER_LENGTH );
        for (unsigned char zz = 0; zz < SPI_DEVICE_COUNT; zz++ )
            {
            __SPI_Send( self,
                   zz,
                   self->TXdata,
                   SPI_BUFFER_LENGTH,
                   0
                   );
                  
            }
        }
    #endif
    #endif    
          
    __SPI_UnSelectAll();
    
    /// CONNECT SPI  OKAY
    return;
}


и отправка данных

Код
short __SPI_Send(
            PSPIPort self,
                   unsigned char devnum,
            unsigned char * data,
            unsigned short count,
            unsigned short timeout
            )
{
    if (!timeout)
        timeout = _SPI_TIMEOUT;
    if (!(count))
        return SPI_ERROR;
    
    __SPI_Select( devnum );
    
    OSSemSet(self->ENDTXSemaphore, 0, &self->last_error);

    unsigned long sr = self->BASE_SPI->SPI_SR;

    // preparing buffer
    self->BASE_SPI_PDC->PDC_TPR = (unsigned int) (char *)data;
    self->BASE_SPI_PDC->PDC_TCR = count;    

    // enabling SEND PDC
    
    // reset IRQ
    self->BASE_SPI->SPI_IDR = (SPI_PDC_TX_FINISHED_FLAG );
    sr = self->BASE_SPI->SPI_SR = 0;
    self->BASE_SPI->SPI_IER = (SPI_PDC_TX_FINISHED_FLAG );
    
    self->BASE_SPI_PDC->PDC_PTCR = AT91C_PDC_TXTEN;
    
    OSSemPend(self->ENDTXSemaphore, timeout , &self->last_error);
    self->BASE_SPI->SPI_IDR = (SPI_PDC_TX_FINISHED_FLAG );

    // need to read it - SPI SAM7 bug
    (unsigned long)self->BASE_SPI->SPI_RDR;
    // reading status to clear it
    (unsigned long)self->BASE_SPI->SPI_SR;
    (unsigned long)self->BASE_SPI->SPI_RDR;
    
    __SPI_UnSelectAll();    
    
    // disabling SEND PDC
    self->BASE_SPI_PDC->PDC_PTCR = AT91C_PDC_TXTDIS;
    
    short res = count - (self->BASE_SPI_PDC->PDC_TCR);
    
    (void)data;

    return res;
}


и выбор чипа

Код
////////////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////////////
__inline void __SPI_Select( unsigned char devnum )
{
    #ifdef SPI_SLAVE
        (void)devnum;
        return;
    #else
    if (devnum > 8)
        return;
    
    #ifdef SPI_STAY_SELECTED
    if (devnum == spi_last_selected) return;
        devnum = spi_last_selected;
    #endif    
    
    // first disabling all
    AT91C_BASE_PIOA->PIO_SODR = DEV_CS_ALL_A;
    AT91C_BASE_PIOA->PIO_CODR = DEV_CS_A[ devnum ];
    
    #ifdef SAM7X
    AT91C_BASE_PIOB->PIO_SODR = DEV_CS_ALL_B;
    AT91C_BASE_PIOB->PIO_CODR = DEV_CS_B[ devnum ];
    #endif

    #endif // SPI_SLAVE
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////////////
__inline void __SPI_UnSelect( unsigned char devnum )
{
    #ifdef SPI_SLAVE

    (void)devnum;
    return;
    
    #else

    if (devnum > 8)
        {
        return;
        }
    // disabling all
    AT91C_BASE_PIOA->PIO_SODR = DEV_CS_A[ devnum ];

    #ifdef SAM7X
    
    AT91C_BASE_PIOB->PIO_SODR = DEV_CS_B[ devnum ];
    
    #endif    // SAM7X

    #endif //SPI_SLAVE
}
Go to the top of the page
 
+Quote Post

Сообщений в этой теме
- xelax   проблемы с передачей по spi   Aug 10 2007, 06:35
- - _dem   отключите CS от периферийного модуля SPI, переключ...   Aug 10 2007, 08:40
- - prottoss   Привет всем! Осваиваю SPI на AT91SAM7X256 - бо...   Jan 8 2008, 10:57
|- - xelax   Цитата(prottoss @ Jan 8 2008, 13:57) Прив...   Jan 9 2008, 07:28
|- - prottoss   Цитата(xelax @ Jan 9 2008, 14:28) Не поня...   Jan 9 2008, 11:55
- - xelax   Вот как у меня запускается приём или передача Код...   Jan 9 2008, 12:53
|- - prottoss   Цитата(xelax @ Jan 9 2008, 19:53) Вот как...   Jan 9 2008, 13:05
|- - KRS   Цитата(prottoss @ Jan 9 2008, 16:05) Спас...   Jan 9 2008, 13:17
|- - prottoss   Цитата(KRS @ Jan 9 2008, 20:17) Отсальные...   Jan 9 2008, 14:26
- - prottoss   Наконец то разобрался в своей проблеме:-) До этого...   Jan 11 2008, 15:40
- - xelax   Вообще конечно ATMEL неприятно удивил своей реализ...   Jan 14 2008, 06:35
- - vdik   Сейчас вот разбираюсь с SPI, чтоб не плодить темы,...   Feb 13 2008, 07:49
- - prottoss   Цитата(vdik @ Feb 13 2008, 14:49) Как наи...   Feb 13 2008, 07:55


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

 


RSS Текстовая версия Сейчас: 18th July 2025 - 12:20
Рейтинг@Mail.ru


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