SPI Flash problem with frequencies greater than 1MHz

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

SPI Flash problem with frequencies greater than 1MHz

3,832 Views
durgeshtanuku
Contributor II

Hello,

     I am using KL25Z64 controller in my project. I have interfaced spansion's S25FL128S external flash. My flash code is working fine when I set 1MHz clock rate in component settings. But when I change the frequency to above 1MHz flash is not responding for Read/Sector erase commands.

    I have gathered the information from reference manual that, spi can work with frequencies upto half of the bus clock frequency when used as master. My core clock and bus clock frequencies are 48MHz and 24MHz. So it should work upto 12MHz.

     I have read the information in reference manual of flash IC that, it works till 113MHz of frequency.

     When I set the frequencies above 1MHz, I could see the spi clock getting generated with the help of logic analyser. But Coding blocking for receive interrupt.

     Suggest me how to resolve this issue

regards,

Durgesh

Labels (1)
Tags (2)
11 Replies

2,013 Views
paulstoffregen
Contributor III

I tested a similar SPI flash chip with Teensy 3.1 (Kinetis K20) today, using 12 MHz SPI clock.

It worked fine, even using normal wires on a solderless breadboard.  Details here:

https://forum.pjrc.com/threads/27507-SPIFIO-issues?p=61918#post61918

flash.jpg

0 Kudos

2,013 Views
mjbcswitzerland
Specialist V

Hi

I have a feeling that the problem here is that the code performing writing/erase and then reading is not checking the SPI Flash chip's busy state.

This means that, as long as the communication speed is low, the flash has completed internal operations when the read starts and so things look OK.

When there is a higher speed the Flash no longer has time to complete the operation and so the read fails because the Flash is still busy.

The solution is to always first check the busy state of the device after a write/erase operation has previously been performed.

Regards

Mark

µTasker Kinetis support

0 Kudos

2,013 Views
durgeshtanuku
Contributor II

Hello Mark,

After working for 4hrs I found the bug in my code(sequence read, write operations I am operating of flash).

Now It is working with the frequencies above 1MHz also.

But I found It's not working with two particular frequencies i.e., 4MHz and 6MHz. With these two frequencies, I am facing the problem in above reply to you(reply with links).

Kindly inform me if you know what might be the problem

Best regards,

Durgesh

2,013 Views
mjbcswitzerland
Specialist V

Hi

Since many people work with the chips at many speeds without any problems, any difficultis are due to coding problems that are susceptible to timing.

I would suggest not to use the PE generated code since your code has no need to be based on its interrupt operation, which is simply complicated things in this situation and causing random behaviour (sometimes OK sometimes not).

Simply send each byte from your buffer by polling the SPI status register after each byte transmission until all have been sent. Then you won't need to depend on the Tx_CompleteFlag.

There is probably also a polling option in PE that could be used instead, which would probably make the behavior more predictable.

Regards

Mark

2,013 Views
durgeshtanuku
Contributor II

Hello Mark

I am polling the device status after each write/erase operation in other function.

Today I have found that problem is with OnBlockReceive interrupt. While debugging the code, I have found that.

When the frequency is greater that 1MHz, InpRcvDataNum is 1 less than the number of bytes I have mentioned in ReceiveBlock function. So the control is blocking for dummy buffer to be willed with the number of bytes mentioned in ReceiveBlock.

Kindly verify the below screen shots

1) 1MHz ----- http://s1.postimg.org/nrhjrl8un/1_MHz.png

2) 4MHz ----- http://s16.postimg.org/x6gd846f9/4_MHz.png

regards,

Durgesh

0 Kudos

2,013 Views
jeremyzhou
NXP Employee
NXP Employee

Hi Durgesh Tanuku,

At first, I'd like to suggest that we should figure out the root reason of the issue.

Did you have the demo that use another MCU work with the external flash on >1 MHz frequency?

If yes, I strongly recommend that you can use logic analyzer to capture the operation signal of the previous MCU and the KL25 communicate with external flash, then compare the signals and find out the differences.

After the comparison of the signals, it will make the reason more conspicuously.

I'm looking forward to your reply.
Have a great day,
Ping

