Files
tinygo/src/machine/machine_rp2_flash.go
T
Michael Smith 4768c7d431 machine/rp2350: add flash support for rp2350 (#4803)
* machine/rp2350: add flash support for rp2350
* combine duplicate files
* clean things up and group by source file
* add stubbed out xip cache clean func if needed in the future
* update flash_enable_xip_via_boot2
* remove unused macros and fix inconsistent formatting
* make flash size configurable like rp2040
* add missing flash size configs
* retain big Go CGo compatibility per #4103
* clarify CS0_SIZE source and remove single-use typedef
2025-03-16 09:45:53 +01:00

112 lines
3.1 KiB
Go

//go:build rp2040 || rp2350
package machine
import (
"unsafe"
)
// EnterBootloader should perform a system reset in preparation
// to switch to the bootloader to flash new firmware.
func EnterBootloader() {
enterBootloader()
}
// 13 = 1 + FLASH_RUID_DUMMY_BYTES(4) + FLASH_RUID_DATA_BYTES(8)
var deviceIDBuf [13]byte
// DeviceID returns an identifier that is unique within
// a particular chipset.
//
// The identity is one burnt into the MCU itself, or the
// flash chip at time of manufacture.
//
// It's possible that two different vendors may allocate
// the same DeviceID, so callers should take this into
// account if needing to generate a globally unique id.
//
// The length of the hardware ID is vendor-specific, but
// 8 bytes (64 bits) is common.
func DeviceID() []byte {
deviceIDBuf[0] = 0x4b // FLASH_RUID_CMD
err := doFlashCommand(deviceIDBuf[:], deviceIDBuf[:])
if err != nil {
panic(err)
}
return deviceIDBuf[5:13]
}
// compile-time check for ensuring we fulfill BlockDevice interface
var _ BlockDevice = flashBlockDevice{}
var Flash flashBlockDevice
type flashBlockDevice struct {
}
// ReadAt reads the given number of bytes from the block device.
func (f flashBlockDevice) ReadAt(p []byte, off int64) (n int, err error) {
if readAddress(off) > FlashDataEnd() {
return 0, errFlashCannotReadPastEOF
}
data := unsafe.Slice((*byte)(unsafe.Pointer(readAddress(off))), len(p))
copy(p, data)
return len(p), nil
}
// WriteAt writes the given number of bytes to the block device.
// Only word (32 bits) length data can be programmed.
// If the length of p is not long enough it will be padded with 0xFF bytes.
// This method assumes that the destination is already erased.
func (f flashBlockDevice) WriteAt(p []byte, off int64) (n int, err error) {
return f.writeAt(p, off)
}
// Size returns the number of bytes in this block device.
func (f flashBlockDevice) Size() int64 {
return int64(FlashDataEnd() - FlashDataStart())
}
const writeBlockSize = 1 << 8
// WriteBlockSize returns the block size in which data can be written to
// memory. It can be used by a client to optimize writes, non-aligned writes
// should always work correctly.
func (f flashBlockDevice) WriteBlockSize() int64 {
return writeBlockSize
}
const eraseBlockSizeValue = 1 << 12
func eraseBlockSize() int64 {
return eraseBlockSizeValue
}
// EraseBlockSize returns the smallest erasable area on this particular chip
// in bytes. This is used for the block size in EraseBlocks.
func (f flashBlockDevice) EraseBlockSize() int64 {
return eraseBlockSize()
}
// EraseBlocks erases the given number of blocks. An implementation may
// transparently coalesce ranges of blocks into larger bundles if the chip
// supports this. The start and len parameters are in block numbers, use
// EraseBlockSize to map addresses to blocks.
func (f flashBlockDevice) EraseBlocks(start, length int64) error {
return f.eraseBlocks(start, length)
}
// return the correct address to be used for write
func writeAddress(off int64) uintptr {
return readAddress(off) - uintptr(memoryStart)
}
// return the correct address to be used for reads
func readAddress(off int64) uintptr {
return FlashDataStart() + uintptr(off)
}