Using 24-bit wide transfers with QSPI.cpp

Discussion to talk about software related topics only.
Post Reply
rsg
Posts: 54
Joined: Thu May 15, 2008 5:36 am

Using 24-bit wide transfers with QSPI.cpp

Post by rsg »

Hi,

I'm trying to use the driver in qspi.cpp to control the QSPI on the PK70. The part I'm communicating with is an Analog Devices AD5362 D/A chip, and requires 24-bit transfers. However, when I try to send data using QSPIStart, I get strange behaviour.

For example, if I want to write a single (24-bit) word to the AD5362, I call the code like this:

QSPIStart(pTxBuf, pRxBuf, 3, pSema);

According to the documentation, the third parameter (3) is the number of bytes to transfer. However, when I look at my logic analyzer, I see the CS go low, a burst of 16 clock cycles along with the first 16 bits of data, then a long pause, then the CS goes high. If I lie and pass 4 instead, it works - I get the burst of 16 bits, then a delay, and then the final burst of 8.

This also works if I write more data. If I want to send two 24-bit words, I must tell it 8 bytes, for three words, 12 bytes. In other words, N*(3 + 1), where N is the number of words, 3 is the number of bytes per word, and the 1 is the fudge.

Here is the part of QSPI_Isr() in qspi.cpp that I think is faulty - the comments are mine:

Code: Select all

   else if((QSPIrec.BitsPerQueue > 16) && (QSPIrec.BitsPerQueue < 25))
   {
      // Not sure what this is all about...
      if(QSPIrec.QSPI_SizeLeft > 32)
      {
         QSPIrec.QSPI_SizeLeft -= 32;
      }
      else
      {
         regWordsToWrite = (QSPIrec.QSPI_SizeLeft / 2);
         if(regWordsToWrite)
         {
            sim_qspi.qwr &= ~(0x0F00);
            sim_qspi.qwr |= ((regWordsToWrite-1) << 8);
         }
         QSPIrec.QSPI_SizeLeft = 0;
      }

      if(Txbuf)
      {
         sim_qspi.qar = 0x0;
         for(i = 0; i < regWordsToWrite; i+=2)
         {
            // Really should have another byte, right?
            sim_qspi.qdr = (*(PDWORD)Txbuf >> 8);
            sim_qspi.qdr = (*(PDWORD)Txbuf & 0xFF);
            Txbuf += 4;
         }
      }
      if(Rxbuf)
      {
         sim_qspi.qar = 0x10;
         for( i=0; i < regLastWordsToWrite; i+=2)
         {
            // Ditto, another byte?
            *(PDWORD)Rxbuf = (sim_qspi.qdr << 8);
            *(PDWORD)Rxbuf |= sim_qspi.qdr;
            Rxbuf += 4;
         }
      }
   }
On entry for sending one 24-bit word (setting the size parameter in QSPIStart to 3), QSPIrec.QSPI_SizeLeft is equal to 3. It seems clear that this results in the two for() loops executing just once, and hence sending/receiveing only two bytes. With the hack of setting the size to 4, it seems 4 bytes are sent (presumably the QSPI peripheral only actually sends the correct 24 bits, of course). However, I don't understand how this works in this case, as the buffers are incremented by 8!

This just looks wrong - or am I missing something?

Thanks,
-Bob
rsg
Posts: 54
Joined: Thu May 15, 2008 5:36 am

Re: Using 24-bit wide transfers with QSPI.cpp

Post by rsg »

Oops! In this code, I now realize that the first sim_qspi.qdr is actually writing two bytes, and the second gets the third byte of interesting data, along with 8 zeros.

Code: Select all

         for(i = 0; i < regWordsToWrite; i+=2)
         {
            // Really should have another byte, right?
            sim_qspi.qdr = (*(PDWORD)Txbuf >> 8);
            sim_qspi.qdr = (*(PDWORD)Txbuf & 0xFF);
            Txbuf += 4;
         }
I still don't understand why it doesn't work, though...

Any thoughts???

Thanks,
-Bob
User avatar
lgitlitz
Posts: 331
Joined: Wed Apr 23, 2008 11:43 am
Location: San Diego, CA
Contact:

Re: Using 24-bit wide transfers with QSPI.cpp

Post by lgitlitz »

To transfer 24-bit packets you must do a 4-byte transfer for each packet. If you look at the qspi.h header comments you will one of the notes states:
(3) Transfers > 8 must be word aligned
This means that all 8-bit packets can be transferred as bytes, 9-16 bit packets are transfered as words and 17-32 bit packets are transferred as DWORDs.

This was done intentionally so that the data can be processed. Say you were able to do 3-byte transfers for your 24-bit packets, then how would you process the data? The processor can only do calculations on byte(8), word(16) or dword(32) sized data. The way the QSPI driver is written allows you to do multiple 3-byte transfers without having to manually DWORD align all your incoming data for processing.

-Larry
rsg
Posts: 54
Joined: Thu May 15, 2008 5:36 am

Re: Using 24-bit wide transfers with QSPI.cpp

Post by rsg »

Hi Larry,

Okay, I'm not sure whether I understand you or not, but I think maybe I do. Perhaps I can rephrase?

For 24-bit transfers, I use 32-bit words, and put my 24-bit in the least significant part, right? So the upper 8 bits are ignored. This makes sense, and is indeed what I am doing.

But even though only 24 bits will be sent over the SPI bus, I still need to tell the driver that there are 4xN bytes of data for N 24-bit transfers? I can live with that, if that is the case, but the QSPIStart function documentation is less than clear on this!

FWIW - the above is how I am coding it now, and this morning, I found a bug on my part in the data I was sending, so I think it is working just fine now. But could you please confirm that I understand you correctly, so that I may sleep at night?!

Thanks,
-Bob
Post Reply