Data corruption with imx6ull qspi peripheral

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

Data corruption with imx6ull qspi peripheral

Jump to solution
970 Views
kevincronn
Contributor III

I am seeing data corruption when using the imx6ull qspi peripheral. I have put prints in after filling the TX FIFO and the prints show the data going into the FIFO is correct but it comes out of the chip onto the qspi bus wrong. Here is an example, the bold data is incorrect (this is a baremetal project):

FC 4F 02 00 FD 4F 02 00 FE 4F 02 00 FF 4F 02 00

00 50 02 00 01 50 02 00 02 50 02 00 03 50 02 00

04 50 02 00 05 50 02 00 06 50 02 00 07 50 02 00

08 50 02 00 09 50 02 00 0A 50 02 00 0B 50 02 00

0C 50 02 00 0D 50 02 00 0E 50 02 00 0F 50 02 00

10 50 02 00 11 50 02 00 12 50 02 00 13 50 02 00

14 50 02 00 15 50 02 00 16 50 02 00 17 50 02 00

18 50 02 00 19 50 02 00 1A 50 02 00 1B 50 02 00

1C 50 02 00 1D 50 02 00 1E 50 02 00 1F 50 02 00

20 50 02 00 21 50 02 00 22 50 02 00 23 50 02 00

00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00

FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF

FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF 

FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF 

FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF 

FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF 

FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF

40 50 02 00 41 50 02 00 42 50 02 00 43 50 02 00

44 50 02 00 45 50 02 00 46 50 02 00 47 50 02 00

48 50 02 00 49 50 02 00 4A 50 02 00 4B 50 02 00

4C 50 02 00 4D 50 02 00 4E 50 02 00 4F 50 02 00

50 50 02 00 51 50 02 00 52 50 02 00 53 50 02 00

54 50 02 00 55 50 02 00 56 50 02 00 57 50 02 00

58 50 02 00 59 50 02 00 5A 50 02 00 5B 50 02 00

5C 50 02 00 5D 50 02 00 5E 50 02 00 5F 50 02 00

It should have been this:

24 50 02 00 25 50 02 00 26 50 02 00 27 50 02 00

28 50 02 00 29 50 02 00 2A 50 02 00 2B 50 02 00

2C 50 02 00 2D 50 02 00 2E 50 02 00 2F 50 02 00

30 50 02 00 31 50 02 00 32 50 02 00 33 50 02 00

34 50 02 00 35 50 02 00 36 50 02 00 37 50 02 00

38 50 02 00 39 50 02 00 3A 50 02 00 3B 50 02 00

3C 50 02 00 3D 50 02 00 3E 50 02 00 3F 50 02 00

Here is my code to write to the qspi peripheral:

void QSPI_Write(QuadSPI_Type *base, uint32_t *buffer, size_t size)
{
    uint32_t i = 0;
    for (i = 0; i < size / 4U; i++)
    {
    /* Check if the buffer is full */
    while (QuadSPI->SR & QuadSPI_SR_TXFULL_MASK)
    {
    }

    base->TBDR = *buffer;
    buffer++;
    }
}

