|
глобальные грабли с spi1 в lpc214x, не работает на прием |
|
|
|
Sep 29 2006, 06:56
|
Местный
  
Группа: Свой
Сообщений: 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)
мож кто сталкивался с подобным?
Заранее благодарствую
|
|
|
|
|
 |
Ответов
|
Oct 2 2006, 17:33
|

Гуру
     
Группа: Свой
Сообщений: 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
|
|
|
|
|
Oct 3 2006, 07:26
|
Местный
  
Группа: Свой
Сообщений: 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) ; // и в конце дочистить приемную очередь
|
|
|
|
|
Oct 3 2006, 07:48
|

Гуру
     
Группа: Свой
Сообщений: 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
|
|
|
|
|
Oct 3 2006, 08:06
|
Местный
  
Группа: Свой
Сообщений: 366
Регистрация: 5-09-06
Из: Санкт-Петербург
Пользователь №: 20 107

|
Цитата(zltigo @ Oct 3 2006, 11:48)  Но: 2. Если у Вас "успевает вылететь", то этому уже ничем не поможешь в случае если количество за раз передаваемых байт превышает размер FIFO :-(. это тоже мне странно... похоже скорость доступа к переферии оч маленькая. компилю ГЦЦ - скомпилиный код почти идеальный (я бы так же на ассемблере написал). Дело, наверное, в том, что скорость переферии у меня 14.7456/4 (это экономит миллиамперы). Похоже, что str rX, [rY], где rY ссылается на переферию занимает 2 такта переферии, а не процессора. буду разбираться. пасиб
|
|
|
|
Сообщений в этой теме
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
2 чел. читают эту тему (гостей: 2, скрытых пользователей: 0)
Пользователей: 0
|
|
|