-----------------------------------------------------------------------------------------------------------------------
Note: If this post answers your question, please click the Correct Answer button. Thank you!
-----------------------------------------------------------------------------------------------------------------------

0 Kudos

2,013 Views
durgeshtanuku
Contributor II

Hello jeremyzhou,

Sorry, I don't have any other controller to test what you told. But my colleague is working on K60DN120 cortex M4.

He is also facing same issue. I am attaching the screen shot of my logic analyser for 1MHz(working frequency) and other non working frequency.

     Code is getting blocked for Rx_Complete_Flag which I am setting in SM0_OnBlockReceive if i am using frequencies greater that 1MHz.

capture for reading an array with 1MHz clock frequency

http://postimg.org/image/paml16otd/

capture for reading an array with 4MHz(>1MHz) clock frequency

http://postimg.org/image/mwf62q8af/


capture of code block instance

http://postimg.org/image/jxewkpqg1/

0 Kudos

2,013 Views
jeremyzhou
NXP Employee
NXP Employee

Hi Durgesh Tanuku,

I've also been confused with this issue until now, and I attach a SPI demo of K60 without using PE, please refer to it and build a new project for the communication between the MCU and spansions.
Have a great day,
Ping

-----------------------------------------------------------------------------------------------------------------------
Note: If this post answers your question, please click the Correct Answer button. Thank you!
-----------------------------------------------------------------------------------------------------------------------

0 Kudos

2,013 Views
durgeshtanuku
Contributor II

!

Hello jeremyzhou,

Sorry, I don't have any other controller to test what you told. But my colleague is working on K60DN120 cortex M4.

He is also facing same issue. I am attaching the screen shot of my logic analyser for 1MHz(working frequency) and other non working frequency.

     Code is getting blocked for Rx_Complete_Flag which I am setting in SM0_OnBlockReceive if i am using frequencies greater that 1MHz.

capture for reading an array with 1MHz clock frequency

http://postimg.org/image/paml16otd/

capture for reading an array with 4MHz(>1MHz) clock frequency

http://postimg.org/image/mwf62q8af/


capture of code block instance

http://postimg.org/image/jxewkpqg1/

!

0 Kudos

2,013 Views
jeremyzhou
NXP Employee
NXP Employee

Hi Durgesh Tanuku,

I‘ve contacted with my colleagues about this issue and one of them said that he encountered the similar issue before.

He interfaced the MCU with the external flash device by using the normal wire and the external flash device could worked fine at low rate, however the operation broke down when the rate beyond the specific frequency.

The issue disappeared when he used theP PCB board instead of the normal wire.

So I'd like to confirm that what way you use to test。
Have a great day,
Ping

-----------------------------------------------------------------------------------------------------------------------
Note: If this post answers your question, please click the Correct Answer button. Thank you!
-----------------------------------------------------------------------------------------------------------------------

0 Kudos

2,013 Views
durgeshtanuku
Contributor II

I am testing this on actual PCB where flash and controller are interfaced

I am using the following code for reading and writing into flash. I have followed the instructions according to the spansions data sheet.

The code is working with lower frequencies(below 1MHz) but not working for higher frequencies

//////////////////////////////////////

#include "../SLLD/slld.h"

#include "HAL.h"

#include "SM0.h"

uint8_t wrBuffer[MAX_BUFFER_SIZE];

uint8_t Dummy_buffer[MAX_BUFFER_SIZE];

// ***************************************************************************

//  FLASH_READ - HAL read function

//

//  input : device_num            device number to which operation will be done

//          command               write a single command byte to flash

//          sys_addr              system address to be used

//          data_buffer           Pointer to the data buffer where to store the read data

//          Number_Of_Read_Bytes  number of bytes to be read

//

//  return value : status of the operation - FAIL or SUCCESS

// ***************************************************************************

SLLD_STATUS FLASH_READ(BYTE command,ADDRESS sys_addr,BYTE *data_buffer,int Number_Of_Read_Bytes )

