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
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
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
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
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
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
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!
-----------------------------------------------------------------------------------------------------------------------
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
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!
-----------------------------------------------------------------------------------------------------------------------
!
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/
!
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!
-----------------------------------------------------------------------------------------------------------------------
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);
}