machine/rp2040: correct Flash implementation

Signed-off-by: deadprogram <ron@hybridgroup.com>
Этот коммит содержится в:
deadprogram 2023-03-11 16:29:40 +01:00 коммит произвёл Ron Evans
родитель 5db83f11df
коммит e6580bfff4

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

@ -75,8 +75,6 @@ void reset_usb_boot(uint32_t usb_activity_gpio_pin_mask, uint32_t disable_interf
#define FLASH_SECTOR_SIZE (1u << 12) #define FLASH_SECTOR_SIZE (1u << 12)
#define FLASH_BLOCK_SIZE (1u << 16) #define FLASH_BLOCK_SIZE (1u << 16)
#define FLASH_UNIQUE_ID_SIZE_BYTES 8
#define BOOT2_SIZE_WORDS 64 #define BOOT2_SIZE_WORDS 64
#define XIP_BASE 0x10000000 #define XIP_BASE 0x10000000
@ -145,7 +143,7 @@ func EnterBootloader() {
} }
// Flash related code // Flash related code
const memoryStart = 0 const memoryStart = C.XIP_BASE // memory start for purpose of erase
// compile-time check for ensuring we fulfill BlockDevice interface // compile-time check for ensuring we fulfill BlockDevice interface
var _ BlockDevice = flashBlockDevice{} var _ BlockDevice = flashBlockDevice{}
@ -157,11 +155,11 @@ type flashBlockDevice struct {
// ReadAt reads the given number of bytes from the block device. // ReadAt reads the given number of bytes from the block device.
func (f flashBlockDevice) ReadAt(p []byte, off int64) (n int, err error) { func (f flashBlockDevice) ReadAt(p []byte, off int64) (n int, err error) {
if uintptr(off)+uintptr(len(p)) > FlashDataEnd() { if readAddress(off) > FlashDataEnd() {
return 0, errFlashCannotReadPastEOF return 0, errFlashCannotReadPastEOF
} }
data := unsafe.Slice((*byte)(unsafe.Pointer(uintptr(off))), len(p)) data := unsafe.Slice((*byte)(unsafe.Pointer(readAddress(off))), len(p))
copy(p, data) copy(p, data)
return len(p), nil return len(p), nil
@ -172,7 +170,7 @@ func (f flashBlockDevice) ReadAt(p []byte, off int64) (n int, err error) {
// If the length of p is not long enough it will be padded with 0xFF bytes. // 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. // 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 uintptr(off)+uintptr(len(p)) > FlashDataEnd() { if writeAddress(off)+uintptr(C.XIP_BASE) > FlashDataEnd() {
return 0, errFlashCannotWritePastEOF return 0, errFlashCannotWritePastEOF
} }
@ -182,7 +180,7 @@ func (f flashBlockDevice) WriteAt(p []byte, off int64) (n int, err error) {
// rp2040 writes to offset, not actual address // rp2040 writes to offset, not actual address
// e.g. real address 0x10003000 is written to at // e.g. real address 0x10003000 is written to at
// 0x00003000 // 0x00003000
address := uintptr(off) - C.XIP_BASE address := writeAddress(off)
padded := f.pad(p) padded := f.pad(p)
C.flash_range_write(C.uint32_t(address), C.flash_range_write(C.uint32_t(address),
@ -223,11 +221,15 @@ func (f flashBlockDevice) EraseBlockSize() int64 {
// supports this. The start and len parameters are in block numbers, use // supports this. The start and len parameters are in block numbers, use
// EraseBlockSize to map addresses to blocks. // 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
}
state := interrupt.Disable() state := interrupt.Disable()
defer interrupt.Restore(state) defer interrupt.Restore(state)
address := uintptr(start*f.EraseBlockSize()) - C.XIP_BASE C.flash_erase_blocks(C.uint32_t(address), C.ulong(length))
C.flash_erase_blocks(C.uint32_t(address), C.ulong(length*f.EraseBlockSize()))
return nil return nil
} }
@ -242,3 +244,13 @@ func (f flashBlockDevice) pad(p []byte) []byte {
padding := bytes.Repeat([]byte{0xff}, int(paddingNeeded)) padding := bytes.Repeat([]byte{0xff}, int(paddingNeeded))
return append(p, padding...) 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)
}