{

  uint8_t Addr1,Addr2,Addr3;

  uint8_t Cmd_Size;

    uint8_t AddBufferPtr[ADD_BUFFER_SIZE]; //! buffer to store address of the flash

    uint8_t Dummy_buffer[DUMMY_BUFFER_SIZE];    //! spi dummy buffer

    SLLD_STATUS status = SLLD_OK;

    Cmd_Size=0;

  AddBufferPtr[Cmd_Size++]=command;

    if(sys_addr != ADDRESS_NOT_USED)

    {

    Addr1=sys_addr;

    Addr2=sys_addr>>8;

    Addr3=sys_addr>>16;

  

  AddBufferPtr[Cmd_Size++]=Addr3;

  AddBufferPtr[Cmd_Size++]=Addr2;

  AddBufferPtr[Cmd_Size++]=Addr1;

    }

   

    // The AddBufferPtr contains the read command along with address of flash to be read

    //make the chip select pin low

    CS_SPI_ClrVal(CS_SPI_DeviceData);

   

    // send the AddBufferPtr to flash

    if(SM0_SendBlock(masterDevData,(LDD_TData*)AddBufferPtr,Cmd_Size)!=ERR_OK)

    {

    while(1);

    }

    if(SM0_ReceiveBlock(masterDevData, (LDD_TData*)Dummy_buffer,Cmd_Size)!=ERR_OK)

    {

    while(1);

    }

    // Wait till transmission and reception completes

    while(Tx_CompleteFlag==0);

    Tx_CompleteFlag=0;

    while(Rx_CompleteFlag==0);

    Rx_CompleteFlag=0;

    // receive the data from flash

  if(SM0_SendBlock(masterDevData, (LDD_TData*)msgDummy,Number_Of_Read_Bytes)!=ERR_OK)

    {

    while(1);

    }

  if(SM0_ReceiveBlock(masterDevData, (LDD_TData*)data_buffer,Number_Of_Read_Bytes)!=ERR_OK)

    {

    while(1);

    }

  //wait till actual data received

    while(Tx_CompleteFlag==0);

    Tx_CompleteFlag=0;

    while(Rx_CompleteFlag==0);

    Rx_CompleteFlag=0;

    // disassert the chipselect

   CS_SPI_SetVal(CS_SPI_DeviceData);

    return(status);

}

/***************************************************************************

  FLASH_WRITE - HAL write function

  input : device_num               device number to which operation will be done

          command                  write a single command byte to flash

          sys_addr                 system address to be used

          data_buffer              Pointer to the data buffer where to store the written data

          Number_Of_Written_Bytes  number of bytes to be written

  return value : status of the operation - FAIL or SUCCESS

***************************************************************************/

SLLD_STATUS FLASH_WRITE(BYTE command,ADDRESS sys_addr,BYTE *data_buffer,int Number_Of_Written_Bytes)

{

    SLLD_STATUS status = SLLD_OK;

   

    uint32_t Cmd_Size;

  uint8_t Addr1,Addr2,Addr3;

    Cmd_Size=0;

   

    wrBuffer[Cmd_Size++] = command;

   

    if(sys_addr != ADDRESS_NOT_USED)

    {

    Addr1=sys_addr;

    Addr2=sys_addr>>8;

    Addr3=sys_addr>>16;

    Cmd_Size = 0;

  

    wrBuffer[Cmd_Size++]=command;

    wrBuffer[Cmd_Size++]=Addr3;

    wrBuffer[Cmd_Size++]=Addr2;

    wrBuffer[Cmd_Size++]=Addr1;

  

    if(data_buffer != BUFFER_NOT_USED)

    {

    uint16_t count;

    for(count=0;count<Number_Of_Written_Bytes;count++)

    {

    wrBuffer[Cmd_Size++] = (uint8_t)*data_buffer;

    data_buffer++;

    }

    }

    }

   

    CS_SPI_ClrVal(CS_SPI_DeviceData);

   

    SM0_SendBlock(masterDevData,(LDD_TData*)wrBuffer,Cmd_Size);

    SM0_ReceiveBlock(masterDevData, (LDD_TData*)Dummy_buffer,Cmd_Size);

    while(Tx_CompleteFlag==0);

    Tx_CompleteFlag=0;

    while(Rx_CompleteFlag==0);

    Rx_CompleteFlag=0;

   CS_SPI_SetVal(CS_SPI_DeviceData);

   

    return(status);

}

0 Kudos