Click here to Skip to main content
15,885,896 members
Please Sign up or sign in to vote.
1.00/5 (1 vote)
See more:
Hi,

I have a .bin file and I want to write it to the qspi memory.

[edit]Code block added - OriginalGriff[/edit]

What I have tried:

I'm dumping the file while debugging the program. but I'm not able to write the file into the buffer properly. Here I'm writing the code..

C++
#include "xparameters.h"	/* SDK generated parameters */
#include "xqspips.h"		/* QSPI device driver */
#include "xil_printf.h"

#define QSPI_DEVICE_ID		XPAR_XQSPIPS_0_DEVICE_ID


#define WRITE_STATUS_CMD	0x01
#define WRITE_CMD		0x02
#define READ_CMD		0x03
#define WRITE_DISABLE_CMD	0x04
#define READ_STATUS_CMD		0x05
#define WRITE_ENABLE_CMD	0x06
#define FAST_READ_CMD		0x0B
#define DUAL_READ_CMD		0x3B
#define QUAD_READ_CMD		0x6B
#define BULK_ERASE_CMD		0xC7
#define	SEC_ERASE_CMD		0xD8
#define READ_ID			0x9F


#define COMMAND_OFFSET		0 /* FLASH instruction */
#define ADDRESS_1_OFFSET	1 /* MSB byte of address to read or write */
#define ADDRESS_2_OFFSET	2 /* Middle byte of address to read or write */
#define ADDRESS_3_OFFSET	3 /* LSB byte of address to read or write */
#define DATA_OFFSET		4 /* Start of Data for Read/Write */
#define DUMMY_OFFSET		4 /* Dummy byte offset for fast, dual and quad
				     reads */
#define DUMMY_SIZE		1 /* Number of dummy bytes for fast, dual and
				     quad reads */
#define RD_ID_SIZE		4 /* Read ID command + 3 bytes ID response */
#define BULK_ERASE_SIZE		1 /* Bulk Erase command size */
#define SEC_ERASE_SIZE		4 /* Sector Erase command + Sector address */

#define OVERHEAD_SIZE		4

/*
 * The following constants specify the page size, sector size, and number of
 * pages and sectors for the FLASH.  The page size specifies a max number of
 * bytes that can be written to the FLASH with a single transfer.
 */
#define SECTOR_SIZE		0x10000
#define NUM_SECTORS		0x100
#define NUM_PAGES		0x10000
#define PAGE_SIZE		256

/*
 * Number of flash pages to be written.
 */
#define PAGE_COUNT		1611

/*
 * Flash address to which data is ot be written.
 */
#define TEST_ADDRESS		0x00000000
#define UNIQUE_VALUE		0x05
/*
 * The following constants specify the max amount of data and the size of the
 * the buffer required to hold the data and overhead to transfer the data to
 * and from the FLASH.
 */
#define MAX_DATA		PAGE_COUNT * PAGE_SIZE

/**************************** Type Definitions *******************************/

/***************** Macros (Inline Functions) Definitions *********************/

/************************** Function Prototypes ******************************/

void FlashErase(XQspiPs *QspiPtr, u32 Address, u32 ByteCount);

void FlashWrite(XQspiPs *QspiPtr, u32 Address, u32 ByteCount, u8 Command);

void FlashRead(XQspiPs *QspiPtr, u32 Address, u32 ByteCount, u8 Command);

int FlashReadID(void);

int QspiFlashPolledExample(XQspiPs *QspiInstancePtr, u16 QspiDeviceId);

/************************** Variable Definitions *****************************/

/*
 * The instances to support the device drivers are global such that they
 * are initialized to zero each time the program runs. They could be local
 * but should at least be static so they are zeroed.
 */
static XQspiPs QspiInstance;

/*
 * The following variable allows a test value to be added to the values that
 * are written to the FLASH such that unique values can be generated to
 * guarantee the writes to the FLASH were successful
 */
int Test = 5;

/*
 * The following variables are used to read and write to the flash and they
 * are global to avoid having large buffers on the stack
 */
u8 ReadBuffer[MAX_DATA + DATA_OFFSET + DUMMY_SIZE];
u8 WriteBuffer[PAGE_SIZE + DATA_OFFSET];

