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

 
 
> глобальные грабли с spi1 в lpc214x, не работает на прием
diwil
сообщение Sep 29 2006, 06:56
Сообщение #1


Местный
***

Группа: Свой
Сообщений: 366
Регистрация: 5-09-06
Из: Санкт-Петербург
Пользователь №: 20 107



Уважаемые,

Я тут наткнулся на следующие грабли -
запускаю СПИ1 в режиме мастера - CPOL = 1, CPHA = 1,
разрешаю прерывания - SSPIMSC = 8 (прерывания, когда очередь на передачу на половину пуста).

Стартую СПИ1 так -
1. очищаю приемную очередь:
while( SSPSR & (1<<2)) __dummy = SSPDR;

2. Записываю 1 байт в очередь
SSPDR = *out_buff++;

3. Разрешаю прерывания.

Осциллом смотрю на все ноги. На ногу MISO подаю данные, которые знаю.
Однако ножку SSEL1 дергаю сам. Вижу следующее -
Посылается один байт. Вызывается обработчик прерывания.

В обработчике прерывания я
1. проверяю - есть ли данные в приемной очереди :
while(SSPSR & (1<<2)) *in_buff++ = SSPDR;

2. Набиваю очередь на передачу
while(SSPSR & (1<<1)) SSPDR = *out_buff++;

3. Естественно, контролирую количество байт, но это не затрагивает обращение к переферийным регистрам.


Теперь собственно ГРАБЛИ:
1. В обработчике прерывания бит RNE (receive FIFO not empty) никогда не бывает установлен в единицу. А это значит, что ничего не принято - а это не понятно почему. Тем не менее, при запуске СПИ1 в приемной очереди есть данные всегда.

2. Передающая очередь никогда не бывает размером больше 2х - т.е. цикл
while(SSPSR & (1<<1)) SSPDR = *out_buff++;
выполняется не более 2х раз!!! (размер очереди - 8)


мож кто сталкивался с подобным?

Заранее благодарствую
Go to the top of the page
 
+Quote Post
 
Start new topic
Ответов
zltigo
сообщение Oct 2 2006, 17:33
Сообщение #2


Гуру
******

Группа: Свой
Сообщений: 13 372
Регистрация: 27-11-04
Из: Riga, Latvia
Пользователь №: 1 244



Простейший вариант без прерывания.
На частоте SPI ~7.5MHz и ниже
FIFO не успевает опустошаться и SSEL не дергается, как и требовалось.
Если ~15MHz, то уже не успевает загрузка+разгрузка SSEL дергается - надо
софтово управлять, как и в случае разрешенных прерываний.

Код
//---------------------------------------------------------------------------
//
//---------------------------------------------------------------------------
int init_SPI1( void )
{
    // Prescaler = 2 (Maximum Clock for Master)
    SSPCPSR_bit.CPSDVSR =  2;

    // Configure Pin Connect Block
    PINSEL1_bit.P0_17 = 0x2;       // SCK1
    PINSEL1_bit.P0_18 = 0x2;    // MISO1
    PINSEL1_bit.P0_19 = 0x2;    // MOSI1
    PINSEL1_bit.P0_20 = 0x2;    // SSEL1

    SSPCR0_bit.FRF    =   0;             // SPI Mode
    SSPCR0_bit.DSS    =  (8-1);         // 8bit Transfer
    SSPCR0_bit.CPOL =     1;             // Polarity
    SSPCR0_bit.CPHA =     1;            // Phase
    SSPCR0_bit.SCR     =  (4-1);        // Divider

    // Device selected as master
    SSPCR1_bit.MS      = 0;                // Master
    SSPCR1_bit.SSE  = 1;                // Global Enable

      for( int i = 0; i < 8; i++ )
      {    ulong dummy = SSPDR;         // Clear the RxFIFO
          dummy = dummy;
    }

    return( 0 );    // Ok
}


//---------------------------------------------------------------------------
BYTE ex_tx_buf[37] = {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29
,30,31,32,33,34,35,36};
BYTE ex_rx_buf[37];
#define EX_TX_BYTE {SSPDR = *tx_ptr++; nn--;}
#define EX_RX_BYTE *rx_ptr++ = SSPDR

// Experiment
//---------------------------------------------------------------------------
void SPI1_experiment( int size )
{
int nn=size;    
BYTE *tx_ptr = ex_tx_buf;
BYTE *rx_ptr = ex_rx_buf;
register BYTE stat;

    memset( rx_ptr, 0xFF, size );

//    ENTER_CRITICAL();
//    {
      
    do
    {  // Забиваем FIFO до упора - хорошо для прерывистого процесса
                 if( (stat = SSPSR) & SSPSR_TNF )
            EX_TX_BYTE;
        if( stat & SSPSR_RNE )    
            EX_RX_BYTE;
    }
    while( nn );
// Вычитывание хвостика FIFO
    do
    {   if( (stat = SSPSR) & SSPSR_RNE )    
            EX_RX_BYTE;
    }
    while( stat & SSPSR_BSY );
// И возможного последнего байта    
         if( SSPSR & SSPSR_RNE )    
        EX_RX_BYTE;

//    }
//    LEAVE_CRITICAL();
      
    bprintf_str( "RX:");
    for( nn = 0; nn<size; nn++ )
        bprintf_str( "%02X ", ex_rx_buf[nn] );        
    bprintf( "end" );          
                      
}


--------------------
Feci, quod potui, faciant meliora potentes
Go to the top of the page
 
