QuadSPI AHB not reading correctly after erasing a sector

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

QuadSPI AHB not reading correctly after erasing a sector

1,436 Views
martir
Contributor III

Hi there,

I'm using a MKL82Z on a custom board with Cypress S25FL256S (http://www.cypress.com/file/177966/download ) external memory. I'm using SDK SDK_2.2_MKL82Z128xxx7, with a little modification of the LUT for the memory mentioned.

The thing is I'm observing a weird behavior when I watch the external memory with the memory browser (or also when I consult its content via an USB driver that I developed).

I have a similar program as below (let's say number in paranthesis are the line numbers):

int main(){
(1)Initializations(); //<-- clock, module initializations, etc

(2)Save_4Bytes_to_external_memory();   //I save 4 bytes to position 0x6810 0000
(3)Erase_sector( 0x6810 0000 );            //Erase the sector where the address is contained

(4)Create_Tasks();
(5)StartScheduler();
while(1);
}

With the memory browser window open, I'm using breakpoints at line (2). So, when the breakpoint is at (2) and I execute Step Over, I see in the memory browser how the 4 bytes are saved. Then I pulse again a Step Over on the line (3) and sometimes you can see the flash all going to FF's (how it's expected) but most of times it just does nothing. When it's just does nothing then I run the program, I pause it and the memory is still with the 4 bytes.

Also, instead of running if I reset the program and execute again without execute Save_4Bytes(), memory is full of FF's, as if previous erase_sector was done ok but it hadn't shown in the memory browser. (that's why my suspicion about AHB).

Also I've observed that if I don't use any breakpoint and then I pause the program, the memory is full FF's as if the erase_sector is executing correctly.

Also tried not to use the debugger, and consult the memory content via an USB API. With this API, I erase the sector and then read the memory and most of the times it reads the 4 bytes (the erase_sector didn't do anything).

So what's going on? Is AHB not working? Am I missing something to configure in the external memory?

Any advice will be much apreciated. Thanks.

PD: I don't know if I've explained myself enough, it's a bit twisted to explain and my english isn't perfect so let me know and I'll try to explain better ... >_<'

I put my LUT table here, maybe there's something wrong:

/* Seq0 :Quad Read */
 /* CMD: 0xEB - Quad Read, Single pad */
 /* ADDR: 0x18 - 24bit address, Quad pads */
 /* DUMMY: 0x06 - 6 clock cyles, Quad pads */
 /* READ: 0x80 - Read 128 bytes, Quad pads */
 /* JUMP_ON_CS: 0 */
[0] = QSPI_LUT_SEQ(QSPI_CMD, QSPI_PAD_1, 0xEB, QSPI_ADDR, QSPI_PAD_4, 0x18),
[1] = QSPI_LUT_SEQ(QSPI_DUMMY, QSPI_PAD_4, 0x06, QSPI_READ, QSPI_PAD_4, 0x80), 
[2] = QSPI_LUT_SEQ(QSPI_JMP_ON_CS, QSPI_PAD_1, 0x0, 0, 0, 0),

/* this this one but same behavior  */
//[0] = QSPI_LUT_SEQ(QSPI_CMD, QSPI_PAD_1, 0xEB, QSPI_ADDR, QSPI_PAD_4, 0x18),
//[1] = QSPI_LUT_SEQ(QSPI_MODE4, QSPI_PAD_4, 0x00, QSPI_DUMMY, QSPI_PAD_4, 0x05),
//[2] = QSPI_LUT_SEQ(QSPI_READ, QSPI_PAD_4, 0x80, QSPI_JMP_ON_CS, QSPI_PAD_1, 0x00),

/* Seq1: Write Enable */
 /* CMD: 0x06 - Write Enable, Single pad */
 [4] = QSPI_LUT_SEQ(QSPI_CMD, QSPI_PAD_1, 0x06, 0, 0, 0),

/* Seq2: Erase All */
 /* CMD: 0x60 - Erase All chip, Single pad */
 [8] = QSPI_LUT_SEQ(QSPI_CMD, QSPI_PAD_1, 0x60, 0, 0, 0),

/* Seq3: Read Status */
 /* CMD: 0x05 - Read Status, single pad */
 /* READ: 0x01 - Read 1 byte */
 [12] = QSPI_LUT_SEQ(QSPI_CMD, QSPI_PAD_1, 0x05, QSPI_READ, QSPI_PAD_1, 0x1),

/* Seq4: Page Program */
 /* CMD: 0x02 - Page Program, Single pad */
 /* ADDR: 0x18 - 24bit address, Single pad */
 /* WRITE: 0x80 - Write 128 bytes at one pass, Single pad */
 [16] = QSPI_LUT_SEQ(QSPI_CMD, QSPI_PAD_1, 0x02, QSPI_ADDR, QSPI_PAD_1, 0x18),
 [17] = QSPI_LUT_SEQ(QSPI_WRITE, QSPI_PAD_1, 0x01, 0, 0, 0),
 // [17] Modified according to https://community.nxp.com/message/962630?commentID=962630&et=watches.email.thread#comment-962630
 // Original: [17] = QSPI_LUT_SEQ(QSPI_WRITE, QSPI_PAD_1, 0x80, 0, 0, 0),

/* Seq5: Write Register */
 /* CMD: 0x01 - Write Status Register, single pad */
 /* WRITE: 0x01 - Write 1 byte of data, single pad */
#ifdef MACRONIX_MX25L
 [20] = QSPI_LUT_SEQ(QSPI_CMD, QSPI_PAD_1, 0x01, QSPI_WRITE, QSPI_PAD_1, 0x1), // FRDM-KL82Z
#endif
#ifdef CYPRESS_S25FL
 [20] = QSPI_LUT_SEQ(QSPI_CMD, QSPI_PAD_1, 0x01, QSPI_WRITE, QSPI_PAD_1, 0x2), // CYPRESS
#endif

/* Seq6: Read Config Register */
 /* CMD: 0x15 - Read Config register, single pad */
 /* READ: 0x01 - Read 1 byte */
#ifdef MACRONIX_MX25L
 [24] = QSPI_LUT_SEQ(QSPI_CMD, QSPI_PAD_1, 0x15, QSPI_READ, QSPI_PAD_1, 0x1), // FRDM-KL82Z
#endif
#ifdef CYPRESS_S25FL
 [24] = QSPI_LUT_SEQ(QSPI_CMD, QSPI_PAD_1, 0x35, QSPI_READ, QSPI_PAD_1, 0x1), // CPYRESS
#endif

/* Seq7: Erase Sector */
 /* CMD: 0x20 - Sector Erase, single pad */
 /* ADDR: 0x18 - 24 bit address, single pad */
 // For 64 kB sectors erase on CYPRESS flash please see [40] below
//#ifdef MACRONIX_MX25L
 [28] = QSPI_LUT_SEQ(QSPI_CMD, QSPI_PAD_1, 0x20, QSPI_ADDR, QSPI_PAD_1, 0x18), // FRDM-KL82Z
 /*#endif
 #ifdef CYPRESS_S25FL
 // Hybrid sectors of 4kb and 64kb, command 0x20 is for 4kb and command 0xd8 is for 64kb
 // [28] erases 4 kB sectors, [40] erases 64 kB sectors
 [28] = QSPI_LUT_SEQ(QSPI_CMD, QSPI_PAD_1, 0x20, QSPI_ADDR, QSPI_PAD_1, 0x18), // CYPRESS
 #endif
 */

/* READ ID*/
 [32] = QSPI_LUT_SEQ(QSPI_CMD, QSPI_PAD_1, 0x90, QSPI_ADDR, QSPI_PAD_1, 0x18), [33] = QSPI_LUT_SEQ(QSPI_READ, QSPI_PAD_1, 0x02, 0, 0, 0),

/* READ DATA*/
 [36] = QSPI_LUT_SEQ(QSPI_CMD, QSPI_PAD_1, 0x03, QSPI_ADDR, QSPI_PAD_1, 0x18), [37] = QSPI_LUT_SEQ(QSPI_READ, QSPI_PAD_1, 16, 0, 0, 0),

#ifdef CYPRESS_S25FL
 /* Seq7: Erase Sector */
 /* CMD: 0x20 - Sector Erase, single pad */
 /* ADDR: 0x18 - 24 bit address, single pad */
 // Hybrid sectors of 4kb and 64kb, command 0x20 is for 4kb and command 0xd8 is for 64kb
 // [28] erases 4 kB sectors, [40] erases 64 kB sectors
 [40] = QSPI_LUT_SEQ(QSPI_CMD, QSPI_PAD_1, 0xD8, QSPI_ADDR, QSPI_PAD_1, 0x18), // CYPRESS
#endif
 /* Match MISRA rule */
 [63] = 0 };
Labels (1)
Tags (3)
0 Kudos
5 Replies

1,078 Views
xiangjun_rong
NXP TechSupport
NXP TechSupport

Hi, Martir,

As you know we have qspi example for FRDM-K82F.  If you run it directly without any modification, is it oaky?

You can download ksdk from the link:

www.nxp.com/ksdk

after you install the driver, pls refer to the example:

C:\DriverE\Freescale\SDK2.2_FRDM-K82F\boards\frdmk82f\driver_examples\qspi\polling_transfer

Hope it can help you

BR

Xiangjun rong

0 Kudos

1,078 Views
xiangjun_rong
NXP TechSupport
NXP TechSupport

Hi, Martir,

BTW, if you program the flash, you have to program at least 4 words or 16 bytes and write the at least 16 bytes to TX
Buffer Data Register (QSPI_TBDR), so I suppose you can use the function:

 

(2)Save_16Bytes_to_external_memory();   //I save 4 bytes to position 0x6810 0000

It has issue to write only 4 bytes as you have done:

 Save_4Bytes_to_external_memory();   //I save 4 bytes to position 0x6810 0000

Hope it can help you

BR

Xiangjun Rong

0 Kudos

1,078 Views
xiangjun_rong
NXP TechSupport
NXP TechSupport

Hi, Roig,

Frankly speaking, I am not very clear about what your question is.

We have the example code, this is the code architecture:

1)initialize the qspi module

2)erase one page, page size is 128 bytes

3)program one page

