ARM+SPI DataFlash - странное поведение

Тема в разделе "WASM.ELECTRONICS", создана пользователем Lecko, 3 окт 2011.

  1. Lecko

    Lecko Андрей

    Публикаций:
    0
    Регистрация:
    20 дек 2010
    Сообщения:
    60
    Имеется тестовый код для ARM7, запрашивающий ID у микросхемы Atmel SPI DataFlash:
    Код (Text):
    1. void SSP1Send( BYTE *buf, DWORD Length )
    2. {
    3.   DWORD i;  
    4.   for ( i = 0; i < Length; i++ )
    5.   {
    6.     /* as long as TNF bit is set (TxFIFO is not full), I can always transmit */
    7.     while ( !(SSP1SR & SSPSR_TNF) );
    8.     SSP1DR = *buf;
    9.     buf++;
    10.     /* Wait until the Busy bit is cleared */
    11.     while ( !(SSP1SR & SSPSR_BSY) );
    12.   }
    13.   return;
    14. }  
    15.  
    16. void SSP1Receive( BYTE *buf, DWORD Length )
    17. {
    18.   DWORD i;
    19.   for ( i = 0; i < Length; i++ )
    20.   {
    21.     /* As long as Receive FIFO is not empty, I can always receive. */
    22.     /* since it's a loopback test, clock is shared for both TX and RX,
    23.     no need to write dummy byte to get clock to get the data */
    24.     /* if it's a peer-to-peer communication, SSPDR needs to be written
    25.     before a read can take place. */
    26.     SSP1DR = 0xFF;
    27.     while ( !(SSP1SR & SSPSR_RNE) );
    28.     *buf = SSP1DR;
    29.     buf++;
    30.   }
    31.   return;  
    32. }
    33.  
    34. ...
    35. for (n = 0; n < 3; n++) {
    36. UART_printf(0,"Try readback ID from DataFlash: ");
    37. data_send[0]=0x9f;
    38.  
    39. SSP1Send(data_send,1);
    40. FIO4CLR = 1<<21;
    41. SSP1Receive(data_recv,7);
    42. FIO4SET = 1<<21;
    43. TFT_printf(0,"Read: 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x \n\r",data_recv[0],data_recv[1],data_recv[2],data_recv[3],data_recv[4],data_recv[5],data_recv[6]);
    44.   }
    В соответствии с даташитом ответ должен быть такой: 0x1f 0x27 0x1 0x0

    На практике имеем следующее:
    Код (Text):
    1. Try readback ID from DataFlash:
    2. Read: 0xff 0x1f 0x27 0x1 0x0 0x0 0x0
    3. Try readback ID from DataFlash:
    4. Read: 0xff 0xff 0x1f 0x27 0x1 0x0 0x0
    5. Try readback ID from DataFlash:
    6. Read: 0xff 0xff 0x1f 0x27 0x1 0x0 0x0
    Логический анализатор показал, что все нормально, на нем этих 0xff нет (точнее есть один, в момент получения команды). Откуда берутся эти "мусорные" байты?
     
  2. l_inc

    l_inc New Member

    Публикаций:
    0
    Регистрация:
    29 сен 2005
    Сообщения:
    2.566
    Lecko
    Не читал даташит, но чисто интуитивно (пальцем в небо) отсутствует ожидание после записи внутри SSP1Receive:
    Код (Text):
    1. ...
    2.     SSP1DR = 0xFF;
    3.     while ( !(SSP1SR & SSPSR_BSY) ); //<-- missing line
    4.     while ( !(SSP1SR & SSPSR_RNE) );
    5.     *buf = SSP1DR;
    6. ...
     
  3. Lecko

    Lecko Андрей

    Публикаций:
    0
    Регистрация:
    20 дек 2010
    Сообщения:
    60
    Спасибо за ответ, уже выяснил:) дело было в том, что надо бы стек FIFO чистить
     
  4. SII

    SII Воин против дзена

    Публикаций:
    0
    Регистрация:
    31 окт 2007
    Сообщения:
    1.483
    Адрес:
    Подмосковье
    Не стек, а очередь. Стек -- это LIFO.
     
  5. Lecko

    Lecko Андрей

    Публикаций:
    0
    Регистрация:
    20 дек 2010
    Сообщения:
    60
    Тьфу) очепятка) очередь, разумеется
     
  6. Lecko

    Lecko Андрей

    Публикаций:
    0
    Регистрация:
    20 дек 2010
    Сообщения:
    60
    В продолжение темы.
    При отладке SPI столкнулся с очень странным глюком. Я пытаюсь послать команду на запись в буфер DataFlash последовательности байт по нулевому адресу. Код выглядит так:

    Код (Text):
    1. BYTE init_buffer[]={0x84,0x00,0x00,0x00};//опкод и адрес
    2. FIO4CLR=1<<21;//инверсный Chip Select
    3. SSP1Send(init_buffer,4);//собственно, послали
    4. ...
    5. FIO4SET=1<<21;инверсный Chip Select
    Вот так выглядит функция SSP1Send:
    Код (Text):
    1. void SSP1Send( BYTE *buf, DWORD Length )
    2. {
    3.   DWORD i;  
    4.   for ( i = 0; i < Length; i++ )
    5.   {
    6.     /* as long as TNF bit is set (TxFIFO is not full), I can always transmit */
    7.     while ( !(SSP1SR & SSPSR_TNF) );
    8.     SSP1DR = *buf;
    9.     buf++;
    10.     /* Wait until the Busy bit is cleared */
    11.     while ( !(SSP1SR & SSPSR_BSY) );
    12.   }
    13.   return;
    14. }
    На логическом анализаторе видно, что после отправки 1 байта (0х84) Chip Select самопроизвольно переходит обратно в единицу, таким образом все последующие байты игнорируются. Если вызвать функцию SSP1Send с такими параметрами 2 раза, то же происходит после отправки 3 байт. Что это такое? может ли микросхема DataFlash сама поднимать Chip Select?
     
  7. Lecko

    Lecko Андрей

    Публикаций:
    0
    Регистрация:
    20 дек 2010
    Сообщения:
    60
    Предыдущая ошибка найдена. неверная функция SSP1Send. Должно быть так:
    Код (Text):
    1. void SSP1Send( BYTE *buf, DWORD Length )
    2. {
    3.   DWORD i;  
    4.   for ( i = 0; i < Length; i++ )
    5.   {
    6.     /* as long as TNF bit is set (TxFIFO is not full), I can always transmit */
    7.     while ( (SSP1SR & (SSPSR_TNF|SSPSRBSY)!=SSPSR_TNF) );
    8.     SSP1DR = *buf;
    9.     buf++;
    10.     /* Wait until the Busy bit is cleared */
    11.     while ( (SSP1SR & SSPSR_BSY) );
    12.   }
    13.   return;
    14. }
    но возник следующий вопрос: почему сразу после команды записи из буфера на SPI DataFlash может не отрабатывать команда чтения? Микропроцессор ARM7 NXP LPC2478, микросхема памяти Atmel 45DB321D