program an extern flash memory with QSPI of coldfire 52235

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

program an extern flash memory with QSPI of coldfire 52235

5,915 Views
fjoli
Contributor I
Hello,

I am trying to program an extern flash memory with QSPI of my coldfire 52235EVB but I don't succeed.
When I read the status register I don't get what I am supposed to have. for example when I send the command Write Enable I am supposed to have the corresponding bit set to 1 but I haven't.
When I program some bytes of the memory and after I read it I don't get what I write.
I am using a flash memory of spansion (S25FL) but maybe I will change if somebody know a good flash memory.
Does somebody had already have this kind of problems ?
Does anybody have some example of code to program an extern flash memory with QSPI ?

thanks.

Fabien
Labels (1)
0 Kudos
10 Replies

1,054 Views
fjoli
Contributor I
Hello,

I have solved my problem. As Mark said it was a problem of wires which was too long.
Thanks everybody for your help.

Fabien
0 Kudos

1,054 Views
fjoli
Contributor I
Hello,

I have tryied to make the wire as short as possible, the board with the memory flash is directly connect to the coldfire.
I have tryied the exemple of code of JimDon.
I have tryied three differents flash memory (I have tried the one  you talk about Kremer the M25P40).

But nothing works I already have the same problem when I send the write enable command and then I read the status register I have 0.
 
Is there something to do before using a flash memory ?
Have you an idea about what can I forget to do ?
Here is the code I use please tell me if you see somethings wrong or if you can test it ?

After QSPI_init(), I call qspi_write_enable() and then I call qspi_read_register and I have 0 everytime.

Thanks for your help

Fabien

