Hi Everyone,
I am working on 1050 EVK and using Hyperflash which is the default.
If I run HyperFlash example from the SDK (boards\evkbimxrt1050\driver_examples\flexspi\hyper_flash\polling_transfer),
it works well which is great.
The test sequence is like below;
- Erase Flash
- Erase Sector
- Program the Page using the numbers from 1 to 255.
- Compare the written content with the source.
So, if I put the above sequence into a loop, there is no problem, it works well.
But if I will the input buffer with some magical numbers, for the first time, it works but after the second iteration, the content does not match.
For example, filling the buffer with 0x12345678 (buffer_cast_to_32bit[0] = 0x12345678, buffer_cast_to_32bit[1] = 0x12345678 ...)
If I call "flexspi_nor_hyperflash_cfi(EXAMPLE_FLEXSPI);" function in the loop before erasing the flash, it does not make any difference but if I call the flexspi_hyper_flash_init() in the loop which called for each iteration, I can see the expected values in the flash.
I assume there should be no need to call the flexspi_hyper_flash_init() before each writing operation, or is there any limitation in HyperFlash? I assume If I erase a sector, the second (or others) should not be a problem.
Am I missing something? Or any idea?
Thank you.
Murat
Hello Murat,
Hope you are doing well.
Could you please confirm the board version you are working with(EVK or EVKB) as well as the SDK and IDE version.
Also, I am trying to reproduce this behavior from my end, but could you tell me which buffer you are writing to.
Best Regards,
Sabina
-----------------------------------------------------------------------------------------------------------------------
Note: If this post answers your question, please click the Correct Answer button. Thank you!
-----------------------------------------------------------------------------------------------------------------------
Hi Murat
See the following
https://www.utasker.com/iMX/RT1050.html
I now have a Hyper Flash driver in the uTasker project that allows it to be used for parameter storage and file system storage in addition to code storage.
The SDK examples only show reading and programming a page of data (512 bytes) and don't solve the complexity of writing and reading random data at any address and any length - since the Hyperflash is short word oriented internally this needs to be respected and interface routines must handle things accordingly.
I don't know whether this is your problem but if you load the binary at the link you can play around with reading, writing and deleting data on its command line menu (I/O menu using the commands "sd" to display storage locations and word sizes, "sm" storage modify to modify locations in Hyper Flash, "sf" storage fill for filling areas with data, and "se" storage erase to erase. You can also view the complete 64 MByte Hyper Flash content on the USB interface as a binary file.
These are the read and write interfaces in the uTasker Flash driver showing the concept of use the flash as random byte read/write memory.
switch (ucCommand) {
case READ_DATA_BYTES:
{
unsigned char ulReadBuffer[2];
MAX_FILE_LENGTH LengthToRead;
if (DataLength == 0) {
return;
}
if ((ulPageNumberOffset & 0x1) != 0) { // if reading from an odd address
fnFlexSPI_Command(HYPERFLASH_CMD_LUT_SEQ_IDX_READDATA, 2, ulReadBuffer, 0, (ulPageNumberOffset - 1)); // read two bytes from the even address
*ucData++ = ulReadBuffer[1]; // put the second byte into the user buffer
if (--DataLength == 0) {
return; // single odd address read complete
}
ulPageNumberOffset++;
}
// Reads from here are even address aligned
//
LengthToRead = (DataLength & ~1); // even length to read
DataLength &= 1; // remaining byte
if (LengthToRead != 0) { // if more that a single byte remaining
fnFlexSPI_Command(HYPERFLASH_CMD_LUT_SEQ_IDX_READDATA, LengthToRead, (unsigned char *)ucData, 0, ulPageNumberOffset); // read an even length of bytes
ulPageNumberOffset += LengthToRead;
ucData += LengthToRead;
}
if (DataLength != 0) { // if one additional byte is to be read
fnFlexSPI_Command(HYPERFLASH_CMD_LUT_SEQ_IDX_READDATA, 1, (unsigned char *)ucData, 0, ulPageNumberOffset); // read an even length of bytes
}
return;
}
case PAGE_PROG:
{
unsigned long ulIntermediateBuffer = 0;
unsigned char ucIntemediateWriteBuffer[SPI_FLASH_PAGE_LENGTH];
int iStartIndex = (ulPageNumberOffset % SPI_FLASH_PAGE_LENGTH);
unsigned long ulWriteDataLength = DataLength;
fnFlexSPI_Command((HYPERFLASH_CMD_LUT_SEQ_IDX_WRITEENABLE | WRITEENABLE_SEQUENCE_LENGTH), 0, 0, 0, ulPageNumberOffset);
if ((ulPageNumberOffset & 0x1) != 0) { // first byte write is to an uneven address
ucIntemediateWriteBuffer[iStartIndex - 1] = 0xff; // prime 0xff so that it doesn't change data when programmed
ulPageNumberOffset--; // program to one address lower
ulWriteDataLength++; // program one extra byte
ulIntermediateBuffer = 1; // the intermediate buffer needs to be used
}
if (((ulPageNumberOffset + ulWriteDataLength) & 0x1) != 0) { // final byte write is to an uneven address
ucIntemediateWriteBuffer[iStartIndex + DataLength] = 0xff; // prime 0xff so that it doesn't change data when programmed
ulWriteDataLength++; // program one extra byte
ulIntermediateBuffer |= 2; // the intermediate buffer needs to be used
}
if (ulIntermediateBuffer != 0) {
uMemcpy(&ucIntemediateWriteBuffer[iStartIndex], (const void *)ucData, DataLength); // copy the user data to the intermediate buffer
ucData = &ucIntemediateWriteBuffer[iStartIndex];
if ((ulIntermediateBuffer & 0x1) != 0) {
ucData--;
}
}
fnFlexSPI_Command((HYPERFLASH_CMD_LUT_SEQ_IDX_PAGEPROGRAM | WRITEDATA_SEQUENCE_LENGTH), ulWriteDataLength, 0, (unsigned char *)ucData, ulPageNumberOffset);
}
break;
case BLOCK_ERASE: // block erase - 256k
fnFlexSPI_Command((HYPERFLASH_CMD_LUT_SEQ_IDX_WRITEENABLE | WRITEENABLE_SEQUENCE_LENGTH), 0, 0, 0, ulPageNumberOffset);
fnFlexSPI_Command((HYPERFLASH_CMD_LUT_SEQ_IDX_ERASESECTOR | ERASESECTOR_SEQUENCE_LENGTH), 0, 0, 0, ulPageNumberOffset); // delete block
break;
case READ_JEDEC_ID:
{
unsigned char ucCommand[2] = {0x00, CFI_ENTER};
fnFlexSPI_Command(HYPERFLASH_CMD_LUT_SEQ_IDX_WRITEDATA, sizeof(ucCommand), 0, ucCommand, CFI_COMMAND_ADDRESS); // enter CFI (common flash interface)
fnFlexSPI_Command(HYPERFLASH_CMD_LUT_SEQ_IDX_READDATA, DataLength, (unsigned char *)ucData, 0, 0); // read the ID
ucCommand[1] = RESET_ASO_EXIT;
fnFlexSPI_Command(HYPERFLASH_CMD_LUT_SEQ_IDX_WRITEDATA, sizeof(ucCommand), 0, ucCommand, 0); // exit CFI
}
return;
case READ_STATUS_REGISTER_1:
{
static const unsigned char ucCommand[2] = { 0x00, STATUS_REGISTER_READ };
fnFlexSPI_Command(HYPERFLASH_CMD_LUT_SEQ_IDX_WRITEDATA, sizeof(ucCommand), 0, (unsigned char *)ucCommand, STATUS_REG__COMMAND_ADDRESS); // enter CFI (common flash interface)
fnFlexSPI_Command(HYPERFLASH_CMD_LUT_SEQ_IDX_READDATA, DataLength, (unsigned char *)ucData, 0, 0); // read the status register
}
return;
default:
_EXCEPTION("Unsupported command!");
break;
}
Regards
Mark
[uTasker project developer for Kinetis and i.MX RT]