4)read one page

For the batch reading one page, the code uses the line:

  for (i = 0; i <128; i++)
    {
        array[i]=((uint32_t *)FSL_FEATURE_QSPI_AMBA_BASE)[i];
    }

//debug the array

__asm("nop"); set a break here

the array[] is located in internal memory, you can check the array in debugger.

Pls tell us your question in detail.

BR

Xiangjun Rong

0 Kudos

1,078 Views
martir
Contributor III

Hi Xiangjun, thanks for your reply! 

I was erasing a sector (with the function erase_sector of the example code) and then I was reading that position I erased.
I should have read full FF's but instead I was reading the previous value, as if the memory AHB buffer wasn't being updated/flushed.

0 Kudos

1,078 Views
martir
Contributor III

Briefly, it 'seems' after an erase sector command, AHB buffer doesn't update. So is there any way to force a flush to the buffer?

Thanks!

EDIT: I corrected this 'problem' adding these lines in erase_sector() function. Dunno if it is the best way to manage this, but I'll use this for now. Cheers.

/*Erase sector */
void erase_sector(uint32_t addr)
{
 while (QSPI_GetStatusFlags(EXAMPLE_QSPI) & kQSPI_Busy)
 {
 }
 QSPI_ClearFifo(EXAMPLE_QSPI, kQSPI_TxFifo);
 QSPI_SetIPCommandAddress(EXAMPLE_QSPI, addr);
 cmd_write_enable();
 QSPI_ExecuteIPCommand(EXAMPLE_QSPI, 28U);
 check_if_finished();

while (QSPI_GetStatusFlags(QSPI_BASE_ADDRESS) & (kQSPI_Busy | kQSPI_IPAccess))
 {
 }
 QSPI_SoftwareReset(QSPI_BASE_ADDRESS);
 while (QSPI_GetStatusFlags(QSPI_BASE_ADDRESS) & (kQSPI_Busy | kQSPI_IPAccess))
 {
 }
}
0 Kudos