tinygo.org/x/drivers@v0.27.1-0.20240509133757-7dbca2a54349/flash/flash.go (about)

     1  package flash
     2  
     3  import (
     4  	"time"
     5  )
     6  
     7  const (
     8  	// BlockSize is the number of bytes in a block for most/all NOR flash memory
     9  	BlockSize = 64 * 1024
    10  
    11  	// SectorSize is the number of bytes in a sector for most/all NOR flash memory
    12  	SectorSize = 4 * 1024
    13  
    14  	// PageSize is the number of bytes in a page for most/all NOR flash memory
    15  	PageSize = 256
    16  )
    17  
    18  // Device represents a NOR flash memory device accessible using SPI
    19  type Device struct {
    20  	trans transport
    21  	attrs Attrs
    22  }
    23  
    24  // DeviceConfig contains the parameters that can be set when configuring a
    25  // flash memory device.
    26  type DeviceConfig struct {
    27  	Identifier DeviceIdentifier
    28  }
    29  
    30  // JedecID encapsules the ID values that unique identify a flash memory device.
    31  type JedecID struct {
    32  	ManufID  uint8
    33  	MemType  uint8
    34  	Capacity uint8
    35  }
    36  
    37  // Uint32 returns the JEDEC ID packed into a uint32
    38  func (id JedecID) Uint32() uint32 {
    39  	return uint32(id.ManufID)<<16 | uint32(id.MemType)<<8 | uint32(id.Capacity)
    40  }
    41  
    42  // SerialNumber represents a serial number read from a flash memory device
    43  type SerialNumber uint64
    44  
    45  // Attrs represent the differences in hardware characteristics and capabilities
    46  // of various SPI flash memory devices.
    47  type Attrs struct {
    48  
    49  	// TotalSize is the number of bytes that the flash device can store
    50  	TotalSize uint32
    51  
    52  	// StartUp is the duration of time between when the device is reset and when
    53  	// it is ready to operation
    54  	StartUp time.Duration
    55  
    56  	// Three response bytes to 0x9f JEDEC ID command.
    57  	JedecID
    58  
    59  	// Max clock speed for all operations and the fastest read mode.
    60  	MaxClockSpeedMHz uint8
    61  
    62  	// Bitmask for Quad Enable bit if present. 0x00 otherwise. This is for the
    63  	// highest byte in the status register.
    64  	QuadEnableBitMask uint8
    65  
    66  	HasSectorProtection bool
    67  
    68  	// Supports the 0x0b fast read command with 8 dummy cycles.
    69  	SupportsFastRead bool
    70  
    71  	// Supports the fast read, quad output command 0x6b with 8 dummy cycles.
    72  	SupportsQSPI bool
    73  
    74  	// Supports the quad input page program command 0x32. This is known as 1-1-4
    75  	// because it only uses all four lines for data.
    76  	SupportsQSPIWrites bool
    77  
    78  	// Requires a separate command 0x31 to write to the second byte of the status
    79  	// register. Otherwise two byte are written via 0x01.
    80  	WriteStatusSplit bool
    81  
    82  	// True when the status register is a single byte. This implies the Quad
    83  	// Enable bit is in the first byte and the Read Status Register 2 command
    84  	// (0x35) is unsupported.
    85  	SingleStatusByte bool
    86  }
    87  
    88  // Configure sets up the device and the underlying transport mechanism.  The
    89  // DeviceConfig argument allows the caller to specify an instance of the
    90  // DeviceIdentifier interface that, if provided, will be used to retrieve the
    91  // attributes of the device based on the JEDEC ID.
    92  func (dev *Device) Configure(config *DeviceConfig) (err error) {
    93  
    94  	dev.trans.configure(config)
    95  
    96  	var id JedecID
    97  	if id, err = dev.ReadJEDEC(); err != nil {
    98  		return err
    99  	}
   100  
   101  	// try to ascertain the vendor-specific attributes of the chip using the
   102  	// provided Identifier
   103  	if config.Identifier != nil {
   104  		dev.attrs = config.Identifier.Identify(id)
   105  	} else {
   106  		dev.attrs = Attrs{JedecID: id}
   107  	}
   108  
   109  	// We don't know what state the flash is in so wait for any remaining
   110  	// writes and then reset.
   111  
   112  	// The write in progress bit should be low.
   113  	for s, err := dev.ReadStatus(); (s & 0x01) > 0; s, err = dev.ReadStatus() {
   114  		if err != nil {
   115  			return err
   116  		}
   117  	}
   118  	// The suspended write/erase bit should be low.
   119  	for s, err := dev.ReadStatus2(); (s & 0x80) > 0; s, err = dev.ReadStatus2() {
   120  		if err != nil {
   121  			return err
   122  		}
   123  	}
   124  	// perform device reset
   125  	if err := dev.trans.runCommand(cmdEnableReset); err != nil {
   126  		return err
   127  	}
   128  	if err := dev.trans.runCommand(cmdReset); err != nil {
   129  		return err
   130  	}
   131  
   132  	// Wait for the reset - 30us by default
   133  	time.Sleep(30 * time.Microsecond)
   134  
   135  	// Speed up to max device frequency
   136  	// I propose a check here for max frequency, but not put that functionality directly into the driver.
   137  	// Either that or we have to change the signature of the SPI interface in the machine package itself.
   138  	if dev.attrs.MaxClockSpeedMHz > 0 {
   139  		err := dev.trans.setClockSpeed(uint32(dev.attrs.MaxClockSpeedMHz) * 1e6)
   140  		if err != nil {
   141  			return err
   142  		}
   143  	}
   144  
   145  	// Enable Quad Mode if available
   146  	if dev.trans.supportQuadMode() && dev.attrs.QuadEnableBitMask > 0 {
   147  		// Verify that QSPI mode is enabled.
   148  		var status byte
   149  		if dev.attrs.SingleStatusByte {
   150  			status, err = dev.ReadStatus()
   151  		} else {
   152  			status, err = dev.ReadStatus2()
   153  		}
   154  		if err != nil {
   155  			return err
   156  		}
   157  		// Check and set the quad enable bit.
   158  		if status&dev.attrs.QuadEnableBitMask == 0 {
   159  			if err := dev.WriteEnable(); err != nil {
   160  				return err
   161  			}
   162  			fullStatus := []byte{0x00, dev.attrs.QuadEnableBitMask}
   163  			if dev.attrs.WriteStatusSplit {
   164  				err = dev.trans.writeCommand(cmdWriteStatus2, fullStatus[1:])
   165  			} else if dev.attrs.SingleStatusByte {
   166  				err = dev.trans.writeCommand(cmdWriteStatus, fullStatus[1:])
   167  			} else {
   168  				err = dev.trans.writeCommand(cmdWriteStatus, fullStatus)
   169  			}
   170  			if err != nil {
   171  				return err
   172  			}
   173  		}
   174  	}
   175  
   176  	// disable sector protection if the chip has it
   177  	if dev.attrs.HasSectorProtection {
   178  		if err := dev.WriteEnable(); err != nil {
   179  			return err
   180  		}
   181  		if err := dev.trans.writeCommand(cmdWriteStatus, []byte{0x00}); err != nil {
   182  			return err
   183  		}
   184  	}
   185  
   186  	// write disable
   187  	if err := dev.trans.runCommand(cmdWriteDisable); err != nil {
   188  		return err
   189  	}
   190  	return dev.WaitUntilReady()
   191  }
   192  
   193  // Attrs returns the attributes of the device determined from the most recent
   194  // call to Configure(). If no call to Configure() has been made, this will be
   195  // the zero value of the Attrs struct.
   196  func (dev *Device) Attrs() Attrs {
   197  	return dev.attrs
   198  }
   199  
   200  // ReadJEDEC reads the JEDEC ID from the device; this ID can then be used to
   201  // ascertain the attributes of the chip from a list of known devices.
   202  func (dev *Device) ReadJEDEC() (JedecID, error) {
   203  	jedecID := make([]byte, 3)
   204  	if err := dev.trans.readCommand(cmdReadJedecID, jedecID); err != nil {
   205  		return JedecID{}, err
   206  	}
   207  	return JedecID{jedecID[0], jedecID[1], jedecID[2]}, nil
   208  }
   209  
   210  // ReadSerialNumber reads the serial numbers from the connected device.
   211  // TODO: maybe check if byte order / endianess is correct, probably is not
   212  func (dev *Device) ReadSerialNumber() (SerialNumber, error) {
   213  	sn := make([]byte, 12)
   214  	if err := dev.trans.readCommand(0x4B, sn); err != nil {
   215  		return 0, err
   216  	}
   217  	return SerialNumber(uint64(sn[11]) | uint64(sn[10])<<0x8 |
   218  		uint64(sn[9])<<0x10 | uint64(sn[8])<<0x18 | uint64(sn[7])<<0x20 |
   219  		uint64(sn[6])<<0x28 | uint64(sn[5])<<0x30 | uint64(sn[4])<<0x38), nil
   220  }
   221  
   222  // Size returns the size of this memory, in bytes.
   223  func (dev *Device) Size() int64 {
   224  	if dev.attrs.TotalSize < 1 {
   225  		// in case a DeviceIdentifier function wasn't used, use the capacity
   226  		// specified in the JEDEC ID instead
   227  		return int64(dev.attrs.Capacity)
   228  	}
   229  	return int64(dev.attrs.TotalSize)
   230  }
   231  
   232  // ReadAt satisfies the io.ReaderAt interface, and fills the provided buffer
   233  // with memory read from the device starting at the provided address.
   234  func (dev *Device) ReadAt(buf []byte, addr int64) (int, error) {
   235  	if err := dev.WaitUntilReady(); err != nil {
   236  		return 0, err
   237  	}
   238  	if err := dev.trans.readMemory(uint32(addr), buf); err != nil {
   239  		return 0, err
   240  	}
   241  	return len(buf), nil
   242  }
   243  
   244  // WriteAt satisfies the io.WriterAt interface and writes data to the device,
   245  // one page at a time, starting at the provided address. This method assumes
   246  // that the destination is already erased.
   247  func (dev *Device) WriteAt(buf []byte, addr int64) (n int, err error) {
   248  	remain := uint32(len(buf))
   249  	idx := uint32(0)
   250  	loc := uint32(addr)
   251  	for remain > 0 {
   252  		if err = dev.WaitUntilReady(); err != nil {
   253  			return
   254  		}
   255  		if err = dev.WriteEnable(); err != nil {
   256  			return
   257  		}
   258  		leftOnPage := PageSize - (loc & (PageSize - 1))
   259  		toWrite := remain
   260  		if leftOnPage < remain {
   261  			toWrite = leftOnPage
   262  		}
   263  		if err = dev.trans.writeMemory(loc, buf[idx:idx+toWrite]); err != nil {
   264  			return
   265  		}
   266  		idx += toWrite
   267  		loc += toWrite
   268  		remain -= toWrite
   269  	}
   270  	return len(buf) - int(remain), nil
   271  }
   272  
   273  // WriteBlockSize returns the block size in which data can be written to
   274  // memory. It can be used by a client to optimize writes, non-aligned writes
   275  // should always work correctly.
   276  // For SPI NOR flash this is the page size, usually/always 256.
   277  func (dev *Device) WriteBlockSize() int64 {
   278  	return PageSize
   279  }
   280  
   281  // EraseBlockSize returns the smallest erasable area on this particular chip
   282  // in bytes. This is used for the block size in EraseBlocks.
   283  // For SPI NOR flash this is the sector size, usually/always 4096.
   284  func (dev *Device) EraseBlockSize() int64 {
   285  	return SectorSize
   286  }
   287  
   288  // EraseBlocks erases the given number of blocks. An implementation may
   289  // transparently coalesce ranges of blocks into larger bundles if the chip
   290  // supports this. The start and len parameters are in block numbers, use
   291  // EraseBlockSize to map addresses to blocks.
   292  func (dev *Device) EraseBlocks(start, len int64) error {
   293  	for i := start; i < start+len; i++ {
   294  		if err := dev.EraseBlock(uint32(i)); err != nil {
   295  			return err
   296  		}
   297  	}
   298  	return nil
   299  }
   300  
   301  func (dev *Device) WriteEnable() error {
   302  	return dev.trans.runCommand(cmdWriteEnable)
   303  }
   304  
   305  // EraseBlock erases a block of memory at the specified index
   306  func (dev *Device) EraseBlock(blockNumber uint32) error {
   307  	if err := dev.WaitUntilReady(); err != nil {
   308  		return err
   309  	}
   310  	if err := dev.WriteEnable(); err != nil {
   311  		return err
   312  	}
   313  	return dev.trans.eraseCommand(cmdEraseBlock, blockNumber*BlockSize)
   314  }
   315  
   316  // EraseSector erases a sector of memory at the given index
   317  func (dev *Device) EraseSector(sectorNumber uint32) error {
   318  	if err := dev.WaitUntilReady(); err != nil {
   319  		return err
   320  	}
   321  	if err := dev.WriteEnable(); err != nil {
   322  		return err
   323  	}
   324  	return dev.trans.eraseCommand(cmdEraseSector, sectorNumber*SectorSize)
   325  }
   326  
   327  // EraseChip erases the entire flash memory chip
   328  func (dev *Device) EraseAll() error {
   329  	if err := dev.WaitUntilReady(); err != nil {
   330  		return err
   331  	}
   332  	if err := dev.WriteEnable(); err != nil {
   333  		return err
   334  	}
   335  	return dev.trans.runCommand(cmdEraseChip)
   336  }
   337  
   338  // ReadStatus reads the value from status register 1 of the device
   339  func (dev *Device) ReadStatus() (status byte, err error) {
   340  	buf := make([]byte, 1)
   341  	err = dev.trans.readCommand(cmdReadStatus, buf)
   342  	return buf[0], err
   343  }
   344  
   345  // ReadStatus2 reads the value from status register 2 of the device
   346  func (dev *Device) ReadStatus2() (status byte, err error) {
   347  	buf := make([]byte, 1)
   348  	err = dev.trans.readCommand(cmdReadStatus2, buf)
   349  	return buf[0], err
   350  }
   351  
   352  // WaitUntilReady queries the status register until the device is ready for the
   353  // next operation.
   354  func (dev *Device) WaitUntilReady() error {
   355  	expire := time.Now().UnixNano() + int64(1*time.Second)
   356  	for s, err := dev.ReadStatus(); (s & 0x03) > 0; s, err = dev.ReadStatus() {
   357  		if err != nil {
   358  			return err
   359  		}
   360  		if time.Now().UnixNano() > expire {
   361  			return ErrWaitExpired
   362  		}
   363  	}
   364  	return nil
   365  }
   366  
   367  const (
   368  	cmdRead            = 0x03 // read memory using single-bit transfer
   369  	cmdQuadRead        = 0x6B // read with 1 line address, 4 line data
   370  	cmdReadJedecID     = 0x9F // read the JEDEC ID from the device
   371  	cmdPageProgram     = 0x02 // write a page of memory using single-bit transfer
   372  	cmdQuadPageProgram = 0x32 // write with 1 line address, 4 line data
   373  	cmdReadStatus      = 0x05 // read status register 1
   374  	cmdReadStatus2     = 0x35 // read status register 2
   375  	cmdWriteStatus     = 0x01 // write status register 1
   376  	cmdWriteStatus2    = 0x31 // write status register 2
   377  	cmdEnableReset     = 0x66 // enable reset
   378  	cmdReset           = 0x99 // perform reset
   379  	cmdWriteEnable     = 0x06 // write-enable memory
   380  	cmdWriteDisable    = 0x04 // write-protect memory
   381  	cmdEraseSector     = 0x20 // erase a sector of memory
   382  	cmdEraseBlock      = 0xD8 // erase a block of memory
   383  	cmdEraseChip       = 0xC7 // erase the entire chip
   384  )
   385  
   386  type Error uint8
   387  
   388  const (
   389  	_                          = iota
   390  	ErrInvalidClockSpeed Error = iota
   391  	ErrInvalidAddrRange
   392  	ErrWaitExpired
   393  )
   394  
   395  func (err Error) Error() string {
   396  	switch err {
   397  	case ErrInvalidClockSpeed:
   398  		return "flash: invalid clock speed"
   399  	case ErrInvalidAddrRange:
   400  		return "flash: invalid address range"
   401  	case ErrWaitExpired:
   402  		return "flash: wait until ready expired"
   403  	default:
   404  		return "flash: unspecified error"
   405  	}
   406  }