/*****************************************************************************/
/**
*
* Main function to call the QSPI Flash example.
*
* @param	None
*
* @return	XST_SUCCESS if successful, otherwise XST_FAILURE.
*
* @note		None
*
******************************************************************************/
int main(void)
{
	int Status;

	xil_printf("QSPI FLASH Polled Example Test \r\n");

	/*
	 * Run the Qspi Interrupt example.
	 */
	Status = QspiFlashPolledExample(&QspiInstance, QSPI_DEVICE_ID);
	if (Status != XST_SUCCESS) {
		xil_printf("QSPI FLASH Polled Example Test Failed\r\n");
		return XST_FAILURE;
	}

	xil_printf("Successfully ran QSPI FLASH Polled Example Test\r\n");
	return XST_SUCCESS;
}

/*****************************************************************************
*
* The purpose of this function is to illustrate how to use the XQspiPs
* device driver in polled mode. This function writes and reads data
* from a serial FLASH.
*
* @param	None.
*
* @return	XST_SUCCESS if successful, else XST_FAILURE.
*
* @note		None.
*
*****************************************************************************/
int QspiFlashPolledExample(XQspiPs *QspiInstancePtr, u16 QspiDeviceId)
{
	int Status;
	u8 *BufferPtr;
	u8 UniqueValue;
	int Count;
	int Page;
	XQspiPs_Config *QspiConfig;

	/*
	 * Initialize the QSPI driver so that it's ready to use
	 */
	QspiConfig = XQspiPs_LookupConfig(QspiDeviceId);
	if (NULL == QspiConfig) {
		return XST_FAILURE;
	}

	Status = XQspiPs_CfgInitialize(QspiInstancePtr, QspiConfig,
					QspiConfig->BaseAddress);
	if (Status != XST_SUCCESS) {
		return XST_FAILURE;
	}

	/*
	 * Perform a self-test to check hardware build
	 */
	Status = XQspiPs_SelfTest(QspiInstancePtr);
	if (Status != XST_SUCCESS) {
		return XST_FAILURE;
	}

	/*
	 * Initialize the write buffer for a pattern to write to the FLASH
	 * and the read buffer to zero so it can be verified after the read,
	 * the test value that is added to the unique value allows the value
	 * to be changed in a debug environment to guarantee
	 */
	for (UniqueValue = UNIQUE_VALUE, Count = 0; Count < PAGE_SIZE;
	     Count++, UniqueValue++) {
		WriteBuffer[DATA_OFFSET + Count] = (u8)(UniqueValue + Test);
	}
	memset(ReadBuffer, 0x00, sizeof(ReadBuffer));

	/*
	 * Set Manual Start and Manual Chip select options and drive HOLD_B
	 * pin high.
	 */
	XQspiPs_SetOptions(QspiInstancePtr, XQSPIPS_MANUAL_START_OPTION |
			XQSPIPS_FORCE_SSELECT_OPTION |
			XQSPIPS_HOLD_B_DRIVE_OPTION);

	/*
	 * Set the prescaler for QSPI clock
	 */
	XQspiPs_SetClkPrescaler(QspiInstancePtr, XQSPIPS_CLK_PRESCALE_8);

	/*
	 * Assert the FLASH chip select.
	 */
	XQspiPs_SetSlaveSelect(QspiInstancePtr);


	//FlashReadID();

	/*
	 * Erase the flash.
	 */
	//FlashErase(QspiInstancePtr, TEST_ADDRESS, MAX_DATA);

	/*
	 * Write the data in the write buffer to the serial FLASH a page at a
	 * time, starting from TEST_ADDRESS
	 */
	for (Page = 0; Page < PAGE_COUNT; Page++) {
		FlashWrite(QspiInstancePtr, (Page * PAGE_SIZE) + TEST_ADDRESS,
			   PAGE_SIZE, WRITE_CMD);
	}


	return XST_SUCCESS;
}
Posted
Updated 22-May-20 1:58am
v2
Comments
CPallini 5-Sep-17 5:02am    
"but I'm not able to write the file into the buffer properly."
That is rather vague. Could you please give us more info?
What kind of device are your programming? What is the QUAD SPI FLASH peripheral?

1 solution

You are nowhere trying to write data. It looks like the posted code is based on the code from xqspips_flash_polled_example.c[^].