+Quote Post
diwil
сообщение Oct 3 2006, 07:26
Сообщение #3


Местный
***

Группа: Свой
Сообщений: 366
Регистрация: 5-09-06
Из: Санкт-Петербург
Пользователь №: 20 107



Цитата(zltigo @ Oct 2 2006, 21:33) *
Простейший вариант без прерывания.
На частоте SPI ~7.5MHz и ниже
FIFO не успевает опустошаться и SSEL не дергается, как и требовалось.


Благодарю примного.
это, конечно же работает... с небольщой оговоркой -
1. частота процессора 14.7456МГц (не надо больше и из соображений требований к потреблению тока)
2. За время записи второго байта в фифу (SPI ~ 2МГц) первый успевает из нее вылететь.

Поэтому мне видится наиболее подходящим следующий алгоритм:
(псевдо)

// очистить приемную очередь... потом:

SSPDR = *tx_ptr++;
tx_cnt--;

do {
// можно проверить есть ли место в передающей фифе. если нет - подождать. без этого тоже работает
SSPDR = *tx_ptr++;
*rx_cnt++ = SSPDR; // наверное нужно проверить rxne флаг, но вроде и без этого работает
} while(--tx_cnt) ;

// и в конце дочистить приемную очередь
Go to the top of the page
 
+Quote Post
zltigo
сообщение Oct 3 2006, 07:48
Сообщение #4


Гуру
******

Группа: Свой
Сообщений: 13 372
Регистрация: 27-11-04
Из: Riga, Latvia
Пользователь №: 1 244



Цитата(diwil @ Oct 3 2006, 10:26) *
1. частота процессора 14.7456МГц (не надо больше и из соображений требований к потреблению тока)
2. За время записи второго байта в фифу (SPI ~ 2МГц) первый успевает из нее вылететь.

1.Что-то у Вас не то с оптимизаций/компилятором - на частоте процессора в ~15MHz и ~2MHz (точнее где-то 1,84...) SPI контролер успевает загружать FIFO без пауз. Мой пример компилировался IAR, ARM Mode, максимальная оптимизация по скорости.

Цитата(diwil @ Oct 3 2006, 10:26) *
SSPDR = *tx_ptr++;
tx_cnt--;

do {
// можно проверить есть ли место в передающей фифе. если нет - подождать. без этого тоже работает
SSPDR = *tx_ptr++;
*rx_cnt++ = SSPDR; // наверное нужно проверить rxne флаг, но вроде и без этого работает
} while(--tx_cnt) ;

Это то, что я имел ввиду когда:
Цитата
байты запихиваются в FIFO и со сдвигом на несколько засунутых в FIFO байт считываются.


Но:
2. Если у Вас "успевает вылететь", то этому уже ничем не поможешь в случае если количество за раз передаваемых байт превышает размер FIFO :-(.


--------------------
Feci, quod potui, faciant meliora potentes
Go to the top of the page
 
+Quote Post
diwil
сообщение Oct 3 2006, 08:06
Сообщение #5


Местный
***

Группа: Свой
Сообщений: 366
Регистрация: 5-09-06
Из: Санкт-Петербург
Пользователь №: 20 107



Цитата(zltigo @ Oct 3 2006, 11:48) *
Но:
2. Если у Вас "успевает вылететь", то этому уже ничем не поможешь в случае если количество за раз передаваемых байт превышает размер FIFO :-(.


это тоже мне странно... похоже скорость доступа к переферии оч маленькая.
компилю ГЦЦ - скомпилиный код почти идеальный (я бы так же на ассемблере написал).

Дело, наверное, в том, что скорость переферии у меня 14.7456/4 (это экономит миллиамперы).
Похоже, что
str rX, [rY], где rY ссылается на переферию занимает 2 такта переферии, а не процессора.

буду разбираться.
пасиб
Go to the top of the page
 
+Quote Post

Сообщений в этой теме
- diwil   глобальные грабли с spi1 в lpc214x   Sep 29 2006, 06:56
- - zltigo   Честно прочитал четыре раза. После процесса иницал...   Sep 29 2006, 21:20
|- - diwil   Цитата(zltigo @ Sep 30 2006, 01:20) Честн...   Oct 2 2006, 08:02
|- - zltigo   Цитата(diwil @ Oct 2 2006, 11:02) Грабли ...   Oct 2 2006, 09:08
|- - diwil   Цитата(zltigo @ Oct 2 2006, 13:08) Цитата...   Oct 2 2006, 10:16
- - zltigo   Урвал минутку, посмотрел. Для начала, так: Код w...   Oct 2 2006, 11:36
|- - diwil   хм... байты по СПИ1 передаются правильно... смотр...   Oct 2 2006, 11:46
|- - zltigo   Цитата(diwil @ Oct 2 2006, 14:46) хм... ...   Oct 2 2006, 12:09
|- - diwil   Цитата(zltigo @ Oct 2 2006, 16:09) Давайт...   Oct 2 2006, 13:02
|- - zltigo   Цитата(diwil @ Oct 2 2006, 16:02) 2. PCLK...   Oct 2 2006, 14:58
|- - diwil   Цитата(zltigo @ Oct 2 2006, 18:58) Самый ...   Oct 2 2006, 16:17
- - zltigo   Цитата(diwil @ Oct 3 2006, 11:06) Дело, н...   Oct 3 2006, 08:14
- - diwil   получилось так: Кодvoid spi1_transfer(uint8_t ...   Oct 3 2006, 17:45


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

 


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


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