diff --git a/src/machine/machine_atsamd21.go b/src/machine/machine_atsamd21.go index e0c5f2cc29..2e5fe604aa 100644 --- a/src/machine/machine_atsamd21.go +++ b/src/machine/machine_atsamd21.go @@ -1904,7 +1904,7 @@ func (f flashBlockDevice) ReadAt(p []byte, off int64) (n int, err error) { } // WriteAt writes the given number of bytes to the block device. -// Only word (32 bits) length data can be programmed. +// Data is written to the page buffer in 4-byte chunks, then saved to flash memory. // See Atmel-42181G–SAM-D21_Datasheet–09/2015 page 359. // 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. @@ -1921,8 +1921,10 @@ func (f flashBlockDevice) WriteAt(p []byte, off int64) (n int, err error) { waitWhileFlashBusy() for j := 0; j < len(padded); j += int(f.WriteBlockSize()) { - // write word - *(*uint32)(unsafe.Pointer(address)) = binary.LittleEndian.Uint32(padded[j : j+int(f.WriteBlockSize())]) + // page buffer is 64 bytes long, but only 4 bytes can be written at once + for k := 0; k < int(f.WriteBlockSize()); k += 4 { + *(*uint32)(unsafe.Pointer(address + uintptr(k))) = binary.LittleEndian.Uint32(padded[j+k : j+k+4]) + } sam.NVMCTRL.SetADDR(uint32(address >> 1)) sam.NVMCTRL.CTRLA.Set(sam.NVMCTRL_CTRLA_CMD_WP | (sam.NVMCTRL_CTRLA_CMDEX_KEY << sam.NVMCTRL_CTRLA_CMDEX_Pos)) @@ -1944,7 +1946,7 @@ func (f flashBlockDevice) Size() int64 { return int64(FlashDataEnd() - FlashDataStart()) } -const writeBlockSize = 4 +const writeBlockSize = 64 // 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