SAMD51: Can't trigger a QSPI read

Go To Last Post
6 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

My QSPI interface seems to be configured and mostly working good in serial data mode.  I can send instructions:

 

    //Working command:
       QSPI ->INSTRCTRL.reg = 0x55;      
       QSPI ->INSTRFRAME.reg = 0x16;

 

I see all the proper signals toggle on my QSPI interface pins

 

And, I can see that when I write to the QSPI address space, I see activity on the QSPI pins:

 

#define POKE(addr, b)   (*(unsigned char *)(addr) = (b))

            QSPI ->INSTRCTRL.reg = 0x02;                //From example in datasheet
            QSPI ->INSTRFRAME.reg = 0x30b3;          //From example in datasheet
            junk = QSPI ->INSTRFRAME.reg;
            POKE(0x4000000, 0x55);
            POKE(0x4000001, 0x55);
            POKE(0x4000002, 0x55);
            delay_ms(100);

 

But I can never see any QSPI pin activity with any read attempts.  I am tried all the datasheet examples, this one is "Exmample 8:Instruction in Quad SPI, with address in Quad SPI, without option, with data read from
Quad SPI, with two dummy cycles, with fetch."

 

#define PEEK(addr)      (*(unsigned char *)(addr))

        QSPI ->INSTRCTRL.reg = 0xb;                  //From example in datasheet
        QSPI ->INSTRFRAME.reg = 0x220b6;        //From example in datasheet
        junk = QSPI ->INSTRFRAME.reg;
        junk = PEEK(0x4000000);

  
        delay_ms(100);

 

I think I am reading to the proper registers since the write to these registers do trigger a write over the QSPI.  Am I not reading registers out of the 0x4000000 -> 0x50000000 space properly?  I have tried a few different methods.

 

Anything I could be missing here to trigger the QSPI read?  I was reading that having caching on might affect this.  I think my START project has it turned off:

 

From hpl_ccmc_config.h:

 

// <q> Cache enable
//<i> Defines the cache should be enabled or not.
// <id> cmcc_enable
#ifndef CONF_CMCC_ENABLE
#define CONF_CMCC_ENABLE 0x0
#endif

 

Does anyone have any working QSPI code they could share?  FYI, I am testing this on an Adafruit Metro M4 board, but using Studio 7, not Arduino.

 

Thanks,

-troy

 

This topic has a solution.
Last Edited: Sun. Dec 1, 2019 - 09:20 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Adafruit has qspi code in their “spiflash” library...
(Hmm. I don’t know if it maps the qspi device into the memory space...)

 

Edit: I checked.  The adafruit spiflash QSPI command does NOT map the device...  :-(

https://github.com/adafruit/Adafruit_SPIFlash/blob/master/src/qspi/Adafruit_FlashTransport_QSPI_SAMD.cpp#L121

 

Last Edited: Sun. Jul 28, 2019 - 10:15 PM
This reply has been marked as the solution. 
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Thanks for the info.  I spent days hacking away at this and I finally got something working.

 

This is on the Metro M4 board, which has the Gigadevice GD25Q16C QSPI flash on it.

 

First, use the Atmel START page to get the basic QSPI config done.

 

Then, before a read loop, init the QSPI interface.  Some of this is already done by default, but I have them here for clarity:

 

uint32_t flash_read[20];

QSPI-> CTRLB.bit.MODE =1;
QSPI -> CTRLB.bit.DATALEN =0;
QSPI -> CTRLB.bit.CSMODE = 0;
QSPI -> CTRLB.bit.LOOPEN =0;
//Configure QSPI attempt
//Enable
QSPI-> CTRLA.bit.ENABLE =1;  //Needs to be enabled before each read? I guess so.
//CLK polarity
QSPI ->BAUD.bit.CPHA  = 0;
QSPI ->BAUD.bit.CPOL  = 0;

QSPI ->INSTRCTRL.reg = 0xeb; // "Quad I/O Fast Read" command in QSPI

QSPI ->INSTRFRAME.reg = 0x610b4; //The magic QSPI instruction frame code.  This works with the 0xeb command code above.

junk = QSPI ->INSTRFRAME.reg; //Datasheet says to read this register once to synchronize.

 

Now that the QSPI reads are set up, you can put this in a loop for consecutive 4-byte reads from any random address:

 

while (1) {
QSPI-> CTRLA.bit.ENABLE =1;  //Not sure why, but you have to re-enable this after each read.  Go figure.
while(QSPI -> STATUS.bit.ENABLE ==0);  //Wait for the enable to happen

 

flash_read[0] = (*(uint32_t *)(0x4000020));  //Trigger the read out of QSPI space.  This reads 4 bytes starting at 0x20.  Since the SAMd51 is 32 bits, the QSPI controller takes 4 bytes out of the flash with address read plus 3 consecutive reads.  So, address your FLASH chip in x4 (0x4000000, 0x4000004, 0x4000008, etc)

 

QSPI -> CTRLA.bit.LASTXFER =1;  //Set the last transfer bit.  This is why you need to re-enable the QSPI again at each new read, I think.

 

sprintf(serial_txt, "Show values   0x%lx \n", flash_read[0]); //Print out your 4 bytes flash data
UART_EDBG_init(serial_txt);

}

 

 

So, with the QSPI controller clocked at a 48Mhz BAUD rate, I can grab 4 bytes of QSPI data from a random location in about 600ns.  Not too shabby.

 

Note the ordering of you data in the 32-bit "flash_read[0]" register.  

 

If you get 0x80706d6e from the read at 0x4000020:

Data     Flash Address

0x80 = 0x23

0x70 = 0x22

0x6d = 0x21

0x6e = 0x20

 

Does that make sense?  I think that makes sense.

 

 

Happy QSPI'ing!

 

-troy

 

Last Edited: Mon. Jul 29, 2019 - 08:54 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

QSPI -> CTRLA.bit.LASTXFER =1;  //Set the last transfer bit.  This is why you need to re-enable the QSPI again at each new read, I think.

The QSPI peripheral is supposed to allow "execute in place", which I would think should mean that you don't have to do anything other than the read.

(Perhaps the particular flash chip used doesn't allow it?  But I thought they were pretty standardized...)

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Misplaced comment deleted...

Last Edited: Fri. Oct 4, 2019 - 04:29 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

One thing to note...

 

I did development on the Adafruit Metro M4 and QSPI was working fine.  Then my own PCBs came in, and the QSPI did not work.

 

There is a non-volatile "Quad-Enable" bit in the status register of the Flash chips.  The M4s seem to have this bit set already when you buy the board, so you don't have to set QE.  But if you get your own fresh Flash chips from the factory, you need code to enable this QE bit, otherwise, no QSPI worko.

 

-troy