rp2040: move flash related functions into separate file from C imports for correct LSP. Fixes #3852

Signed-off-by: deadprogram <ron@hybridgroup.com>
Этот коммит содержится в:
deadprogram 2023-08-12 16:59:53 +02:00 коммит произвёл Ron Evans
родитель 37a4fa205c
коммит bfe9ee378f
2 изменённых файлов: 100 добавлений и 81 удалений

97
src/machine/machine_rp2040_flash.go Обычный файл
Просмотреть файл

@ -0,0 +1,97 @@
//go:build rp2040
package machine
import (
"bytes"
"unsafe"
)
// EnterBootloader should perform a system reset in preparation
// to switch to the bootloader to flash new firmware.
func EnterBootloader() {
enterBootloader()
}
// 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)
}
// pad data if needed so it is long enough for correct byte alignment on writes.
func (f flashBlockDevice) pad(p []byte) []byte {
overflow := int64(len(p)) % f.WriteBlockSize()
if overflow == 0 {
return p
}
padding := bytes.Repeat([]byte{0xff}, int(f.WriteBlockSize()-overflow))
return append(p, padding...)
}
// 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)
}

Просмотреть файл

@ -3,7 +3,6 @@
package machine
import (
"bytes"
"runtime/interrupt"
"unsafe"
)
@ -136,40 +135,14 @@ void ram_func flash_erase_blocks(uint32_t offset, size_t count)
*/
import "C"
// EnterBootloader should perform a system reset in preparation
// to switch to the bootloader to flash new firmware.
func EnterBootloader() {
func enterBootloader() {
C.reset_usb_boot(0, 0)
}
// Flash related code
const memoryStart = C.XIP_BASE // memory start for purpose of erase
// 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) {
func (f flashBlockDevice) writeAt(p []byte, off int64) (n int, err error) {
if writeAddress(off)+uintptr(C.XIP_BASE) > FlashDataEnd() {
return 0, errFlashCannotWritePastEOF
}
@ -190,37 +163,7 @@ func (f flashBlockDevice) WriteAt(p []byte, off int64) (n int, err error) {
return len(padded), nil
}
// 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 {
func (f flashBlockDevice) eraseBlocks(start, length int64) error {
address := writeAddress(start * f.EraseBlockSize())
if address+uintptr(C.XIP_BASE) > FlashDataEnd() {
return errFlashCannotErasePastEOF
@ -233,24 +176,3 @@ func (f flashBlockDevice) EraseBlocks(start, length int64) error {
return nil
}
// pad data if needed so it is long enough for correct byte alignment on writes.
func (f flashBlockDevice) pad(p []byte) []byte {
overflow := int64(len(p)) % f.WriteBlockSize()
if overflow == 0 {
return p
}
padding := bytes.Repeat([]byte{0xff}, int(f.WriteBlockSize()-overflow))
return append(p, padding...)
}
// return the correct address to be used for write
func writeAddress(off int64) uintptr {
return readAddress(off) - uintptr(C.XIP_BASE)
}
// return the correct address to be used for reads
func readAddress(off int64) uintptr {
return FlashDataStart() + uintptr(off)
}