加載方法
ZYNQ的啟動鏡像是由FSBL程序(bootloader),PL配置文件(硬件比特流文件),應用層軟件三個部分組成,其通過SDK的軟件生成工具把三個部分按規定的格式拼湊成一個.bin文件,最終將這個文件寫入到QSPIFLASH中,整個ZYNQ在配置好啟動方式為FLASH啟動后,便可做到上電自啟動運行下載到FLASH中的用戶程序。
為了實現遠程加載,拋開仿真器,通過UART的方式將固定的.bin文件發送給ZYNQ,然后將文件寫入到FLASH。其分三個步驟完成整個程序的更新:第一,搭建UART的傳輸,通過規定的握手協議,PC機將.bin文件以串口的形式發送給ZYNQ;第二,ZYNQ將收到的文件存儲在指定的DDR3內存當中;第三,ZYNQ將DDR3中的文件數據寫入到FLASH,寫完以后在讀出來與接收的數據作對比,做一個校驗。
串口交互形式
1. 開啟PC機加載程序,等待任務機發送加載信號;
2. ZYNQ上電后第一時間給UART發送加載信號0xee,隨后監測UART上的回應信號;
3. PC機監測UART上的加載信號,若是0xee,則發送回應信號0xab,表示PC機做好了進入加載的準備,若不是0xee則不會發送回應信號;
4. ZYNQ收到回應信息0xab以后,進入加載流程,發送獲取長度指令信號0xcc給PC機;
5. PC機監測UART上的獲取長度指令信號,若是0xcc,則發送數據總包數n給PC機(長度=128*n);
6. ZQNY收到數據長度數據后,發送應答信號0xaa給PC機,表示接收到數據長度了;
7. PC機監測UART上的應答信號,接收到應答信號0xaa后,PC機進入發送數據流程,監測ZYNQ的準備好接收數據信號0xdd;
8. ZYNQ接收完數據長度以后,發送準備好接收數據信號0xdd給PC機;
9. PC機監測UART上的準備好接收數據信號0xdd,收到準備好信號0xdd信號以后,發送一包數據(128byte)給ZYNQ,發送完了以后又監測準備好信號0xdd,然后又發送一包數據(128byte)給ZYNQ,往復循環,直到數據包發送完,發送完數據后監測數據接收完信號0xbb;
10. ZYNQ接收完數據后,發送接收完信號0xbb給PC機;
11. PC機監測數據接收完信號0xbb;收到接收完信號0xbb后,數據交互流程完成,ZYNQ監測FLASH寫入操作完成信號;
12. ZYNQ將接收到的數據寫入到FLASH,寫入完了以后發送FLASH寫入操作完成信號0xaf給PC機;
13. PC機監測到接收完成信號0xaf后,提示用戶寫flash操作完成;進入到監測FLASH數據校驗階段;
14. ZYNQ寫完flash后,將對應數據從flash中讀出來做校驗,校驗成功則發送校驗完成信號0xcf給PC機,若校驗失敗則發送失敗信號0xef給PC機;
15. PC機監測到校驗完成信號或者校驗失敗信號后提示用戶校驗完成,整個加載程序完成。
交互流程如圖1所示。
UART與QSPI讀寫函數的設計
Uart初始化流程
1. 通過uart設備ID找到對應的外設信息;
2. 填充uart外設寄存器基地址和一些相關信息;
3. uart外設自檢;
4. 配置uart的fifo的觸發等級;
5. 使能uart外設;
源碼如下
void Init_Uart(void) { XUartPs_Config *UartConifgPtr; s32 temp; //find device UartConifgPtr = XUartPs_LookupConfig (XPAR_PS7_UART_1_DEVICE_ID); //config xuartps data struct XUartPs_CfgInitialize(&Uart_1,UartConifgPtr, UartConifgPtr->BaseAddress); //self test temp = XUartPs_SelfTest(&Uart_1); if(temp != XST_SUCCESS) { return; } // XUartPs_SetDataFormat(&Uart_1,XUARTPS_FORMAT_EVEN_PARITY); //set uart fifo level XUartPs_SetFifoThreshold(&Uart_1,8); //uart enable XUartPs_EnableUart(&Uart_1); }
Uart接收字節函數
判斷RX的FIFO是否為空,如果處于空的狀態,一直等待;如果不為空,讀取RX的FIFO里面的數據,源碼如下:
u8 Uart_RecvByte(void) { u8 byte = 0; while((((XUartPs_ReadReg(InstancePtr->Config.BaseAddress,XUARTPS_SR_OFFSET)) & 0x02) == 0x02)); byte = XUartPs_ReadReg(InstancePtr->Config.BaseAddress,XUARTPS_FIFO_OFFSET); return byte; }
Uart發送字節函數
判斷TX的FIFO是否滿,如果處于滿的狀態,一直等待;如果未滿,則把需要發送的數據寫入到TX的FIFO中,源碼如下:
void Uart_SendByte(u8 byte) { while((((XUartPs_ReadReg(InstancePtr->Config.BaseAddress,XUARTPS_SR_OFFSET)) & 0x10) == 0x10)); XUartPs_WriteReg(InstancePtr->Config.BaseAddress,XUARTPS_FIFO_OFFSET,byte); }
初始化QSPI流程
1. 通過qspi設備ID找到對應的外設信息;
2. 填充qspi外設寄存器基地址和一些相關信息;
3. Qspi外設自檢;
4. 配置qspi的工作模式;
5. 配置qspi的工作頻率;
6. 配置qspi的為從設備選擇;
源碼如下:
void Init_Qspi(void) { XQspiPs_Config *QspiConfig; //find device QspiConfig = XQspiPs_LookupConfig(XPAR_XQSPIPS_0_DEVICE_ID); //config XQspiPs data struct QspiInstance XQspiPs_CfgInitialize(&QspiInstance, QspiConfig,QspiConfig->BaseAddress); //self test XQspiPs_SelfTest(&QspiInstance); //set qspi option XQspiPs_SetOptions(&QspiInstance,XQSPIPS_MANUAL_START_OPTION |XQSPIPS_FORCE_SSELECT_OPTION |XQSPIPS_HOLD_B_DRIVE_OPTION); //set qspi clk XQspiPs_SetClkPrescaler(&QspiInstance, XQSPIPS_CLK_PRESCALE_8); //set slave select of qspi XQspiPs_SetSlaveSelect(&QspiInstance); }
Flash擦除函數流程
1. 根據需要寫入數據的大小判斷需要整片擦除還是扇區擦除;
2. 通過qspi接口將寫使能命令寫入到flash;
3. 通過qspi接口將寫命令和需要擦除的flash地址以及數據發送到flash;
4. 等待數據的傳輸完成;
函數源碼:
*/
WriteBuffer[COMMAND_OFFSET] = BULK_ERASE_CMD;
/*
* Send the bulk erase command; no receive buffer is specified
* since there is nothing to receive
*/
XQspiPs_PolledTransfer(QspiPtr, WriteBuffer, NULL,
BULK_ERASE_SIZE);
/*
* Wait for the erase command to the FLASH to be completed
*/
while (1) {
/*
* Poll the status register of the device to determine
* when it completes, by sending a read status command
* and receiving the status byte
*/
XQspiPs_PolledTransfer(QspiPtr, ReadStatusCmd,
FlashStatus,
sizeof(ReadStatusCmd));
/*
* If the status indicates the write is done, then stop
* waiting; if a value of 0xFF in the status byte is
* read from the device and this loop never exits, the
* device slave select is possibly incorrect such that
* the device status is not being read
*/
if ((FlashStatus[1] & 0x01) == 0) {
break;
}
}
return;
}
/*
* If the erase size is less than the total size of the flash, use
* sector erase command
*/
for (Sector = 0; Sector
/*
* Send the write enable command to the SEEPOM so that it can be
* written to, this needs to be sent as a seperate transfer
* before the write
*/
XQspiPs_PolledTransfer(QspiPtr, &WriteEnableCmd, NULL,
sizeof(WriteEnableCmd));
/*
* Setup the write command with the specified address and data
* for the FLASH
*/
WriteBuffer[COMMAND_OFFSET] = SEC_ERASE_CMD;
WriteBuffer[ADDRESS_1_OFFSET] = (u8)(Address >> 16);
WriteBuffer[ADDRESS_2_OFFSET] = (u8)(Address >> 8);
WriteBuffer[ADDRESS_3_OFFSET] = (u8)(Address & 0xFF);
/*
* Send the sector erase command and address; no receive buffer
* is specified since there is nothing to receive
*/
XQspiPs_PolledTransfer(QspiPtr, WriteBuffer, NULL,
SEC_ERASE_SIZE);
/*
* Wait for the sector erse command to the FLASH to be completed
*/
while (1) {
/*
* Poll the status register of the device to determine
* when it completes, by sending a read status command
* and receiving the status byte
*/
XQspiPs_PolledTransfer(QspiPtr, ReadStatusCmd,
FlashStatus,
sizeof(ReadStatusCmd));
/*
* If the status indicates the write is done, then stop
* waiting, if a value of 0xFF in the status byte is
* read from the device and this loop never exits, the
* device slave select is possibly incorrect such that
* the device status is not being read
*/
if ((FlashStatus[1] & 0x01) == 0) {
break;
}
}
Address += SECTOR_SIZE;
}
}
Flash寫入函數流程
1. 通過qspi接口將寫使能發送給flash;
2. 通過qspi接口將寫命令和需要寫入數據的flash地址以及數據發送到flash;
3. 等待數據傳輸完成;
源碼如下:
void FlashWrite(XQspiPs *QspiPtr, u32 Address, u32 ByteCount, u8 Command)
{
u8 WriteEnableCmd = { WRITE_ENABLE_CMD };
u8 ReadStatusCmd[] = { READ_STATUS_CMD, 0 }; /* must send 2 bytes */
u8 FlashStatus[2];
/*
* Send the write enable command to the FLASH so that it can be
* written to, this needs to be sent as a seperate transfer before
* the write
*/
XQspiPs_PolledTransfer(QspiPtr, &WriteEnableCmd, NULL,
sizeof(WriteEnableCmd));
/*
* Setup the write command with the specified address and data for the
* FLASH
*/
WriteBuffer[COMMAND_OFFSET] = Command;
WriteBuffer[ADDRESS_1_OFFSET] = (u8)((Address & 0xFF0000) >> 16);
WriteBuffer[ADDRESS_2_OFFSET] = (u8)((Address & 0xFF00) >> 8);
WriteBuffer[ADDRESS_3_OFFSET] = (u8)(Address & 0xFF);
/*
* Send the write command, address, and data to the FLASH to be
* written, no receive buffer is specified since there is nothing to
* receive
*/
XQspiPs_PolledTransfer(QspiPtr, WriteBuffer, NULL,
ByteCount + OVERHEAD_SIZE);
/*
* Wait for the write command to the FLASH to be completed, it takes
* some time for the data to be written
*/
while (1) {
/*
* Poll the status register of the FLASH to determine when it
* completes, by sending a read status command and receiving the
* status byte
*/
XQspiPs_PolledTransfer(QspiPtr, ReadStatusCmd, FlashStatus,
sizeof(ReadStatusCmd));
/*
* If the status indicates the write is done, then stop waiting,
* if a value of 0xFF in the status byte is read from the
* device and this loop never exits, the device slave select is
* possibly incorrect such that the device status is not being
* read
*/
if ((FlashStatus[1] & 0x01) == 0) {
break;
}
}
}
Flash讀函數流程
1. 判斷讀指令是普通讀指令還是其他的讀指令;
2. 根據判斷使用對應的讀指令,將對應指令和flash寫入到flash,并根據需要讀多少個數據,寫入對應個無效數據到flash,以獲取flash中對應地址的數據;
函數源碼如下:
void FlashRead(XQspiPs *QspiPtr, u32 Address, u32 ByteCount, u8 Command)
{
/*
* Setup the write command with the specified address and data for the
* FLASH
*/
WriteBuffer[COMMAND_OFFSET] = Command;
WriteBuffer[ADDRESS_1_OFFSET] = (u8)((Address & 0xFF0000) >> 16);
WriteBuffer[ADDRESS_2_OFFSET] = (u8)((Address & 0xFF00) >> 8);
WriteBuffer[ADDRESS_3_OFFSET] = (u8)(Address & 0xFF);
if ((Command == FAST_READ_CMD) || (Command == DUAL_READ_CMD) ||
(Command == QUAD_READ_CMD)) {
ByteCount += DUMMY_SIZE;
}
/*
* Send the read command to the FLASH to read the specified number
* of bytes from the FLASH, send the read command and address and
* receive the specified number of bytes of data in the data buffer
*/
XQspiPs_PolledTransfer(QspiPtr, WriteBuffer, ReadBuffer,
ByteCount + OVERHEAD_SIZE);
}
加載程序源碼
/*
* uart_flash.c
*/
#include "xuartps.h"
#include "xil_types.h"
#include "xparameters.h" /* SDK generated parameters */
#include "xqspips.h" /* QSPI device driver */
/////////////////////////////////////////////////////
#define UART_DEVICE_ID XPAR_PS7_UART_1_DEVICE_ID
#define HEAD_LEN 2
XUartPs Uart_1;
XUartPs *InstancePtr = &Uart_1;
int Data_Len = 0;
int Len_Count = 0;
int Data_Count = 0;
u8 Uart_ReadBuffer[128];
u8 Uart_WriteBuffer[128];
u8 ReadCMD[10];
u8 WriteHeadLen[HEAD_LEN] = {0xcc,0x55};
u8 WriteLenOver[HEAD_LEN] = {0xaa,0x55};
u8 WriteHeadData[HEAD_LEN] = {0xdd,0x55};
u8 WriteDataOver[HEAD_LEN] = {0xbb,0x55};
u8 WritePowerOn[HEAD_LEN] = {0xee,0x55};
u8 Uart_RecvByte(void);
void Uart_SendByte(u8 byte);
int Uart_SendBuffer(u8 *buff,int length);
void Init_Uart(void);
int find_Head(u8 *src,u8 *dst,u8 length);
void delay(u32 count);
#define USER_DDR_BASE_ADDR 0x3e000000
u32 DDR_Base_Addr = USER_DDR_BASE_ADDR;
///////////////////////////////////////////////////////
///////////////////////////////////////////////////////
#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 quadreads */
#define DUMMY_SIZE 1 /* Number of dummy bytes for fast, dual andquad 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
#define SECTOR_SIZE 0x10000
#define NUM_SECTORS 0x100
#define NUM_PAGES 0x10000
#define PAGE_SIZE 256
#define PAGE_COUNT 16
#define TEST_ADDRESS 0x00000000//0x00055000
#define UNIQUE_VALUE 0x05
#define MAX_DATA PAGE_COUNT * PAGE_SIZE
void Init_Qspi(void);
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);
XQspiPs QspiInstance;
unsigned int Flash_Address = 0x000000;
u8 ReadBuffer[MAX_DATA + DATA_OFFSET + DUMMY_SIZE];
u8 WriteBuffer[PAGE_SIZE + DATA_OFFSET];
///////////////////////////////////////////////////////
int main(void)
{
int recv_count = 0,i = 0,j = 0,verify_flag = 0;
u8 tt;
Init_Uart();
Init_Qspi();
// recv start signal
delay(10000);
//1 send power on to pc
Uart_SendBuffer(WritePowerOn,1);
delay(10000);
//recv power on ack
ReadCMD[0] = Uart_RecvByte();
delay(10000);
//2,ack right goto load
if(ReadCMD[0] == 0xab)
{
//3,send get data_len to pc
Uart_SendBuffer(WriteHeadLen,1);
delay(1000);
//4,recv length
while(1)
{
if(Len_Count > 1)
{
//5,send len tran over to pc
Uart_SendBuffer(WriteLenOver,1);
//6,data_len option
Data_Len |= ReadCMD[0] << 8;
Data_Len |= ReadCMD[1];
break;
}
ReadCMD[Len_Count] = Uart_RecvByte();
Len_Count++;
}
//7,sent get data to pc
delay(100000);
while(1)
{
//send over data
if(Data_Count >= Data_Len)
{
// send data over to pc
Uart_SendBuffer(WriteDataOver,1);
break;
}
// send get data to pc
Uart_SendBuffer(WriteHeadData,1);
while(1)
{
//get data to buffer
Uart_ReadBuffer[recv_count] = Uart_RecvByte();
if(recv_count >= 127)
{
break;
}
recv_count++;
}
recv_count = 0;
//write ddr3
for(i = 0,DDR_Base_Addr = USER_DDR_BASE_ADDR + Data_Count * 128;i < 128;i++,DDR_Base_Addr++)
{
*(unsigned int *)DDR_Base_Addr = Uart_ReadBuffer[i];
}
Data_Count++;
}
//flash program
Flash_Address = 0x000000;
DDR_Base_Addr = USER_DDR_BASE_ADDR;
//erase
FlashErase(&QspiInstance,0x000000, Data_Len * 128);
//write flash
for(i = 0;i < (Data_Len * 128 / PAGE_SIZE + 1);i++)
{
for(j = 0;j < PAGE_SIZE;j++)
{
WriteBuffer[j + 4] = *(unsigned int *)(DDR_Base_Addr + PAGE_SIZE * i + j);
}
FlashWrite(&QspiInstance, Flash_Address,PAGE_SIZE,WRITE_CMD);
Flash_Address += PAGE_SIZE;
}
Uart_SendByte(0xaf);
//verify Data
Flash_Address = 0x000000;
DDR_Base_Addr = USER_DDR_BASE_ADDR;
for(i = 0;i < (Data_Len * 128 / PAGE_SIZE + 1);i++)
{
FlashRead(&QspiInstance, Flash_Address,PAGE_SIZE,READ_CMD);
Flash_Address += PAGE_SIZE;
for(j = 0;j < PAGE_SIZE;j++)
{
tt = *(unsigned int *)(DDR_Base_Addr + PAGE_SIZE * i + j);
if(ReadBuffer[j + 4] == tt)
{
verify_flag = 0;
}
else
{
verify_flag = 1;
}
}
}
if(verify_flag == 1)
{
Uart_SendByte(0xcf);
}
else
{
Uart_SendByte(0xef);
}
while(1)
{
}
}
else
{
print("author:660 dz!!/r/n");
print("timer:2019/3/13!!/r/n");
while(1)
{
}
}
return 0;
}
void Init_Uart(void)
{
XUartPs_Config *UartConifgPtr;
s32 temp;
//find device
UartConifgPtr = XUartPs_LookupConfig(XPAR_PS7_UART_1_DEVICE_ID);
//config xuartps data struct
XUartPs_CfgInitialize(&Uart_1,UartConifgPtr, UartConifgPtr->BaseAddress);
//self test
temp = XUartPs_SelfTest(&Uart_1);
if(temp != XST_SUCCESS)
{
return;
}
// XUartPs_SetDataFormat(&Uart_1,XUARTPS_FORMAT_EVEN_PARITY);
//set uart fifo level
XUartPs_SetFifoThreshold(&Uart_1,8);
//uart enable
XUartPs_EnableUart(&Uart_1);
}
u8 Uart_RecvByte(void)
{
u8 byte = 0;
while((((XUartPs_ReadReg(InstancePtr->Config.BaseAddress,XUARTPS_SR_OFFSET)) & 0x02) == 0x02));
byte = XUartPs_ReadReg(InstancePtr->Config.BaseAddress,XUARTPS_FIFO_OFFSET);
return byte;
}
void Uart_SendByte(u8 byte)
{
while((((XUartPs_ReadReg(InstancePtr->Config.BaseAddress,XUARTPS_SR_OFFSET)) & 0x10) == 0x10));
XUartPs_WriteReg(InstancePtr->Config.BaseAddress,XUARTPS_FIFO_OFFSET,byte);
}
int Uart_SendBuffer(u8 *buff,int length)
{
int i = 0;
for(i = 0;i < length;i++)
{
Uart_SendByte(buff[i]);
}
return i;
}
int find_Head(u8 *src,u8 *dst,u8 length)
{
int i = 0,ret = 0;
for(i = 0;i < length - 1;i++)
{
if((src[i] == dst[0]) && (src[i + 1] == dst[1]))
{
ret = 1;
}
}
return ret;
}
void delay(u32 count)
{
unsigned int i = 0;
for(i = 0;i < count;i++)
;
}
void Init_Qspi(void)
{
XQspiPs_Config *QspiConfig;
//find device
QspiConfig = XQspiPs_LookupConfig(XPAR_XQSPIPS_0_DEVICE_ID);
//config XQspiPs data struct QspiInstance
XQspiPs_CfgInitialize(&QspiInstance, QspiConfig,QspiConfig->BaseAddress);
//self test
XQspiPs_SelfTest(&QspiInstance);
//set qspi option
XQspiPs_SetOptions(&QspiInstance,XQSPIPS_MANUAL_START_OPTION |XQSPIPS_FORCE_SSELECT_OPTION |XQSPIPS_HOLD_B_DRIVE_OPTION);
//set qspi clk
XQspiPs_SetClkPrescaler(&QspiInstance, XQSPIPS_CLK_PRESCALE_8);
//set slave select of qspi
XQspiPs_SetSlaveSelect(&QspiInstance);
}
void FlashErase(XQspiPs *QspiPtr, u32 Address, u32 ByteCount)
{
u8 WriteEnableCmd = { WRITE_ENABLE_CMD };
u8 ReadStatusCmd[] = { READ_STATUS_CMD, 0 }; /* must send 2 bytes */
u8 FlashStatus[2];
int Sector;
/*
* If erase size is same as the total size of the flash, use bulk erase
* command
*/
if (ByteCount == (NUM_SECTORS * SECTOR_SIZE)) {
/*
* Send the write enable command to the FLASH so that it can be
* written to, this needs to be sent as a seperate transfer
* before the erase
*/
XQspiPs_PolledTransfer(QspiPtr, &WriteEnableCmd, NULL,
sizeof(WriteEnableCmd));
/*
* Setup the bulk erase command
*/
WriteBuffer[COMMAND_OFFSET] = BULK_ERASE_CMD;
/*
* Send the bulk erase command; no receive buffer is specified
* since there is nothing to receive
*/
XQspiPs_PolledTransfer(QspiPtr, WriteBuffer, NULL,
BULK_ERASE_SIZE);
/*
* Wait for the erase command to the FLASH to be completed
*/
while (1) {
/*
* Poll the status register of the device to determine
* when it completes, by sending a read status command
* and receiving the status byte
*/
XQspiPs_PolledTransfer(QspiPtr, ReadStatusCmd,
FlashStatus,
sizeof(ReadStatusCmd));
/*
* If the status indicates the write is done, then stop
* waiting; if a value of 0xFF in the status byte is
* read from the device and this loop never exits, the
* device slave select is possibly incorrect such that
* the device status is not being read
*/
if ((FlashStatus[1] & 0x01) == 0) {
break;
}
}
return;
}
/*
* If the erase size is less than the total size of the flash, use
* sector erase command
*/
for (Sector = 0; Sector < ((ByteCount / SECTOR_SIZE) + 1); Sector++) {
/*
* Send the write enable command to the SEEPOM so that it can be
* written to, this needs to be sent as a seperate transfer
* before the write
*/
XQspiPs_PolledTransfer(QspiPtr, &WriteEnableCmd, NULL,
sizeof(WriteEnableCmd));
/*
* Setup the write command with the specified address and data
* for the FLASH
*/
WriteBuffer[COMMAND_OFFSET] = SEC_ERASE_CMD;
WriteBuffer[ADDRESS_1_OFFSET] = (u8)(Address >> 16);
WriteBuffer[ADDRESS_2_OFFSET] = (u8)(Address >> 8);
WriteBuffer[ADDRESS_3_OFFSET] = (u8)(Address & 0xFF);
/*
* Send the sector erase command and address; no receive buffer
* is specified since there is nothing to receive
*/
XQspiPs_PolledTransfer(QspiPtr, WriteBuffer, NULL,
SEC_ERASE_SIZE);
/*
* Wait for the sector erse command to the FLASH to be completed
*/
while (1) {
/*
* Poll the status register of the device to determine
* when it completes, by sending a read status command
* and receiving the status byte
*/
XQspiPs_PolledTransfer(QspiPtr, ReadStatusCmd,
FlashStatus,
sizeof(ReadStatusCmd));
/*
* If the status indicates the write is done, then stop
* waiting, if a value of 0xFF in the status byte is
* read from the device and this loop never exits, the
* device slave select is possibly incorrect such that
* the device status is not being read
*/
if ((FlashStatus[1] & 0x01) == 0) {
break;
}
}
Address += SECTOR_SIZE;
}
}
void FlashWrite(XQspiPs *QspiPtr, u32 Address, u32 ByteCount, u8 Command)
{
u8 WriteEnableCmd = { WRITE_ENABLE_CMD };
u8 ReadStatusCmd[] = { READ_STATUS_CMD, 0 }; /* must send 2 bytes */
u8 FlashStatus[2];
/*
* Send the write enable command to the FLASH so that it can be
* written to, this needs to be sent as a seperate transfer before
* the write
*/
XQspiPs_PolledTransfer(QspiPtr, &WriteEnableCmd, NULL,
sizeof(WriteEnableCmd));
/*
* Setup the write command with the specified address and data for the
* FLASH
*/
WriteBuffer[COMMAND_OFFSET] = Command;
WriteBuffer[ADDRESS_1_OFFSET] = (u8)((Address & 0xFF0000) >> 16);
WriteBuffer[ADDRESS_2_OFFSET] = (u8)((Address & 0xFF00) >> 8);
WriteBuffer[ADDRESS_3_OFFSET] = (u8)(Address & 0xFF);
/*
* Send the write command, address, and data to the FLASH to be
* written, no receive buffer is specified since there is nothing to
* receive
*/
XQspiPs_PolledTransfer(QspiPtr, WriteBuffer, NULL,
ByteCount + OVERHEAD_SIZE);
/*
* Wait for the write command to the FLASH to be completed, it takes
* some time for the data to be written
*/
while (1) {
/*
* Poll the status register of the FLASH to determine when it
* completes, by sending a read status command and receiving the
* status byte
*/
XQspiPs_PolledTransfer(QspiPtr, ReadStatusCmd, FlashStatus,
sizeof(ReadStatusCmd));
/*
* If the status indicates the write is done, then stop waiting,
* if a value of 0xFF in the status byte is read from the
* device and this loop never exits, the device slave select is
* possibly incorrect such that the device status is not being
* read
*/
if ((FlashStatus[1] & 0x01) == 0) {
break;
}
}
}
void FlashRead(XQspiPs *QspiPtr, u32 Address, u32 ByteCount, u8 Command)
{
/*
* Setup the write command with the specified address and data for the
* FLASH
*/
WriteBuffer[COMMAND_OFFSET] = Command;
WriteBuffer[ADDRESS_1_OFFSET] = (u8)((Address & 0xFF0000) >> 16);
WriteBuffer[ADDRESS_2_OFFSET] = (u8)((Address & 0xFF00) >> 8);
WriteBuffer[ADDRESS_3_OFFSET] = (u8)(Address & 0xFF);
if ((Command == FAST_READ_CMD) || (Command == DUAL_READ_CMD) ||
(Command == QUAD_READ_CMD)) {
ByteCount += DUMMY_SIZE;
}
/*
* Send the read command to the FLASH to read the specified number
* of bytes from the FLASH, send the read command and address and
* receive the specified number of bytes of data in the data buffer
*/
XQspiPs_PolledTransfer(QspiPtr, WriteBuffer, ReadBuffer,
ByteCount + OVERHEAD_SIZE);
}
int FlashReadID(void)
{
int Status;
/*
* Read ID in Auto mode.
*/
WriteBuffer[COMMAND_OFFSET] = READ_ID;
WriteBuffer[ADDRESS_1_OFFSET] = 0x23; /* 3 dummy bytes */
WriteBuffer[ADDRESS_2_OFFSET] = 0x08;
WriteBuffer[ADDRESS_3_OFFSET] = 0x09;
Status = XQspiPs_PolledTransfer(&QspiInstance, WriteBuffer, ReadBuffer,RD_ID_SIZE);
if (Status != XST_SUCCESS) {
return XST_FAILURE;
}
return XST_SUCCESS;
}
編輯:hfy
-
Zynq
+關注
關注
10文章
609瀏覽量
47175 -
SDK
+關注
關注
3文章
1035瀏覽量
45905
發布評論請先 登錄
相關推薦
評論