void programQspiFlash(uint32_t addr, uint32_t *src_addr)
{

    while (QuadSPI->SR & QuadSPI_SR_BUSY_MASK)
    {
    }
    // clear FIFO
    QuadSPI->MCR |= QuadSPI_MCR_CLR_TXF_MASK;


    // Set IP Command Address
    QuadSPI->SFAR = addr;


    // cmd write enable
   while (QuadSPI->SR & QuadSPI_SR_BUSY_MASK & QuadSPI_SR_BUSY_MASK)
   {
   }
   while (QuadSPI->SR & QuadSPI_SR_BUSY_MASK & (QuadSPI_SR_BUSY_MASK |       QuadSPI_SR_IP_ACC_MASK))
    {
    }
    QuadSPI->SPTRCLR = QuadSPI_SPTRCLR_IPPTRC_MASK;


   // Write the seqid bit
   QuadSPI->IPCR = ((QuadSPI->IPCR & (~QuadSPI_IPCR_SEQID_MASK)) | QuadSPI_IPCR_SEQID(1));
   // end cmd write enable 

    while (QuadSPI->SR & QuadSPI_SR_BUSY_MASK)
    {
    }

    QuadSPI->SPTRCLR = QuadSPI_SPTRCLR_IPPTRC_MASK;

    // First write some data into TXFIFO to prevent from under run
   QSPI_Write(QuadSPI, src_addr, 128);
    src_addr += 32;

    // Start the program
   QuadSPI->IPCR = ((QuadSPI->IPCR & (~QuadSPI_IPCR_IDATSZ_MASK)) |     QuadSPI_IPCR_IDATSZ(FLASH_PAGE_SIZE));

   while (QuadSPI->SR & (QuadSPI_SR_BUSY_MASK | QuadSPI_SR_IP_ACC_MASK))
    {
    }
    QuadSPI->SPTRCLR = QuadSPI_SPTRCLR_IPPTRC_MASK;

    // Write the seqid bit
    QuadSPI->IPCR = ((QuadSPI->IPCR & (~QuadSPI_IPCR_SEQID_MASK)) | QuadSPI_IPCR_SEQID(4U));
QSPI_Write(QuadSPI, src_addr, 128);
src_addr += 32;

// Wait until flash finished program
uint32_t val = 0;
do
{
while (QuadSPI->SR & QuadSPI_SR_BUSY_MASK)
{
}

// Clear FIFO
QuadSPI->MCR |= QuadSPI_MCR_CLR_RXF_MASK;
// Clear command sequence.
QuadSPI->SPTRCLR = QuadSPI_SPTRCLR_IPPTRC_MASK;
// Write the seqid bit
QuadSPI->IPCR = ((QuadSPI->IPCR & (~QuadSPI_IPCR_SEQID_MASK)) | QuadSPI_IPCR_SEQID(3U));
while (QuadSPI->SR & QuadSPI_SR_BUSY_MASK)
{
}
val = *(volatile uint32_t *)(FSL_FEATURE_QSPI_ARDB_BASE);
// Clear ARDB area
QuadSPI->FR = QuadSPI_FR_RBDF_MASK;
} while (val & 0x1);


while (QuadSPI->SR & (QuadSPI_SR_BUSY_MASK | QuadSPI_SR_IP_ACC_MASK))
{
}

// Do a software reset of the qspi peripheral
// Reset AHB domain and buffer domian
QuadSPI->MCR |= (QuadSPI_MCR_SWRSTHD_MASK | QuadSPI_MCR_SWRSTSD_MASK);

// Wait for the reset to finish
int i = 0;
for (i = 0; i < 100; i++)
{
__ASM("nop");
}

// Disable QSPI module
QuadSPI->MCR |= QuadSPI_MCR_MDIS_MASK;

// Clear the reset flags
QuadSPI->MCR &= ~(QuadSPI_MCR_SWRSTHD_MASK | QuadSPI_MCR_SWRSTSD_MASK);

// Enable QSPI module
QuadSPI->MCR &= ~QuadSPI_MCR_MDIS_MASK;

}

I am at a loss to explain the data corruption, has anyone seen this before or have any ideas to the issue?

Labels (1)
Tags (1)
0 Kudos
1 Solution
821 Views
kevincronn
Contributor III

If I disable all interrupts before programming the flash I never see any corruption. Is it recommended to disable interrupts before programming qspi with the imx6ull? I haven't found anything in the reference manual to that effect but somehow interrupts are causing corruption in my application.

View solution in original post

0 Kudos
3 Replies
822 Views
kevincronn
Contributor III

If I disable all interrupts before programming the flash I never see any corruption. Is it recommended to disable interrupts before programming qspi with the imx6ull? I haven't found anything in the reference manual to that effect but somehow interrupts are causing corruption in my application.

0 Kudos
821 Views
igorpadykov
NXP Employee
NXP Employee

inrerrupts may affect timings, as processor spends some time processing them.

In general qspi with interrupts working fine in nxp linux bsps on

linux-imx - i.MX Linux kernel 
Linux  Documentation
i.MX Software | NXP 

Best regards
igor

0 Kudos
821 Views
igorpadykov
NXP Employee
NXP Employee

Hi Kevin

data corruption can be caused by timings and signal noise, one can check them

with oscilloscope, use that qspi datasheet timings and sect.4.12.10 QUAD SPI (QSPI) Timing

Parameters i.MX6ULL Datasheet
https://www.nxp.com/docs/en/data-sheet/IMX6ULLCEC.pdf

Best regards
igor
-----------------------------------------------------------------------------------------------------------------------
Note: If this post answers your question, please click the Correct Answer button. Thank you!
-----------------------------------------------------------------------------------------------------------------------

0 Kudos