How to use JFlash

在使用JFlash v3.42b向LPC2214下载固件时遇到问题,设备无法正常启动。升级到JFlash v4.02和v4.08后问题解决。分析发现,在0x00000014地址处缺少32位校验和导致了设备运行状态异常。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

 There is a problem happen when download firmware to the LPC2214 with JFlash v3.42b, the unit will not be turned on when power is on.

But the download will be ok when I use JFlash v4.02 and v4.08, the unit will running normally.

 

I have readout the code in the MCU after each download respectly, a difference was found, the one which can run normally has a 32bits checksum value in the address of 0x00000014, this value affect the running status switch from prog to user app.to see detail please refer to LPC2214 user guide.
this checksum words is not generated when I use v3.42b.Now I am still searching for the reason.

 

 

 

以下是我修改后的代码,依然无法完成向S25FL256SAGNFI000写入数据,帮我检查bug #include "xparameters.h" /* SDK generated parameters */ #include "xqspips.h" /* QSPI device driver */ #include "xil_printf.h" #include "QSPI_flash.h" #include "FIFO.h" #include "G_variable.h" #include "PL_uart.h" #include "UDP_base.h" #include "config_PL.h" #include "sleep.h" /************************** Constant Definitions *****************************/ #define cfg_pkg_len 2000 /* * The following constants map to the XPAR parameters created in the * xparameters.h file. They are defined here such that a user can easily * change all the needed parameters in one place. */ #define QSPI_DEVICE_ID XPAR_XQSPIPS_0_DEVICE_ID /* * The following constants define the commands which may be sent to the FLASH * device. */ #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 WRITE_4B_CMD 0x12 // 新增 4 字节页编程命令 #define SEC_ERASE_4B_CMD 0xDC // 4 字节扇区擦除命令 #define PAGE_SIZE 256 #define DATA_OFFSET 5 /* Start of Data for Read/Write */ #define WRITE_CMD 0x02 #define FLASH_BOOT_BIN_ADDRESS 0x0 /* * The following constants define the offsets within a FlashBuffer data * type for each kind of data. Note that the read data offset is not the * same as the write data because the QSPI driver is designed to allow full * duplex transfers such that the number of bytes received is the number * sent and received. */ #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 ADDRESS_4_OFFSET 4 /* LSB byte of address to read or write */ //#define DATA_OFFSET 5 /* Start of Data for Read/Write */ #define DUMMY_OFFSET 5 /* 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 5 /* Sector Erase command + Sector address */ /* 添加4字节读命令 */ #define QUAD_READ_4B_CMD 0x6C #define FAST_READ_4B_CMD 0x0C /* * The following constants specify the extra bytes which are sent to the * FLASH on the QSPI interface, that are not data, but control information * which includes the command and address */ #define OVERHEAD_SIZE 5 /* * 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 0x200 //256Mb #define NUM_PAGES 0x20000 //256Mb /* Number of flash pages to be written.*/ #define PAGE_COUNT 16 /* Flash address to which data is to be written.*/ #define TEST_ADDRESS (250000000/8)//0x00055000 //4字节BOOT.bin长度,长度不包括头,但包括CRC #define BIN_HEAD_LEN 12 #define BIN_CRC_LEN 4 #define BOOT_BIN_SIZE (1024*1024*15) //8M #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); void FlashQuadEnable(XQspiPs *QspiPtr); int QspiFlashPolledExample(XQspiPs *QspiInstancePtr, u16 QspiDeviceId,u8 write_en,u8 read_en); /************************** 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. */ XQspiPs my_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 flash_WriteBuffer[PAGE_SIZE + OVERHEAD_SIZE]; u8 user_WriteBuffer[(cfg_pkg_len/PAGE_SIZE + 1) * PAGE_SIZE]; u8 *BufferPtr; int8_t DEV_UID[8]; /*****************************************************************************/ /** * * Main function to call the QSPI Flash example. * * * @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(&my_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; // } // 新增函数:启用 4 字节地址模式 void FlashEnter4ByteMode(XQspiPs *QspiPtr) { u8 Enter4ByteModeCmd = 0xB7; // 进入 4 字节地址模式命令 XQspiPs_PolledTransfer(QspiPtr, &Enter4ByteModeCmd, NULL, 1); } void QSPI_flash_write(unsigned char *p,unsigned int len) { int Status; int i; for(i = 0;i < len;i ++) { user_WriteBuffer[i] = p[i]; } Status = QspiFlashPolledExample(&my_QspiInstance, QSPI_DEVICE_ID,1,0); if (Status != XST_SUCCESS) { //xil_printf("QSPI flash write Failed\r\n"); } } void QSPI_flash_read(unsigned char *p,unsigned int len) { int Status; int i; Status = QspiFlashPolledExample(&my_QspiInstance, QSPI_DEVICE_ID,0,1); if (Status != XST_SUCCESS) { //xil_printf("QSPI flash read Failed\r\n"); } else { for(i = 0;i < len;i ++) { p[i] = BufferPtr[i]; } //xil_printf("QSPI flash read successfull\r\n"); } } /*****************************************************************************/ /** * * 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 QspiInstancePtr is a pointer to the QSPIPS driver to use. * @param QspiDeviceId is the XPAR_<QSPIPS_instance>_DEVICE_ID value * from xparameters.h. * * @return XST_SUCCESS if successful, else XST_FAILURE. * * @note None. * *****************************************************************************/ int QspiFlashPolledExample(XQspiPs *QspiInstancePtr, u16 QspiDeviceId,u8 write_en,u8 read_en) { int Status; u8 UniqueValue; int Count; int Page; XQspiPs_Config *QspiConfig; int i; /* Initialize the QSPI driver so that it's ready to use*/ QspiConfig = XQspiPs_LookupConfig(QspiDeviceId); if (QspiConfig == NULL) { 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++) { // flash_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(); FlashEnter4ByteMode(QspiInstancePtr); // 新增:启用 4 字节地址模式 FlashQuadEnable(QspiInstancePtr); if(write_en) { /* Erase the flash.*/ FlashErase(QspiInstancePtr, TEST_ADDRESS, MAX_DATA); for (Page = 0; Page < (cfg_pkg_len + PAGE_SIZE - 1)/PAGE_SIZE; Page++) //PAGE_COUNT { for (Count = 0; Count < PAGE_SIZE; Count++) { if ((DATA_OFFSET + Count) < sizeof(flash_WriteBuffer)) { flash_WriteBuffer[DATA_OFFSET + Count] = user_WriteBuffer[Count + Page*PAGE_SIZE]; } } FlashWrite(QspiInstancePtr, (Page * PAGE_SIZE) + TEST_ADDRESS,PAGE_SIZE, WRITE_CMD); //cfg_pkg_len PAGE_SIZE } } /* * Read the contents of the FLASH from TEST_ADDRESS, using Normal Read * command. Change the prescaler as the READ command operates at a * lower frequency. */ // FlashRead(QspiInstancePtr, TEST_ADDRESS, MAX_DATA, READ_CMD); // // /* // * Setup a pointer to the start of the data that was read into the read // * buffer and verify the data read is the data that was written // */ // BufferPtr = &ReadBuffer[DATA_OFFSET]; // // for (UniqueValue = UNIQUE_VALUE, Count = 0; Count < MAX_DATA; // Count++, UniqueValue++) { // if (BufferPtr[Count] != (u8)(UniqueValue + Test)) { // return XST_FAILURE; // } // } /* * Read the contents of the FLASH from TEST_ADDRESS, using Fast Read * command */ if(read_en) { memset(ReadBuffer, 0x00, sizeof(ReadBuffer)); FlashRead(QspiInstancePtr, TEST_ADDRESS, MAX_DATA, FAST_READ_CMD); /* * Setup a pointer to the start of the data that was read into the read * buffer and verify the data read is the data that was written */ BufferPtr = &ReadBuffer[DATA_OFFSET + DUMMY_SIZE]; } if(write_en && read_en) { for (i = 0; i < cfg_pkg_len; i ++) { if (BufferPtr[i] != user_WriteBuffer[i]) { return XST_FAILURE; } } } // /* // * Read the contents of the FLASH from TEST_ADDRESS, using Dual Read // * command // */ // memset(ReadBuffer, 0x00, sizeof(ReadBuffer)); // FlashRead(QspiInstancePtr, TEST_ADDRESS, MAX_DATA, DUAL_READ_CMD); // // /* // * Setup a pointer to the start of the data that was read into the read // * buffer and verify the data read is the data that was written // */ // BufferPtr = &ReadBuffer[DATA_OFFSET + DUMMY_SIZE]; // // for (UniqueValue = UNIQUE_VALUE, Count = 0; Count < MAX_DATA; // Count++, UniqueValue++) { // if (BufferPtr[Count] != (u8)(UniqueValue + Test)) { // return XST_FAILURE; // } // } // // /* // * Read the contents of the FLASH from TEST_ADDRESS, using Quad Read // * command // */ // memset(ReadBuffer, 0x00, sizeof(ReadBuffer)); // FlashRead(QspiInstancePtr, TEST_ADDRESS, MAX_DATA, QUAD_READ_CMD); // // /* // * Setup a pointer to the start of the data that was read into the read // * buffer and verify the data read is the data that was written // */ // BufferPtr = &ReadBuffer[DATA_OFFSET + DUMMY_SIZE]; // // for (UniqueValue = UNIQUE_VALUE, Count = 0; Count < MAX_DATA; // Count++, UniqueValue++) { // if (BufferPtr[Count] != (u8)(UniqueValue + Test)) { // 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++) { // flash_WriteBuffer[DATA_OFFSET + Count] = (u8)(UniqueValue + Test); // } // memset(ReadBuffer, 0x00, sizeof(ReadBuffer)); // // /* // * Set Auto Start and Manual Chip select options and drive HOLD_B // * pin high. // */ // XQspiPs_SetOptions(QspiInstancePtr, XQSPIPS_FORCE_SSELECT_OPTION | // XQSPIPS_HOLD_B_DRIVE_OPTION); // // /* 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); // } // // /* // * Read the contents of the FLASH from TEST_ADDRESS, using Normal Read // * command. Change the prescaler as the READ command operates at a // * lower frequency. // */ // FlashRead(QspiInstancePtr, TEST_ADDRESS, MAX_DATA, READ_CMD); // // /* // * Setup a pointer to the start of the data that was read into the read // * buffer and verify the data read is the data that was written // */ // BufferPtr = &ReadBuffer[DATA_OFFSET]; // // // for (i = 0; i < cfg_pkg_len; i ++) // { // if (BufferPtr[i] != user_WriteBuffer[i]) // { // return XST_FAILURE; // } // } // /* // * Read the contents of the FLASH from TEST_ADDRESS, using Fast Read // * command // */ // memset(ReadBuffer, 0x00, sizeof(ReadBuffer)); // FlashRead(QspiInstancePtr, TEST_ADDRESS, MAX_DATA, FAST_READ_CMD); // /* // * Setup a pointer to the start of the data that was read into the read // * buffer and verify the data read is the data that was written // */ // BufferPtr = &ReadBuffer[DATA_OFFSET + DUMMY_SIZE]; // for (UniqueValue = UNIQUE_VALUE, Count = 0; Count < MAX_DATA; // Count++, UniqueValue++) { // if (BufferPtr[Count] != (u8)(UniqueValue + Test)) { // return XST_FAILURE; // } // } // /* // * Read the contents of the FLASH from TEST_ADDRESS, using Dual Read // * command // */ // memset(ReadBuffer, 0x00, sizeof(ReadBuffer)); // FlashRead(QspiInstancePtr, TEST_ADDRESS, MAX_DATA, DUAL_READ_CMD); // /* // * Setup a pointer to the start of the data that was read into the read // * buffer and verify the data read is the data that was written // */ // BufferPtr = &ReadBuffer[DATA_OFFSET + DUMMY_SIZE]; // for (UniqueValue = UNIQUE_VALUE, Count = 0; Count < MAX_DATA; // Count++, UniqueValue++) { // if (BufferPtr[Count] != (u8)(UniqueValue + Test)) { // return XST_FAILURE; // } // } // /* // * Read the contents of the FLASH from TEST_ADDRESS, using Quad Read // * command // */ // memset(ReadBuffer, 0x00, sizeof(ReadBuffer)); // FlashRead(QspiInstancePtr, TEST_ADDRESS, MAX_DATA, QUAD_READ_CMD); // /* // * Setup a pointer to the start of the data that was read into the read // * buffer and verify the data read is the data that was written // */ // BufferPtr = &ReadBuffer[DATA_OFFSET + DUMMY_SIZE]; // for (UniqueValue = UNIQUE_VALUE, Count = 0; Count < MAX_DATA; // Count++, UniqueValue++) { // if (BufferPtr[Count] != (u8)(UniqueValue + Test)) { // return XST_FAILURE; // } // } return XST_SUCCESS; } /*****************************************************************************/ /** * * This function writes to the serial FLASH connected to the QSPI interface. * All the data put into the buffer must be in the same page of the device with * page boundaries being on 256 byte boundaries. * * @param QspiPtr is a pointer to the QSPI driver component to use. * @param Address contains the address to write data to in the FLASH. * @param ByteCount contains the number of bytes to write. * @param Command is the command used to write data to the flash. QSPI * device supports only Page Program command to write data to the * flash. * * @return None. * * @note None. * ******************************************************************************/ void FlashWrite(XQspiPs *QspiPtr, u32 Address, u32 ByteCount, u8 Command) { u8 WriteEnableCmd = WRITE_ENABLE_CMD; u8 ReadStatusCmd[] = { READ_STATUS_CMD, 0 }; u8 FlashStatus[2]; // 发送写使能 XQspiPs_PolledTransfer(QspiPtr, &WriteEnableCmd, NULL, sizeof(WriteEnableCmd)); // 选择正确的写命令 (4字节/3字节) u8 actualCommand = (Address > 0xFFFFFF) ? WRITE_4B_CMD : Command; // 填充命令和地址 flash_WriteBuffer[COMMAND_OFFSET] = actualCommand; flash_WriteBuffer[ADDRESS_1_OFFSET] = (u8)((Address >> 24) & 0xFF); flash_WriteBuffer[ADDRESS_2_OFFSET] = (u8)((Address >> 16) & 0xFF); flash_WriteBuffer[ADDRESS_3_OFFSET] = (u8)((Address >> 8) & 0xFF); flash_WriteBuffer[ADDRESS_4_OFFSET] = (u8)(Address & 0xFF); // 计算实际传输长度 u32 headerSize = (actualCommand == WRITE_4B_CMD) ? 5 : 4; u32 TransferLength = headerSize + ByteCount; // 确保不超出缓冲区大小 if (TransferLength > sizeof(flash_WriteBuffer)) { TransferLength = sizeof(flash_WriteBuffer); } // 执行传输 XQspiPs_PolledTransfer(QspiPtr, flash_WriteBuffer, NULL, TransferLength); // 等待写入完成 do { XQspiPs_PolledTransfer(QspiPtr, ReadStatusCmd, FlashStatus, sizeof(ReadStatusCmd)); } while (FlashStatus[1] & 0x01); // 检查 BUSY 位 } /*****************************************************************************/ /** * * This function reads from the serial FLASH connected to the * QSPI interface. * * @param QspiPtr is a pointer to the QSPI driver component to use. * @param Address contains the address to read data from in the FLASH. * @param ByteCount contains the number of bytes to read. * @param Command is the command used to read data from the flash. QSPI * device supports one of the Read, Fast Read, Dual Read and Fast * Read commands to read data from the flash. * * @return None. * * @note None. * ******************************************************************************/ void FlashRead(XQspiPs *QspiPtr, u32 Address, u32 ByteCount, u8 Command) { // 添加命令转换逻辑 u8 actualCommand = Command; // 添加对所有读命令的转换 switch(Command) { case FAST_READ_CMD: actualCommand = FAST_READ_4B_CMD; break; case QUAD_READ_CMD: actualCommand = QUAD_READ_4B_CMD; break; case DUAL_READ_CMD: actualCommand = DUAL_READ_CMD; break; // 没有4B版本 case READ_CMD: actualCommand = READ_CMD; break; // 没有4B版本 default: actualCommand = Command; break; } /* * Setup the write command with the specified address and data for the * FLASH */ flash_WriteBuffer[COMMAND_OFFSET] = actualCommand; /* flash_WriteBuffer[ADDRESS_1_OFFSET] = (u8)((Address & 0xFF0000) >> 16); flash_WriteBuffer[ADDRESS_2_OFFSET] = (u8)((Address & 0xFF00) >> 8); flash_WriteBuffer[ADDRESS_3_OFFSET] = (u8)(Address & 0xFF); */ flash_WriteBuffer[ADDRESS_1_OFFSET] = (u8)((Address & 0xFF000000) >> 24); // 新增 flash_WriteBuffer[ADDRESS_2_OFFSET] = (u8)((Address & 0xFF0000) >> 16); flash_WriteBuffer[ADDRESS_3_OFFSET] = (u8)((Address & 0xFF00) >> 8); flash_WriteBuffer[ADDRESS_4_OFFSET] = (u8)(Address & 0xFF); // 修改 // 设置虚拟字节大小 u32 DummyBytes = 0; if (actualCommand == FAST_READ_4B_CMD || actualCommand == QUAD_READ_4B_CMD) { DummyBytes = DUMMY_SIZE; flash_WriteBuffer[DUMMY_OFFSET] = 0x00; // 必须设置虚拟字节值 } // 计算总传输长度 u32 TransferLength = OVERHEAD_SIZE + ByteCount + DummyBytes; // 确保不超出缓冲区大小 if (TransferLength > sizeof(ReadBuffer)) { TransferLength = sizeof(ReadBuffer); } /* * 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, flash_WriteBuffer, ReadBuffer,TransferLength); } /*****************************************************************************/ /** * * This function erases the sectors in the serial FLASH connected to the * QSPI interface. * * @param QspiPtr is a pointer to the QSPI driver component to use. * @param Address contains the address of the first sector which needs to * be erased. * @param ByteCount contains the total size to be erased. * * @return None. * * @note None. * ******************************************************************************/ 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 separate transfer * before the erase */ XQspiPs_PolledTransfer(QspiPtr, &WriteEnableCmd, NULL, sizeof(WriteEnableCmd)); /* Setup the bulk erase command*/ flash_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, flash_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 */ //FlashStatus[1] |= FlashStatus[0]; 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 separate transfer * before the write */ XQspiPs_PolledTransfer(QspiPtr, &WriteEnableCmd, NULL, sizeof(WriteEnableCmd)); /* * Setup the write command with the specified address and data * for the FLASH */ // 根据地址选择命令 u8 eraseCmd = (Address > 0xFFFFFF) ? SEC_ERASE_4B_CMD : SEC_ERASE_CMD; flash_WriteBuffer[COMMAND_OFFSET] = eraseCmd; //flash_WriteBuffer[COMMAND_OFFSET] = SEC_ERASE_CMD; /* flash_WriteBuffer[ADDRESS_1_OFFSET] = (u8)(Address >> 16); flash_WriteBuffer[ADDRESS_2_OFFSET] = (u8)(Address >> 8); flash_WriteBuffer[ADDRESS_3_OFFSET] = (u8)(Address & 0xFF); */ flash_WriteBuffer[ADDRESS_1_OFFSET] = (u8)((Address & 0xFF000000) >> 24); flash_WriteBuffer[ADDRESS_2_OFFSET] = (u8)((Address & 0xFF0000) >> 16); flash_WriteBuffer[ADDRESS_3_OFFSET] = (u8)((Address & 0xFF00) >> 8); flash_WriteBuffer[ADDRESS_4_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, flash_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 */ //FlashStatus[1] |= FlashStatus[0]; if ((FlashStatus[0] & 0x01) == 0) { break; } } Address += SECTOR_SIZE; } } /*****************************************************************************/ /** * * This function reads serial FLASH ID connected to the SPI interface. * * * @return XST_SUCCESS if read id, otherwise XST_FAILURE. * * @note None. * ******************************************************************************/ int FlashReadID(void) { int Status; // 正确的退出 4 字节模式命令 u8 Exit4ByteModeCmd = 0xE9; // 根据 S25FL256S 数据手册 XQspiPs_PolledTransfer(&my_QspiInstance, &Exit4ByteModeCmd, NULL, 1); /* Read ID in Auto mode.*/ flash_WriteBuffer[COMMAND_OFFSET] = READ_ID; flash_WriteBuffer[ADDRESS_1_OFFSET] = 0x23; /* 3 dummy bytes */ flash_WriteBuffer[ADDRESS_2_OFFSET] = 0x08; flash_WriteBuffer[ADDRESS_3_OFFSET] = 0x09; Status = XQspiPs_PolledTransfer(&my_QspiInstance, flash_WriteBuffer, ReadBuffer, RD_ID_SIZE); if (Status != XST_SUCCESS) { return XST_FAILURE; } //xil_printf("FlashID=0x%x 0x%x 0x%x\n\r", ReadBuffer[1], ReadBuffer[2], // ReadBuffer[3]); // 重新进入4字节模式 FlashEnter4ByteMode(&my_QspiInstance); return XST_SUCCESS; } /* int FlashReadUID(void) { int Status; flash_WriteBuffer[COMMAND_OFFSET] = 0x4B; flash_WriteBuffer[ADDRESS_1_OFFSET] = 0x23; flash_WriteBuffer[ADDRESS_2_OFFSET] = 0x08; flash_WriteBuffer[ADDRESS_3_OFFSET] = 0x09; Status = XQspiPs_PolledTransfer(&my_QspiInstance,flash_WriteBuffer, ReadBuffer, 16); if (Status != XST_SUCCESS) { return XST_FAILURE; } DEV_UID[0] = ReadBuffer[5]; DEV_UID[1] = ReadBuffer[6]; DEV_UID[2] = ReadBuffer[7]; DEV_UID[3] = ReadBuffer[8]; DEV_UID[4] = ReadBuffer[9]; DEV_UID[5] = ReadBuffer[10]; DEV_UID[6] = ReadBuffer[11]; DEV_UID[7] = ReadBuffer[12]; //xil_printf("Flash Unique ID=0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x\n\r",ReadBuffer[5], ReadBuffer[6], ReadBuffer[7], ReadBuffer[8], ReadBuffer[9], ReadBuffer[10], ReadBuffer[11], ReadBuffer[12]); return XST_SUCCESS; } */ int FlashReadUID(void) { int Status; u8 cmdBuffer[5] = {0x4B, 0x00, 0x00, 0x00, 0x00}; // 命令 + 4字节地址 u8 response[13]; // 接收缓冲区 // 保存当前地址模式 u8 Exit4ByteModeCmd = 0xE9; XQspiPs_PolledTransfer(&my_QspiInstance, &Exit4ByteModeCmd, NULL, 1); // 发送读取UID命令 Status = XQspiPs_PolledTransfer(&my_QspiInstance, cmdBuffer, response, sizeof(cmdBuffer)); // 恢复4字节模式 u8 Enter4ByteModeCmd = 0xB7; XQspiPs_PolledTransfer(&my_QspiInstance, &Enter4ByteModeCmd, NULL, 1); if (Status != XST_SUCCESS) { //xil_printf("FlashReadUID: Transfer failed with status %d\r\n", Status); return XST_FAILURE; } // 验证响应(可选) if(response[0] != 0x4B) { //xil_printf("FlashReadUID: Invalid response header\r\n"); return XST_FAILURE; } // 提取唯一ID(字节5-12) for(int i=0; i<8; i++) { DEV_UID[i] = response[i+5]; } return XST_SUCCESS; } /*****************************************************************************/ /** * * This function enables quad mode in the serial flash connected to the * SPI interface. * * @param QspiPtr is a pointer to the QSPI driver component to use. * * @return None. * * @note None. * ******************************************************************************/ void FlashQuadEnable(XQspiPs *QspiPtr) { u8 WriteEnableCmd = WRITE_ENABLE_CMD; u8 ReadStatusCmd1[] = {0x05, 0}; // 读状态寄存器1 u8 ReadStatusCmd2[] = {0x35, 0}; // 读状态寄存器2 u8 WriteStatusCmd[] = {0x01, 0x00, 0x02}; // 写状态寄存器 (直接设置 QE 位) u8 FlashStatus[2]; // 读取状态寄存器2 XQspiPs_PolledTransfer(QspiPtr, ReadStatusCmd2, FlashStatus, sizeof(ReadStatusCmd2)); // 检查QE位(bit1)是否已设置 if ((FlashStatus[1] & 0x02) == 0) { // 修正索引为 [1] // 发送写使能 XQspiPs_PolledTransfer(QspiPtr, &WriteEnableCmd, NULL, sizeof(WriteEnableCmd)); // 直接设置 QE 位 (bit1) WriteStatusCmd[2] = 0x02; // 状态寄存器2的QE位 // 写入状态寄存器 XQspiPs_PolledTransfer(QspiPtr, WriteStatusCmd, NULL, sizeof(WriteStatusCmd)); // 增加延迟确保写入完成 usleep(50000); // 50ms 延迟 // 等待写入完成 do { XQspiPs_PolledTransfer(QspiPtr, ReadStatusCmd1, FlashStatus, sizeof(ReadStatusCmd1)); } while (FlashStatus[1] & 0x01); // 检查 BUSY 位 } }
最新发布
07-23
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值