[SOLVED] Swap word order on SPI XiP flash

This site uses cookies. By continuing to browse this site, you are agreeing to our Cookie Policy.

  • [SOLVED] Swap word order on SPI XiP flash

    When programming QSPI serial flash, the word order is swapped, and execution fails (core hardfault).

    The device is an NXP Kinetis K8x (K81/K81 family) MCU part, with a Micron or Cypress 128Mb serial QSPI flash part. The MCU has a QSPI peripheral with XiP capability, for which the default configuration is 64-bit Little-endian. When using the external flash as a data device, the 32-bit word order is consistent and correct. However, when using the external flash for executable code, the word order of the instructions is swapped.

    Expected
    ADDR 0004 [byte7][byte6][byte5][byte4]
    ADDR 0000 [byte3][byte2]byte1][byte0]

    Loaded:
    ADDR 0004 [byte3][byte2]byte1][byte0]
    ADDR 0000 [byte7][byte6][byte5][byte4]

    Now, if I set the QSPI peripheral at 32-bit Little endian, the the J-Link programmed code runs. However, data reads now have the each 32-bit word pair swapped.

    Sanity check: I manually swapped the word order of the external function in the Intel Hex file, and then programmed the flash, and everything ran perfectly. (Note that I did not touch the word order of code targeted at the main, internal flash)

    What's going on here? Can the J-Link be set to swap words? Should I be looking at the GNU compiler/linker/objcopy to fix this? Any ideas are welcome.
  • Hello,

    Thank you for your inquiry.
    Such an issue is not known to us.
    J-Link will store data exactly as specified in your binary or hex you are trying to program.
    Is the data also swapped in the binary/hex that gets output by your Toolchain?
    Which target device are you trying to debug exactly?
    Is it on an eval board or custom hardware?

    Best regards,
    Nino
    Please read the forum rules before posting.

    Keep in mind, this is *not* a support forum.
    Our engineers will try to answer your questions between their projects if possible but this can be delayed by longer periods of time.
    Should you be entitled to support you can contact us via our support system: segger.com/ticket/

    Or you can contact us via e-mail.
  • Hi Nino,

    It appears that the data is stored exactly as specified in the ihex file, and is not swapped in the toolchain. I appears that the problem occurs with direct memory-mapped reads: pairs of 32-bit words are swapped between reading from flash, and their arrival in the instruction queue. I have tried this on both my custom board (NXP MK81), and an eval board (NXP FRDM-K82F). NXP are investigating: I will let you know what they find.

    Kind regards,
    Denis
  • In the meantime I am trying to find a solution using a JLink Script, triggered from the GDB. The script runs but does not change the register as expected.

    C Source Code

    1. /*********************************************************************
    2. *
    3. * InitTarget
    4. */
    5. int HandleBeforeFlashProg(void) {
    6. U32 QSPI_MCR_BASE;
    7. U32 QSPI_MCR_DATA;
    8. U32 QSPI_MCR_64LE;
    9. int r;
    10. Report("J-Link script: NXP_MK8x_QSPI.JLinkScript");
    11. QSPI_MCR_BASE = 0x400DA000; // Address of QuadSPI0_MCR Register on K8x MCU
    12. QSPI_MCR_64LE = 0x0000000C; // 64LE: bits[3:2] = 3
    13. QSPI_MCR_DATA = JLINK_MEM_ReadU32(QSPI_MCR_BASE);
    14. JLINK_SYS_Report1("J-Link script: Reading QSPI->MCR: ", QSPI_MCR_DATA);
    15. QSPI_MCR_DATA = QSPI_MCR_DATA | QSPI_MCR_64LE;
    16. JLINK_SYS_Report1("J-Link script: Writing QSPI->MCR: ", QSPI_MCR_DATA);
    17. r = JLINK_MEM_WriteU32(QSPI_MCR_BASE, QSPI_MCR_DATA);
    18. if (r <0) {
    19. JLINK_SYS_Report("J-Link script: !!Unable to set QuadSPI_MCR to 64bit Little-endian!!");
    20. }
    21. else {
    22. JLINK_SYS_Report("J-Link script: QuadSPI_MCR set to 64bit Little-endian");
    23. }
    24. return r;
    25. }
    Display All

    output:
    ...
    Verify method "Programmed sectors, fastest method" is not supported for this device.
    Changed to "Programmed sectors using read back"
    J-Link script: NXP_MK8x_QSPI.JLinkScript
    J-Link script: Reading QSPI->MCR: 0xFFFFFFFF <<< This is not correct - looks like the register read failed
    J-Link script: Writing QSPI->MCR: 0xFFFFFFFF
    J-Link script: QuadSPI_MCR set to 64bit Little-endian
    J-Link: Flash download: Bank 0 @ 0x00000000
    J-Link: Flash download: Bank 1 @ 0x68000000
  • Hello,

    we received your inquiry per e-mail as well.
    To make sure that no information gets lost between different communication channels this thread will be closed now.

    EDIT: Additional information regarding this topic. The Flash loader programs the Flash in 32-bit LE mode.
    However NXP drivers assume 64-bit LE mode.
    Quote from Denis:
    "This is not a problem if the flash is exclusively dedicated for data storage (64LE), or XiP code (32LE). But it becomes an issue when the flash is used for both, simultaneously. For this to work correctly, changes must be made to the NXP QSPI driver code (fsl_qspi) so that it is endian-aware."

    Best regards,
    Nino
    Please read the forum rules before posting.

    Keep in mind, this is *not* a support forum.
    Our engineers will try to answer your questions between their projects if possible but this can be delayed by longer periods of time.
    Should you be entitled to support you can contact us via our support system: segger.com/ticket/

    Or you can contact us via e-mail.