eblot / pyspiflash

SPI data flash device drivers (pure Python)
MIT License
39 stars 30 forks source link

SPI mode 3 #21

Open dordor3 opened 3 years ago

dordor3 commented 3 years ago

how can I change the spi mode to 3? it's mentions that it was verify on Micron N25Q, but it required spi mode = 3 I see any option to change the spi mode

eblot commented 3 years ago

It's been a very long time since I've used N25Q, but it used to support mode = 0:

N25Q64
dordor3 commented 3 years ago

actually, I'm using MT25QL128ABA8ESF, which has the same JEDEC ID ads the N25Q. in mode=0 I'm getting bit shift. if I change the script to mode=3 it work perfectly fine. since I don't want to change the original script I wonder if there is a way to set this mode without editing.

eblot commented 3 years ago

I can think of two hack-ish fully untested ways (there may be more):

  1. Use your pre-instantiated SpiPort
    from pyftdi.spi import SpiController
    from spiflash.serialflash import SerialFlashManager
    cs = 1
    frequency = 6E6
    spi = SpiController(url)
    # instantiate the port, with the proper mode
    _ = spi.get_port(cs, freq= frequency, mode=3)
    # instantiate the flash device, should use the existing port, w/ changing its mode
    flash = SerialFlashManager.get_from_controller(spi, cs, frequency)

    This one is fragile, as it relies on the fact that PyFtdi does not cross check a pre-existing setting, so it may break in the future...

  2. Change the mode once the flash is discovered
    from spiflash.serialflash import SerialFlashManager
    cs = 1
    frequency = 6E6
    flash = SerialFlashManager.get_flash_device(url, cs, frequency)
    flash._spi.set_mode(3)

    This one would only work if the flash is properly discovered in mode 0, the bit shifting you are observing is only seen during data transfer

  3. Re-implement SerialFlashManager.get_flash_device()
    from spiflash.serialflash import SerialFlashManager
    class MySerialFlashManager(SerialFlashManager):
       def get_flash_device(url: str, cs: int = 0, mode: int = 0, freq: Optional[float] = None) \
               -> '_SpiFlashDevice':
           ctrl = SpiController(cs_count=cs+1)
           ctrl.configure(url)
           spi = ctrl.get_port(cs, freq, mode)
           jedec = SerialFlashManager.read_jedec_id(spi)
           if not jedec:
               # it is likely that the latency setting is too low if this
               # condition is encountered
               raise SerialFlashUnknownJedec("Unable to read JEDEC Id")
           flash = SerialFlashManager._get_flash(spi, jedec)
           flash.set_spi_frequency(freq)
           return flash
    cs = 1
    frequency = 6E6
    flash = MySerialFlashManager.get_flash_device(url, cs, 3, frequency)

    This one may also break with a future update of SpiFlash.

In any case, please do not close this ticket, as SpiFlash definitely needs a way to set the mode.