rp2040: move flash related functions into separate file from C imports for correct LSP. Fixes #3852
Signed-off-by: deadprogram <ron@hybridgroup.com>
Этот коммит содержится в:
родитель
37a4fa205c
коммит
bfe9ee378f
2 изменённых файлов: 100 добавлений и 81 удалений
97
src/machine/machine_rp2040_flash.go
Обычный файл
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
|
package machine
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
|
||||||
"runtime/interrupt"
|
"runtime/interrupt"
|
||||||
"unsafe"
|
"unsafe"
|
||||||
)
|
)
|
||||||
|
@ -136,40 +135,14 @@ void ram_func flash_erase_blocks(uint32_t offset, size_t count)
|
||||||
*/
|
*/
|
||||||
import "C"
|
import "C"
|
||||||
|
|
||||||
// EnterBootloader should perform a system reset in preparation
|
func enterBootloader() {
|
||||||
// to switch to the bootloader to flash new firmware.
|
|
||||||
func EnterBootloader() {
|
|
||||||
C.reset_usb_boot(0, 0)
|
C.reset_usb_boot(0, 0)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Flash related code
|
// Flash related code
|
||||||
const memoryStart = C.XIP_BASE // memory start for purpose of erase
|
const memoryStart = C.XIP_BASE // memory start for purpose of erase
|
||||||
|
|
||||||
// compile-time check for ensuring we fulfill BlockDevice interface
|
func (f flashBlockDevice) writeAt(p []byte, off int64) (n int, err error) {
|
||||||
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) {
|
|
||||||
if writeAddress(off)+uintptr(C.XIP_BASE) > FlashDataEnd() {
|
if writeAddress(off)+uintptr(C.XIP_BASE) > FlashDataEnd() {
|
||||||
return 0, errFlashCannotWritePastEOF
|
return 0, errFlashCannotWritePastEOF
|
||||||
}
|
}
|
||||||
|
@ -190,37 +163,7 @@ func (f flashBlockDevice) WriteAt(p []byte, off int64) (n int, err error) {
|
||||||
return len(padded), nil
|
return len(padded), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Size returns the number of bytes in this block device.
|
func (f flashBlockDevice) eraseBlocks(start, length int64) error {
|
||||||
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 {
|
|
||||||
address := writeAddress(start * f.EraseBlockSize())
|
address := writeAddress(start * f.EraseBlockSize())
|
||||||
if address+uintptr(C.XIP_BASE) > FlashDataEnd() {
|
if address+uintptr(C.XIP_BASE) > FlashDataEnd() {
|
||||||
return errFlashCannotErasePastEOF
|
return errFlashCannotErasePastEOF
|
||||||
|
@ -233,24 +176,3 @@ func (f flashBlockDevice) EraseBlocks(start, length int64) error {
|
||||||
|
|
||||||
return nil
|
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)
|
|
||||||
}
|
|
||||||
|
|
Загрузка…
Создание таблицы
Сослаться в новой задаче