Shop OBEX P1 Docs P2 Docs Learn Events
Propeller Memory Card - QPI mode very slow??? — Parallax Forums

Propeller Memory Card - QPI mode very slow???

RossHRossH Posts: 5,462
edited 2013-11-04 15:18 in Propeller 1
Hi,

I've recently been testing some Catalina drivers for the Propeller Memory Card, and I've noticed some VERY odd behavior. At first, I thought my drivers were not working at all, but it turns out they are - I just had not left them running for long enough!

It seems that when the FLASH chip is set to QPI mode, the Sector Erase ($20) and Chip Erase ($C7) operations just take a very, very long time!

Here is what I am seeing ...

In SPI mode:
Erasing a 4k block : < 0.1 second
Erasing the entire chip : 10 seconds
In QPI mode:
Erasing a 4k block : 30 seconds!
Erasing the entire chip : 2 hours!

If I leave my drivers running for long enough (as I just happend to do tonight) they work fine - but 2 hours??? This seems very bizarre!

The Parallax demo programs for this board only use SPI mode - does anyone have any working QPI code for erasing the FLASH chip on this board that might tell me what I am doing wrong???

Ross,

Comments

  • David BetzDavid Betz Posts: 14,516
    edited 2013-11-01 06:14
    RossH wrote: »
    Hi,

    I've recently been testing some Catalina drivers for the Propeller Memory Card, and I've noticed some VERY odd behavior. At first, I thought my drivers were not working at all, but it turns out they are - I just had not left them running for long enough!

    It seems that when the FLASH chip is set to QPI mode, the Sector Erase ($20) and Chip Erase ($C7) operations just take a very, very long time!

    Here is what I am seeing ...

    In SPI mode:
    Erasing a 4k block : < 0.1 second
    Erasing the entire chip : 10 seconds
    In QPI mode:
    Erasing a 4k block : 30 seconds!
    Erasing the entire chip : 2 hours!

    If I leave my drivers running for long enough (as I just happend to do tonight) they work fine - but 2 hours??? This seems very bizarre!

    The Parallax demo programs for this board only use SPI mode - does anyone have any working QPI code for erasing the FLASH chip on this board that might tell me what I am doing wrong???

    Ross,
    I have a driver for PropGCC but it's a bit hard to read since I've tried to factor out the common code into source files that can be share among drivers. I can send you a zip file containing the relevant files if that would help. I haven't seen the long erase times for 4k blocks.

    Edit: I've attached a zip file containing the PropGCC external memory driver for the PMC.

    pmc.zip
  • RossHRossH Posts: 5,462
    edited 2013-11-01 16:06
    Thanks, David.

    The main difference I can see between your code and mine is that your code seems to use bit 7 as the busy bit:
    wait_until_done
            mov     cmd, frdstatus
            call    #sst_start_quad_spi_cmd_1
            andn    dira, sio_mask
    :wait   call    #sqiRecvByte
            test    data, #$80 wz    <----- BIT 7 ???
      if_nz jmp     #:wait
            call    #release
    wait_until_done_ret
            ret
    

    My data sheet for the W25Q32 (and also the Parallax demo code) indicates the busy bit is bit 0.

    Ross.
  • David BetzDavid Betz Posts: 14,516
    edited 2013-11-01 16:56
    RossH wrote: »
    Thanks, David.

    The main difference I can see between your code and mine is that your code seems to use bit 7 as the busy bit:
    wait_until_done
            mov     cmd, frdstatus
            call    #sst_start_quad_spi_cmd_1
            andn    dira, sio_mask
    :wait   call    #sqiRecvByte
            test    data, #$80 wz    <----- BIT 7 ???
      if_nz jmp     #:wait
            call    #release
    wait_until_done_ret
            ret
    

    My data sheet for the W25Q32 (and also the Parallax demo code) indicates the busy bit is bit 0.

    Ross.
    Hmmm... Maybe it's fast because it doesn't wait long enough? I've never had programming errors though. I think I got the SQI code from someone else but I can't recall who at the moment. I'll check into this. Thanks for pointing it out.
  • David BetzDavid Betz Posts: 14,516
    edited 2013-11-01 17:02
    RossH wrote: »
    Thanks, David.

    The main difference I can see between your code and mine is that your code seems to use bit 7 as the busy bit:
    wait_until_done
            mov     cmd, frdstatus
            call    #sst_start_quad_spi_cmd_1
            andn    dira, sio_mask
    :wait   call    #sqiRecvByte
            test    data, #$80 wz    <----- BIT 7 ???
      if_nz jmp     #:wait
            call    #release
    wait_until_done_ret
            ret
    

    My data sheet for the W25Q32 (and also the Parallax demo code) indicates the busy bit is bit 0.

    Ross.
    Actually, you're looking at the SST code. It tests bit 7 but the Winbond code tests bit 0. This driver was designed to work with either type of flash chip.
  • David BetzDavid Betz Posts: 14,516
    edited 2013-11-01 17:11
    Okay, now I see what is different. I never converted to using SQI mode. I'm using the old QuadSPI mode that was the only mode that worked on the older Winbond chips. That uses SPI to send the command and QuadSPI to send/receive the data. I guess I should try switching to the SQI mode in my driver.
  • RossHRossH Posts: 5,462
    edited 2013-11-02 17:08
    David Betz wrote: »
    Okay, now I see what is different. I never converted to using SQI mode. I'm using the old QuadSPI mode that was the only mode that worked on the older Winbond chips. That uses SPI to send the command and QuadSPI to send/receive the data. I guess I should try switching to the SQI mode in my driver.

    Thanks, David - yes, I missed that also.

    Everything seems fine in QPI mode except for the Sector Erase and Chip Erase commands (well, they work, but they take far too long to be useful!). So for the moment I will just leave it like that - i.e. for those two commands only, I will revert to SPI mode.

    If you ever do convert your driver to use QPI mode for these commands, I'd be interested to see what times you get.

    Ross.
  • David BetzDavid Betz Posts: 14,516
    edited 2013-11-03 10:32
    RossH wrote: »
    Hi,

    I've recently been testing some Catalina drivers for the Propeller Memory Card, and I've noticed some VERY odd behavior. At first, I thought my drivers were not working at all, but it turns out they are - I just had not left them running for long enough!

    It seems that when the FLASH chip is set to QPI mode, the Sector Erase ($20) and Chip Erase ($C7) operations just take a very, very long time!

    Here is what I am seeing ...

    In SPI mode:
    Erasing a 4k block : < 0.1 second
    Erasing the entire chip : 10 seconds
    In QPI mode:
    Erasing a 4k block : 30 seconds!
    Erasing the entire chip : 2 hours!

    If I leave my drivers running for long enough (as I just happend to do tonight) they work fine - but 2 hours??? This seems very bizarre!

    The Parallax demo programs for this board only use SPI mode - does anyone have any working QPI code for erasing the FLASH chip on this board that might tell me what I am doing wrong???

    Ross,
    I've now switched over to QPI mode for the PMC flash chip and I'm finding that the 4k erase never finishes. I suppose I must have made an error in my conversion from QuadSPI to QPI. Can you post the code you're using for QPI mode?

    Thanks,
    David
  • David BetzDavid Betz Posts: 14,516
    edited 2013-11-03 13:08
    David Betz wrote: »
    I've now switched over to QPI mode for the PMC flash chip and I'm finding that the 4k erase never finishes. I suppose I must have made an error in my conversion from QuadSPI to QPI. Can you post the code you're using for QPI mode?

    Thanks,
    David
    I had a bug in my code and now that I've fixed it I see the same slow behavior that you were noticing. I guess I'll try what you're doing and do the erase and maybe the programming as well in QuadSPI model instead of QPI mode. It's odd that Winbond doesn't have an errata that mentions this problem. I've also noticed that my driver only works once right after powering on the QuickStart. That's because on subsequent attempts without an intervening power cycle the flash chip is already in QPI mode and attempting to put it in that mode again causes the SPI commands to fail. How have you handled that? I can't see a safe way to determine whether the chip is already in QPI mode.
  • Roy ElthamRoy Eltham Posts: 3,000
    edited 2013-11-03 14:43
    According to the datasheet it should only take a maximum of 400ms to erase a sector(4k).
    Can you share the code you are using for the QPI mode?

    One thing I thought of, which is just a guess and may be silly to ask, but I'll ask it anyway. Is it possible that you are not leaving CS high long enough after issuing the erase command before you try to read the status register (which will bring CS low again? The datasheet says it needs to be high for 50ns to deselect.

    Also, have you tried using the larger block erase commands? or the whole chip erase command?
  • David BetzDavid Betz Posts: 14,516
    edited 2013-11-03 16:20
    Roy Eltham wrote: »
    According to the datasheet it should only take a maximum of 400ms to erase a sector(4k).
    Can you share the code you are using for the QPI mode?

    One thing I thought of, which is just a guess and may be silly to ask, but I'll ask it anyway. Is it possible that you are not leaving CS high long enough after issuing the erase command before you try to read the status register (which will bring CS low again? The datasheet says it needs to be high for 50ns to deselect.

    Also, have you tried using the larger block erase commands? or the whole chip erase command?
    That 50ns may be the problem. Here is the code I was using:
        FLASH_ERASE4KBLK    = $20
        FLASH_RDSTATUS      = $05
        FLASH_WRENABLE      = $06
    
    erase_4k_block
            call    #qpi_write_enable
            mov     data, #FLASH_ERASE4KBLK
            call    #start_flash_read_write
            call    #release
            call    #qpi_wait_until_done
    erase_4k_block_ret
            ret
    
    qpi_write_enable
            andn    outa, flash_cs_mask
            mov     data, #FLASH_WRENABLE
            call    #sqiSendByte
            call    #release
    qpi_write_enable_ret
            ret
            
    start_flash_read_write
            andn    outa, flash_cs_mask
            call    #sqiSendByte
            mov     data, extaddr
            shr     data, #16
            call    #sqiSendByte
            mov     data, extaddr
            shr     data, #8
            call    #sqiSendByte
            mov     data, extaddr
            call    #sqiSendByte
    start_flash_read_write_ret
            ret
    
    qpi_wait_until_done
            andn    outa, flash_cs_mask
            mov     data, #FLASH_RDSTATUS
            call    #sqiSendByteX
            andn    dira, sio_mask
            andn    outa, sck_mask
    :wait   call    #sqiRecvByte
            test    data, #1 wz
      if_nz jmp     #:wait
            call    #release
    qpi_wait_until_done_ret
            ret
    
    sqiSendByte
            mov     bits, data
            ror     bits, #4
            rol     bits, sio_shift
            and     bits, sio_mask
            andn    outa, sio_mask
            or      outa, bits
            or      outa, sck_mask
            andn    outa, sck_mask
            rol     data, sio_shift
            and     data, sio_mask
            andn    outa, sio_mask
            or      outa, data
            or      outa, sck_mask
            andn    outa, sck_mask
    sqiSendByte_ret
            ret
    
    sqiSendByteX
            mov     bits, data
            ror     bits, #4
            rol     bits, sio_shift
            and     bits, sio_mask
            andn    outa, sio_mask
            or      outa, bits
            or      outa, sck_mask
            andn    outa, sck_mask
            rol     data, sio_shift
            and     data, sio_mask
            andn    outa, sio_mask
            or      outa, data
            or      outa, sck_mask
            ' let the caller release the clock so that the bus
            ' can be switched to input before the clock goes low
            ' andn    outa, sck_mask
    sqiSendByteX_ret
            ret
    
    sqiRecvByte
            or      outa, sck_mask
            mov     data, ina
            and     data, sio_mask
            rol     data, #4
            andn    outa, sck_mask
            or      outa, sck_mask
            mov     bits, ina
            and     bits, sio_mask
            or      data, bits
            ror     data, sio_shift
            andn    outa, sck_mask
    sqiRecvByte_ret
            ret
    
    release
            mov     outa, pinout
            mov     dira, pindir
    release_ret
            ret
    
  • David BetzDavid Betz Posts: 14,516
    edited 2013-11-04 15:05
    Roy Eltham wrote: »
    Is it possible that you are not leaving CS high long enough after issuing the erase command before you try to read the status register (which will bring CS low again? The datasheet says it needs to be high for 50ns to deselect.
    I was just thinking about this again. At 80mhz, doesn't each instruction on the P1 take 50ns? If so, it isn't possible to leave CS high for less than 50ns. Or have I gotten my math wrong again? :-)
  • Roy ElthamRoy Eltham Posts: 3,000
    edited 2013-11-04 15:13
    David, you are correct.
    I was concerned if you were setting it high, and then in the very next instruction setting it low. Which would be right at the 50ns edge and might have been an issue, but your code has several instructions between setting it, so the timing is not the issue.
    Although, the release function uses pinout and pindir that I assume are defined someplace else. Is this resulting in CS being set high, or is it letting it float? Is there a pullup on the CS line?
  • David BetzDavid Betz Posts: 14,516
    edited 2013-11-04 15:18
    Roy Eltham wrote: »
    David, you are correct.
    I was concerned if you were setting it high, and then in the very next instruction setting it low. Which would be right at the 50ns edge and might have been an issue, but your code has several instructions between setting it, so the timing is not the issue.
    Although, the release function uses pinout and pindir that I assume are defined someplace else. Is this resulting in CS being set high, or is it letting it float? Is there a pullup on the CS line?
    pinout sets the CS lines to high for both the flash and the SRAM.
Sign In or Register to comment.