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

 
 
2 страниц V   1 2 >  
Reply to this topicStart new topic
> глобальные грабли с 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
zltigo
сообщение Sep 29 2006, 21:20
Сообщение #2


Гуру
******

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



Честно прочитал четыре раза. После процесса иницализации и 'стартую 1 2 3' не смог ничего понять из дальнейших действий :-(
С 213x/4x работаю из "проблем" с FIFO только одна - нет возможности сбросить его содержимое без тупого вычитывания.
Все испробованые режимы соответствуют документации. Возможные грабли весьма интересуют посему просьба описать более ясно ситуацию - попробую повторить.


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


Местный
***

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



Цитата(zltigo @ Sep 30 2006, 01:20) *
Честно прочитал четыре раза. После процесса иницализации и 'стартую 1 2 3' не смог ничего понять из дальнейших действий :-(
С 213x/4x работаю из "проблем" с FIFO только одна - нет возможности сбросить его содержимое без тупого вычитывания.
Все испробованые режимы соответствуют документации. Возможные грабли весьма интересуют посему просьба описать более ясно ситуацию - попробую повторить.


Грабли такие -
1. Размер очереди на передачу - по документации она == 8, у меня ее размер, вычисленный путем проверки флага в SSPSR получается не более 2х.
2. Флаг наличия данных в приемной очереди никогда не бывает равен 1. Т.е. такое впечатление, что очередь всегда пуста.
Go to the top of the page
 
+Quote Post
zltigo
сообщение Oct 2 2006, 09:08
Сообщение #4


Гуру
******

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



Цитата(diwil @ Oct 2 2006, 11:02) *
Грабли такие -

Не совсем понятны условия в которых сие проявляется. В меру своего понимания описанного явления попробую что-то подобное сочинить (просто самому интересно) и проверить.


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


Местный
***

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



Цитата(zltigo @ Oct 2 2006, 13:08) *
Цитата(diwil @ Oct 2 2006, 11:02) *

Грабли такие -

Не совсем понятны условия в которых сие проявляется. В меру своего понимания описанного явления попробую что-то подобное сочинить (просто самому интересно) и проверить.


Код такой -
Код
extern char *in, *out;

void __irq spp_isr(void)
{
   while(SSPSR & (1<<2) )
     *in++ = SSPDR;

   while(SSPSR & (1<<1))
     SSPDR = *out++;
}

void ssp_start(char *inb, char *outb)
{
   int dummy;
   in = inb;
   out = outb+1;

     while(SSPSR & (1<<2) )
       dummy = SSPDR;

   SSPIMSC = 12;
   SSPDR = *outb;
  
}


В обработчике прерываний первый цикл никогда не выполняется, второй - запихивает по два байта в SSPDR.
Go to the top of the page
 
+Quote Post
zltigo
сообщение Oct 2 2006, 11:36
Сообщение #6


Гуру
******

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



Урвал минутку, посмотрел.
Для начала, так:
Код
  
while(SSPSR & (1<<1))
     SSPDR = *out++;

Делать нельзя, дело в том, что обращение к периферии очень медленное (не менее 8 тактов на обращение) и на приличных скоростях SPI SSPDR удается в общем случае загружать медленне, чем он разгружается :-(
Даже простейший вариант
SSPDR = i++;
Успевает (проверено электроникой) даже на 15Mhz "залить" в 8ми элементное FIFO 32!!! байта до его "переполнения" Глубина FIFO действительно 8 элементов и при приеме из 32 переданных вычитываются первые 8.
Эксперимент проводился на 2148 без индекса 01 - возможно с 01 картина будет несколько иная.
Так что заливать придется, например, с огдядкой :-( на переполнение приемного FIFO.


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


Местный
***

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



хм...

байты по СПИ1 передаются правильно... смотрел осциллом и на другой конец приходят прально.

если читать приемный регистр "руками", то они в нем тоже правильные оказываются...
не понятки - почему не выставляется флаг что приемная очередь не пуста?

тогда ладно... допустим он по прерываниям не будет работать...
а если сделать как в филипсовском примере? (платы нет под рукой)
Go to the top of the page
 
+Quote Post
zltigo
сообщение Oct 2 2006, 12:09
Сообщение #8


Гуру
******

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



Цитата(diwil @ Oct 2 2006, 14:46) *
хм...

байты по СПИ1 передаются правильно... смотрел осциллом и на другой конец приходят прально.

У меня для начала однозначно захлебывается уже передача.

Цитата
тогда ладно... допустим он по прерываниям не будет работать...

Почему не будет! будет!
А что Вы хотели сказать (ну хотя-бы HEX, если биты влом описать) этим
SSPIMSC = 12;
Выбирая прерывания при полупустых обеих FIFO
зачем оба-то, тем более для мастера?

Цитата
а если сделать как в филипсовском примере?

Не читал "примеры" - давно "завязал" :-( c чтением.


Я честно говоря просто не могу понять конечную цель, чего надо достигнуть???

Давайте так:
1. Master - это понятно.
2. На какой скорости?
3. Обмен пакетный? Одиночными фреймами?
4. Нарезка SSELом на фреймы нужна?


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


Местный
***

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



Цитата(zltigo @ Oct 2 2006, 16:09) *
Давайте так:
1. Master - это понятно.
2. На какой скорости?
3. Обмен пакетный? Одиночными фреймами?
4. Нарезка SSELом на фреймы нужна?


1. Мастер и только мастер
2. PCLK/2 : pclk = 14.7456/2 MHz итого сторость СПИ1 около 1МГц
3. нет. хочу передавать и принимать (одновременно) данные от 37 до 535 байт. при этом, на время всей передачи SSEL должен быть низким.
4. нет
Go to the top of the page
 
+Quote Post
zltigo
сообщение Oct 2 2006, 14:58
Сообщение #10


Гуру
******

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



Цитата(diwil @ Oct 2 2006, 16:02) *
2. PCLK/2 : pclk = 14.7456/2 MHz итого сторость СПИ1 около 1МГц

"Скорость" SPI таки в битах, посему ~7,5MHz, что является достаточно быстрым и попадает в неприятную зону, когда уже не успеть (практически это в Вашем случае 128 тактов процессора с момента полупустого FIFO)забивать и вычитывать FIFO со скоростью обеспечивающей отсутствие аппаратного дергания SSEL. SSEL - софтом дергать надо будет.
Кроме того это где-то надо думать использовать/не использовать прерывание - ибо прерывание опять будет приходить через 128 тактов - и накладные расходы на обслуживание будут немалые.
Ответ на вопрос по использованию прерывания зависит от прочих системных решений.
Цитата
3. нет. хочу передавать и принимать (одновременно) данные от 37 до 535 байт. при этом, на время всей передачи SSEL должен быть низким.

Т.е. в какой-то момент времени в буфере передачи появляетя порция от 37 до 535 байт и это является сигналом к началу процесса.
Принятые байты складываются в приемный буфер и все разборки "потом".

Самый тупой вариант SSEL софтом управляемый, байты запихиваются в FIFO и со сдвигом на несколько засунутых в FIFO байт считываются. Прерывания от SPI не используются. Времени занимает много, но при разрешенных прерываниях и/или наличии операционки все будет работать с минимальными суммарными накладными расходами.

Набросать такой вариант? Или с прерываниями, если нужно обеспечить более высокую равномерность работы с SPI?


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


Местный
***

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



Цитата(zltigo @ Oct 2 2006, 18:58) *
Самый тупой вариант SSEL софтом управляемый, байты запихиваются в FIFO и со сдвигом на несколько засунутых в FIFO байт считываются. Прерывания от SPI не используются. Времени занимает много, но при разрешенных прерываниях и/или наличии операционки все будет работать с минимальными суммарными накладными расходами.


Пасибо большое.
добрался до платы. Разобрался.
Было:
1. скорость СПИ1 (в битах) около 2МГц
2. За время цикла записи числа в ФИФУ она успевает вычищаться и весь блок передается в одном цикле обработчика прерывания.
3. аппаратный SSEL1 успевает дернуться после записи каждого байта в фифу.
4. И да, когда заканчиваются данные на запись, то начинается чтение из приемной фифы. В результате я там имею первые 8 байт.

Похоже, что прерывание отменяются, ибо макс. внутренний буфер (>4K) , будет накапливаться за 16 мс, что допустимо.

еще раз спасибо
Дима
Go to the top of the page
 
+Quote Post
zltigo
сообщение Oct 2 2006, 17:33
Сообщение #12


Гуру
******

Группа: Свой
Сообщений: 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
Сообщение #13


Местный
***

Группа: Свой
Сообщений: 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
Сообщение #14


Гуру
******

Группа: Свой
Сообщений: 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
Сообщение #15


Местный
***

Группа: Свой
Сообщений: 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

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

 


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


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