Code:
void QSPI_init(){  //initialisation des pins QSPI MCF_GPIO_PQSPAR |=  MCF_GPIO_PQSPAR_QSPI_DOUT_DOUT | MCF_GPIO_PQSPAR_QSPI_DIN_DIN |       MCF_GPIO_PQSPAR_QSPI_CLK_CLK |       MCF_GPIO_PQSPAR_QSPI_CS0_CS0 | MCF_GPIO_PQSPAR_QSPI_CS1_CS1 |       MCF_GPIO_PQSPAR_QSPI_CS2_CS2 |MCF_GPIO_PQSPAR_QSPI_CS3_CS3; //initialisation registre mode MCF_QSPI_QMR = MCF_QSPI_QMR_BAUD(0x4B);// MCF_QSPI_QMR |= MCF_QSPI_QMR_DOHIE;// MCF_QSPI_QMR |= MCF_QSPI_QMR_CPOL;// MCF_QSPI_QMR |= MCF_QSPI_QMR_CPHA; MCF_QSPI_QMR |= MCF_QSPI_QMR_MSTR; MCF_QSPI_QMR |= MCF_QSPI_QMR_BITS(8); //initialisation des délais// MCF_QSPI_QDLYR = MCF_QSPI_QDLYR_DTL(2); MCF_QSPI_QDLYR = (0|            MCF_QSPI_QDLYR_QCD(0x4B)|// delay from assertion of CS to valid QSPI_CLK transition            MCF_QSPI_QDLYR_DTL(9)    // delay after transfer                                 );  //initialisation du registre de control des interruption (pas d'interruption et effacement de toutes les interruptions) MCF_QSPI_QIR = MCF_QSPI_QIR_WCEFB | MCF_QSPI_QIR_ABRTB | MCF_QSPI_QIR_ABRTL |
  MCF_QSPI_QIR_SPIF | MCF_QSPI_QIR_ABRT|MCF_QSPI_QIR_WCEF/*|MCF_QSPI_QIR_SPIFE*/;  }int qspi_write_enable(){  MCF_QSPI_QAR = 0x20; // set QAR to command RAM zone    MCF_QSPI_QDR = 0x0E00;            // last transfer    MCF_QSPI_QAR = 0x00;      // set QAR to transmit RAM zone    MCF_QSPI_QDR = 0x06;              // send READ instruction to flash       MCF_QSPI_QWR = (0|MCF_QSPI_QWR_CSIV| MCF_QSPI_QWR_ENDQP( 0 ));// chip select active low                               // set end queue pointer, other pointers null                     MCF_QSPI_QDLYR |= MCF_QSPI_QDLYR_SPE; // enable qspi module    /******************* INTERRUPT HANDLING ********************/    // write collision error    if( (( MCF_QSPI_QIR & MCF_QSPI_QIR_WCEF ) == MCF_QSPI_QIR_WCEF))    {        return -1;    }    // abort error    if( (( MCF_QSPI_QIR & MCF_QSPI_QIR_ABRT ) == MCF_QSPI_QIR_ABRT))    {        return -2;    }    // wait until tranfer finished     //while(ptr_sQSPI->temps_set != 1);    while ( (MCF_QSPI_QIR & MCF_QSPI_QIR_SPIF) != MCF_QSPI_QIR_SPIF );    MCF_QSPI_QIR |= MCF_QSPI_QIR_SPIF; // QSPI finished flag cleared    // MCF_GPIO_PORTQS = 0x08;}int qspi_read_register(uint16 * buffer, unsigned int size){    int i = 0;       MCF_QSPI_QAR = 0x20; // set QAR to command RAM zone    MCF_QSPI_QDR = 0x8E00;            // READ instruction time  for ( i = 1 ; i < size ; i++ )    {        MCF_QSPI_QDR = 0x8E00;        // data receive time    }    MCF_QSPI_QDR = 0x0E00;            // last transfer    MCF_QSPI_QAR = 0x00;      // set QAR to transmit RAM zone    MCF_QSPI_QDR = 0x05;              // send READ instruction to flash    for( i = 0 ; i < size ; i++ )    {        MCF_QSPI_QDR = 0x0;          // requested data sent out    }MCF_QSPI_QWR = (0|MCF_QSPI_QWR_CSIV| MCF_QSPI_QWR_ENDQP( size));// chip select active low                               // set end queue pointer, other pointers null                  // MCF_GPIO_PORTQS = 0x00;    MCF_QSPI_QDLYR |= MCF_QSPI_QDLYR_SPE; // enable qspi module    /******************* INTERRUPT HANDLING ********************/    // write collision error    if( (( MCF_QSPI_QIR & MCF_QSPI_QIR_WCEF ) == MCF_QSPI_QIR_WCEF))    {        return -1;    }    // abort error    if( (( MCF_QSPI_QIR & MCF_QSPI_QIR_ABRT ) == MCF_QSPI_QIR_ABRT))    {        return -2;    }    // wait until tranfer finished     //while(ptr_sQSPI->temps_set != 1);    while ( (MCF_QSPI_QIR & MCF_QSPI_QIR_SPIF) != MCF_QSPI_QIR_SPIF );    MCF_QSPI_QIR |= MCF_QSPI_QIR_SPIF; // QSPI finished flag cleared        MCF_QSPI_QAR = 0x10 + 1;            // set QAR to receive RAM zone    for ( i = 0; i < size; i++ )    {        // get from hi-byte in the basic address of Receive RAM zone                *buffer = MCF_QSPI_QDR ;                    buffer++;    }    return 0;}


Message Edited by fjoli on 2008-07-08 04:32 PM
0 Kudos

1,054 Views
RichTestardi
Senior Contributor II
I'll add a few observations...  The first is that the scope is the way to go if you have one.  That'll tell you if you have chip select problems (accidental inverts or even de-asserts during the transfer).  The QSPI chip selects are definitely not obvious to use correctly (I got them wrong twice, and only resolved the issue with a scope) -- some folks have had better luck just using a GPIO output pin.  And you have to be careful with the clock edges as well, obviously.  So the scope is really the way to go if you have one.
 
Then, it seems the "|=" here should be an "=", in case you already have non-0 value for pin assignments:
 
    MCF_GPIO_PQSPAR |=  ...
 
That could cause your QSPI pins to never leave the chip...
 
Otherwise everything else looks basically right...  Have you tried just disconnecting QSPI_DIN and using a pull-up or pull-down resistor, and verifying you read back 1's or 0's, respectively?  That would allow you to test this without the external flash.
 
Good luck!
 
-- Rich
0 Kudos

1,054 Views
Kremer
Contributor I
Hi fjoli

This is what i call WR_EN, wich is the GPIO connected to Write Protect pin on my design.

#define WR_EN MCF_GPIO_PORTNQ_PORTNQ2

This pin has no effect on your tests, since it´s related to write operations in memory.

Seems like you are almost there. The only problem i could see on your code is that, on your read status routine, you are expecting to receive the Status Register value right after you send the 0x05 command, without driving the 8 sclk pulses again. I mean, on your code, you drive 8 sclk pulses to shift out the 0x05 value, and expects to receive instantly the status register value from those same 8 sclk pulses.
Just drive 8 more pulses before read QDR and you´ll be fine.

Regards
Alex
0 Kudos

1,054 Views
francois_boucha
Contributor III
Hi, I am using MCF5282 with M25P40 linked by the QSPI module.  I'm able to communicate with the eeprom.
Here is what I do is for a READ instruction at address $0.  According to the M25P40 info, 4 bytes ( 1 instruction and 3 address) has to be sent.  First, I fill the command RAM with 4 commands (for the tx) and 4 commands for the rx.  Then, I place (0x3, 0x0, 0x0, 0x0) in the transmit RAM entry.   Transfer can now start.

Valid received data are located at index 4 to 7 in the Rx RAM.

It works, but do I realy have to place 4 dummy commands for the chip to remain asserted and to keep the clock ticking while receiving my data from the EEPROM?

thx

Francois

0 Kudos

1,054 Views
Kremer
Contributor I
Currently i´m using the M25P40 and another one form microchip 25AA1024 with no problems.
Maybe the problem is with Chip Select. Did you troubleshoot it with a scope in order to see if it´s selected while the SPI data flows out, or even to check if the data comes out indeed?

Here is a piece of my code, wich is used to setup QSPI and to retrieve the status register of the M25P40 serial flash:


void qspi_init(void)
{
/* Habilita IO´s da Porta QS (Menos PQS5) para funcão primária (QSPI) */
MCF_GPIO_PQSPAR |= 0x1255;
MCF_GPIO_DDRQS |= MCF_GPIO_DDRQS_DDRQS5;
MCF_GPIO_PORTQS |= WR_EN;

/* Estabelece atraso entra habilitar CS e iniciar SCLK */
MCF_QSPI_QDLYR = 0x0000|MCF_QSPI_QDLYR_QCD(127);

/* Limpa registrador de interrupção */
MCF_QSPI_QIR |= MCF_QSPI_QIR_SPIF;

/* Configura Modo de Operação*/
MCF_QSPI_QMR = 0xC04B; // SPI a 400 KHz
}


char m25p40_read_status(void)
{
volatile char status_register;

/* Estabelece comunicacao de 8 bits */
MCF_QSPI_QMR &= ~(MCF_QSPI_QMR_BITS(0x0F));
MCF_QSPI_QMR |= MCF_QSPI_QMR_BITS(0x08);

/* Aponta para RAM de comando posição 0 */
MCF_QSPI_QAR = 0x0020;
MCF_QSPI_QDR = 0xDE00;

/* Aponta para RAM de dados posição 0 */
MCF_QSPI_QAR = 0x0000;

/* Entrada dos dados a serem transferidos para CS0 */
MCF_QSPI_QDR = 0x0005;// Read Status Register

/* Configura Wrap Register */
MCF_QSPI_QWR = 0x2000;

/*Transmite */
MCF_QSPI_QDLYR |= MCF_QSPI_QDLYR_SPE;


/* Aguarda término da sequencia*/
while (!(MCF_QSPI_QIR & MCF_QSPI_QIR_SPIF));

MCF_QSPI_QIR |= MCF_QSPI_QIR_SPIF
|MCF_QSPI_QIR_WCEF;

/* Le 8 bits do Status Register da Serial Flash */

MCF_QSPI_QMR &= ~(MCF_QSPI_QMR_BITS(0x0F));
MCF_QSPI_QMR |= MCF_QSPI_QMR_BITS(0x08);

/* Aponta para RAM de comando posição 0 */
MCF_QSPI_QAR = 0x0020;

/* Estabelece sequencia de comandos para CS0 */
MCF_QSPI_QDR = 0xDE00;

/* Aponta para RAM de dados posição 0 */
MCF_QSPI_QAR = 0x0000;

/* Entrada dos dados a serem transferidos para CS0 */
MCF_QSPI_QDR = 0x0000;

/* Configura Wrap Register */
MCF_QSPI_QWR = 0x2000;

/*Transmite */
MCF_QSPI_QDLYR |= MCF_QSPI_QDLYR_SPE;


/* Aguarda término da sequencia*/
while (!(MCF_QSPI_QIR & MCF_QSPI_QIR_SPIF));

MCF_QSPI_QIR |= MCF_QSPI_QIR_SPIF
|MCF_QSPI_QIR_WCEF;

/* Adquire dado */
MCF_QSPI_QAR = 0x0010;

status_register = MCF_QSPI_QDR;

MCF_QSPI_QIR |= MCF_QSPI_QIR_SPIF
|MCF_QSPI_QIR_WCEF;
delay_us(1000);

/* Le 8 bits do Status Register da Serial Flash */

MCF_QSPI_QMR &= ~(MCF_QSPI_QMR_BITS(0x0F));
MCF_QSPI_QMR |= MCF_QSPI_QMR_BITS(0x08);

/* Aponta para RAM de comando posição 0 */
MCF_QSPI_QAR = 0x0020;

/* Estabelece sequencia de comandos para CS0 */
MCF_QSPI_QDR = 0xDE00;

/* Aponta para RAM de dados posição 0 */
MCF_QSPI_QAR = 0x0000;

/* Entrada dos dados a serem transferidos para CS0 */
MCF_QSPI_QDR = 0x0000;

/* Configura Wrap Register */
MCF_QSPI_QWR = 0x3000;

/*Transmite */
MCF_QSPI_QDLYR |= MCF_QSPI_QDLYR_SPE;


/* Aguarda término da sequencia*/
while (!(MCF_QSPI_QIR & MCF_QSPI_QIR_SPIF));

MCF_QSPI_QIR |= MCF_QSPI_QIR_SPIF
|MCF_QSPI_QIR_WCEF;

return(status_register);

}


Hope this helps. To understand it you must read the M25P40 datasheet too.

Message Edited by Kremer on 2008-07-04 07:36 PM
0 Kudos

1,054 Views
fjoli
Contributor I
Hello Kremer

Thanks for your answer.

I have use a scope to see the QSPI communication, there is no problem with the chip select and I can see the command I want to send but when I read the status register or the memory I don't have what I am supposed to have.

I tryied your piece of code to read the status register I don't have what I am supposed to have, I only send a command "write enable" and after I read the status register and I have 0 instead of 2 (write enable bit = 1).

I have some question about your code :

what is the value of WR_EN in qspi_init() ?

And why do you wait and then send a 0 after you have read the value of the status register ?


Thanks

Fabien

0 Kudos

1,054 Views
JimDon
Senior Contributor III
Here is some sample code that shows QSPI driving EzPort.

Don't know if it applies, but it may be worth a try.
0 Kudos

1,054 Views
mjbcswitzerland
Specialist V
Hi

When prototyping with SPI FLASH make sure that your wires are as short as possible. They can be quite sensitive to overshoot and ringing - even connecting a scope to the clock line has been known to stop them working correctly (when on the limit).

Regards

Mark

www.uTasker.com
0 Kudos

1,054 Views
mjbcswitzerland
Specialist V
Hi Fabien

Take a look at the uTasker project (www.uTasker.com). It supports SPI FLASH (presently ATMEL and ST, with SST being added shortly). This allows the 55235 to be connected to one or more such devices and use it /them as file system (eg. for serving web pages) or for firmware updates (via Ethernet). The M52235 and the SPI FLASH (QSPI) are simulated so that all such futher development work can be continued comfortably on a PC without needing to work on the target.

It is suported at its forum www.uTasker.com/forum/ where you will also find a number of discussions about using SPI FLASH together with the Coldfire.

Regards

Mark

0 Kudos