Browse Source

machine/samd51: disable/restore Flash cache on write/erase

Signed-off-by: deadprogram <ron@hybridgroup.com>
pull/3431/head
deadprogram 2 years ago
committed by Ron Evans
parent
commit
0bc19735f3
  1. 35
      src/machine/machine_atsamd51.go

35
src/machine/machine_atsamd51.go

@ -2096,8 +2096,6 @@ func (f flashBlockDevice) ReadAt(p []byte, off int64) (n int, err error) {
return 0, errFlashCannotReadPastEOF
}
f.ensureInitComplete()
waitWhileFlashBusy()
data := unsafe.Slice((*byte)(unsafe.Add(unsafe.Pointer(FlashDataStart()), uintptr(off))), len(p))
@ -2116,30 +2114,28 @@ func (f flashBlockDevice) WriteAt(p []byte, off int64) (n int, err error) {
return 0, errFlashCannotWritePastEOF
}
f.ensureInitComplete()
address := FlashDataStart() + uintptr(off)
padded := f.pad(p)
settings := disableFlashCache()
defer restoreFlashCache(settings)
waitWhileFlashBusy()
sam.NVMCTRL.CTRLB.Set(sam.NVMCTRL_CTRLB_CMD_PBC | (sam.NVMCTRL_CTRLB_CMDEX_KEY << sam.NVMCTRL_CTRLB_CMDEX_Pos))
waitWhileFlashBusy()
sam.NVMCTRL.SetADDR(uint32(address))
for j := 0; j < len(padded); j += int(f.WriteBlockSize()) {
// write first word using double-word low order word
*(*uint32)(unsafe.Pointer(address)) = binary.LittleEndian.Uint32(padded[j : j+int(f.WriteBlockSize()/2)])
address += uintptr(f.WriteBlockSize()) / 2
// write second word using double-word high order word
*(*uint32)(unsafe.Pointer(address)) = binary.LittleEndian.Uint32(padded[j+int(f.WriteBlockSize()/2) : j+int(f.WriteBlockSize())])
*(*uint32)(unsafe.Add(unsafe.Pointer(address), uintptr(f.WriteBlockSize())/2)) = binary.LittleEndian.Uint32(padded[j+int(f.WriteBlockSize()/2) : j+int(f.WriteBlockSize())])
waitWhileFlashBusy()
sam.NVMCTRL.SetADDR(uint32(address))
sam.NVMCTRL.CTRLB.Set(sam.NVMCTRL_CTRLB_CMD_WQW | (sam.NVMCTRL_CTRLB_CMDEX_KEY << sam.NVMCTRL_CTRLB_CMDEX_Pos))
waitWhileFlashBusy()
@ -2148,7 +2144,7 @@ func (f flashBlockDevice) WriteAt(p []byte, off int64) (n int, err error) {
return j, err
}
address += uintptr(f.WriteBlockSize()) / 2
address += uintptr(f.WriteBlockSize())
}
return len(padded), nil
@ -2185,9 +2181,11 @@ func (f flashBlockDevice) EraseBlockSize() int64 {
// supports this. The start and len parameters are in block numbers, use
// EraseBlockSize to map addresses to blocks.
func (f flashBlockDevice) EraseBlocks(start, len int64) error {
f.ensureInitComplete()
address := FlashDataStart() + uintptr(start*f.EraseBlockSize())
settings := disableFlashCache()
defer restoreFlashCache(settings)
waitWhileFlashBusy()
for i := start; i < start+len; i++ {
@ -2217,10 +2215,8 @@ func (f flashBlockDevice) pad(p []byte) []byte {
return append(p, padding...)
}
func (f flashBlockDevice) ensureInitComplete() {
if f.initComplete {
return
}
func disableFlashCache() uint16 {
settings := sam.NVMCTRL.CTRLA.Get()
// disable caches
sam.NVMCTRL.SetCTRLA_CACHEDIS0(1)
@ -2228,7 +2224,12 @@ func (f flashBlockDevice) ensureInitComplete() {
waitWhileFlashBusy()
f.initComplete = true
return settings
}
func restoreFlashCache(settings uint16) {
sam.NVMCTRL.CTRLA.Set(settings)
waitWhileFlashBusy()
}
func waitWhileFlashBusy() {

Loading…
Cancel
Save