Skip to content

Commit

Permalink
applet.memory.25x: use QSPI controller instead of SPI.
Browse files Browse the repository at this point in the history
This makes it possible to use higher transfer rates, at the cost of
WP# and HOLD# pins becoming mandatory.
  • Loading branch information
whitequark committed Aug 12, 2024
1 parent 481c887 commit 97f8db8
Show file tree
Hide file tree
Showing 3 changed files with 21 additions and 32 deletions.
9 changes: 5 additions & 4 deletions software/glasgow/applet/interface/qspi_controller/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -233,12 +233,13 @@ class QSPIControllerApplet(GlasgowApplet):
"""

@classmethod
def add_build_arguments(cls, parser, access):
def add_build_arguments(cls, parser, access, *, include_pins=True):
super().add_build_arguments(parser, access)

access.add_pin_argument(parser, "sck", default=True)
access.add_pin_set_argument(parser, "io", width=4, default=True)
access.add_pin_set_argument(parser, "cs", width=1, default=True)
if include_pins:
access.add_pin_argument(parser, "sck", default=True)
access.add_pin_set_argument(parser, "io", width=4, default=True)
access.add_pin_set_argument(parser, "cs", width=1, default=True)

# Most devices that advertise QSPI support should work at 1 MHz.
parser.add_argument(
Expand Down
33 changes: 11 additions & 22 deletions software/glasgow/applet/memory/_25x/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
from ....support.logging import dump_hex
from ....database.jedec import *
from ....protocol.sfdp import *
from ...interface.spi_controller import SPIControllerApplet
from ...interface.qspi_controller import QSPIControllerApplet
from ... import *


Expand Down Expand Up @@ -236,7 +236,7 @@ async def read(self, offset, length):
return await self._m25x_iface.read_sfdp(offset, length)


class Memory25xApplet(SPIControllerApplet):
class Memory25xApplet(QSPIControllerApplet):
logger = logging.getLogger(__name__)
help = "read and write 25-series SPI Flash memories"
description = """
Expand Down Expand Up @@ -272,22 +272,11 @@ class Memory25xApplet(SPIControllerApplet):

@classmethod
def add_build_arguments(cls, parser, access):
super().add_build_arguments(parser, access, omit_pins=True)

access.add_pin_argument(parser, "cs", default=True, required=True)
access.add_pin_argument(parser, "cipo", default=True, required=True)
access.add_pin_argument(parser, "wp", default=True)
access.add_pin_argument(parser, "copi", default=True, required=True)
access.add_pin_argument(parser, "sck", default=True, required=True)
access.add_pin_argument(parser, "hold", default=True)

def build_subtarget(self, target, args):
subtarget = super().build_subtarget(target, args)
if args.pin_hold is not None:
hold_t = self.mux_interface.get_deprecated_pad(args.pin_hold)
else:
hold_t = None
return Memory25xSubtarget(subtarget, hold_t)
super().add_build_arguments(parser, access, include_pins=False)

access.add_pin_set_argument(parser, "cs", width=1, required=True, default=[5])
access.add_pin_set_argument(parser, "io", width=4, required=True, default=[2, 4, 3, 0])
access.add_pin_argument( parser, "sck", required=True, default=1)

async def run(self, device, args):
spi_iface = await self.run_lower(Memory25xApplet, device, args)
Expand Down Expand Up @@ -456,10 +445,10 @@ async def interact(self, device, args, m25x_iface):
if args.operation in ("read", "fast-read"):
if args.operation == "read":
data = await m25x_iface.read(args.address, args.length,
callback=self._show_progress)
callback=self._show_progress)
if args.operation == "fast-read":
data = await m25x_iface.fast_read(args.address, args.length,
callback=self._show_progress)
callback=self._show_progress)

if args.file:
args.file.write(data)
Expand All @@ -478,10 +467,10 @@ async def interact(self, device, args, m25x_iface):
await m25x_iface.page_program(args.address, data)
if args.operation == "program":
await m25x_iface.program(args.address, data, args.page_size,
callback=self._show_progress)
callback=self._show_progress)
if args.operation == "erase-program":
await m25x_iface.erase_program(args.address, data, args.sector_size,
args.page_size, callback=self._show_progress)
args.page_size, callback=self._show_progress)

if args.operation == "verify":
if args.data is not None:
Expand Down
11 changes: 5 additions & 6 deletions software/glasgow/applet/memory/_25x/test.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,15 +7,14 @@
class Memory25xAppletTestCase(GlasgowAppletTestCase, applet=Memory25xApplet):
@synthesis_test
def test_build(self):
self.assertBuilds(args=["--pin-sck", "0", "--pin-cs", "1",
"--pin-copi", "2", "--pin-cipo", "3"])
self.assertBuilds()

# Flash used for testing: Winbond 25Q32FV
hardware_args = [
"--voltage", "3.3",
"--pin-cs", "0", "--pin-cipo", "1",
"--pin-copi", "2", "--pin-sck", "3",
"--pin-hold", "4"
"--voltage", "3.3",
"--pin-sck", "0",
"--pins-io", "1:4",
"--pins-cs", "5",
]
dut_ids = (0xef, 0x15, 0x4016)
dut_page_size = 0x100
Expand Down

0 comments on commit 97f8db8

Please sign in to comment.