If so, you have to copy the data to be written to &WriteBuffer[DATA_OFFSET] and call FlashWrite() page wise.

Untested example:
C++
// pSrcData: Data read from file
// nSrcLen:  Number of bytes
// Assuming driver has been initialised

u32 nPage;
u32 nPages = nSrcLen / PAGE_SIZE;
u32 nLast = nSrcLen % PAGE_SIZE;
u32 nSpiAddress = 0; // Flash start address
u32 nOffset = 0;

#if 0
// Optional read and store last page here if data should be preserved
// Only necessary if nLast is not zero
u8 pPreserved[PAGE_SIZE]; 
if (nLast)
{
    FlashRead(QspiInstancePtr, nSpiAddress + nPages * PAGE_SIZE, PAGE_SIZE, READ_CMD);
    memcpy(pPreserved, &ReadBuffer[DATA_OFFSET], PAGE_SIZE);
}
#endif

// Erase flash pages to be written
u32 nMaxData = nPages * PAGE_SIZE;
if (nLast)
    nMaxData += PAGE_SIZE;
FlashErase(QspiInstancePtr, nSpiAddress, nMaxData);

for (nPage = 0; nPage < nPages; nPage++, nOffset += PAGE_SIZE) 
{
    memcpy(&WriteBuffer[DATA_OFFSET], pSrcData + nOffset, PAGE_SIZE);
    FlashWrite(QspiInstancePtr, nSpiAddress + nOffset, PAGE_SIZE, WRITE_CMD);
}
if (nLast)
{
    // Clear unused memory
    memset(&WriteBuffer[DATA_OFFSET + nLast], 0, PAGE_SIZE - nLast);
    // If the memory must be preserved, it must be read and stored before erasing
    //  and copied back here
    //memcpy(&WriteBuffer[DATA_OFFSET], pPreserved, PAGE_SIZE);
    memcpy(&WriteBuffer[DATA_OFFSET], pSrcData + nOffset, nLast);
    FlashWrite(QspiInstancePtr, nSpiAddress + nOffset, PAGE_SIZE, WRITE_CMD);
}

// Perform verification in a similar manner by reading data and comapre with pSrcData
 
Share this answer
 
Comments
CPallini 5-Sep-17 5:55am    
My 5.
Veerendra-13142768 20-Sep-17 4:38am    
Hi,
Thanks for ur reply. I'm restoring file before executing flashwrite(), using write buffer address, I tried to change byte count to MAX_DATA also. But its not working....
Jochen Arndt 20-Sep-17 5:17am    
It looks like you still did not understand how flash memory is written.

- You have to erase the memory before writing
- You can not write more than page size bytes at once to the flash memory
- If you have more data, you have to write page by page
- Because your FlashWrite() function uses a defined buffer (WriteBuffer), you have to copy the data to be written to that buffer before calling the function
- You have to pass the matching arguments (flash memory address)

I can not test the code because I don't have the hardware. But my example code shows how it must be done.

In the loop:
memcpy(&WriteBuffer[DATA_OFFSET], pSrcData + nOffset, PAGE_SIZE);

Copies a block of data from pSrcData to the buffer (pSrcData must contain the complete file).
FlashWrite(QspiInstancePtr, nSpiAddress + nOffset, PAGE_SIZE, WRITE_CMD);

Writes a block of data (page size) from the buffer to the flash memory.
Veerendra-13142768 20-Sep-17 6:12am    
Hello,
Sorry for asking same again and again. yeah I understood that we cant write more than 1 page(256bytes) at a time, that's why we are using for loop in the code.

//for (Page = 0; Page < PAGE_COUNT; Page++)
{
FlashWrite(QspiInstancePtr, (Page * PAGE_SIZE) + TEST_ADDRESS,PAGE_SIZE, WRITE_CMD);
}
//
and u have given file pSrcData, that we are restoring completely while debugging.
And if you want hardware to test the code ,then you can come online(teamviewer) and can check on hardware....

Thank you...
Jochen Arndt 20-Sep-17 6:20am    
Sorry, but I'm not going to test it for you. We are all volunteers here and have "main" jobs to earn money.

Why do you have removed the memcpy() line?
It won't work without that!

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900