machine/samd51: disable/restore Flash cache on write/erase
Signed-off-by: deadprogram <ron@hybridgroup.com>
Этот коммит содержится в:
родитель
51c1579c3d
коммит
0bc19735f3
1 изменённых файлов: 18 добавлений и 17 удалений
|
@ -2096,8 +2096,6 @@ func (f flashBlockDevice) ReadAt(p []byte, off int64) (n int, err error) {
|
||||||
return 0, errFlashCannotReadPastEOF
|
return 0, errFlashCannotReadPastEOF
|
||||||
}
|
}
|
||||||
|
|
||||||
f.ensureInitComplete()
|
|
||||||
|
|
||||||
waitWhileFlashBusy()
|
waitWhileFlashBusy()
|
||||||
|
|
||||||
data := unsafe.Slice((*byte)(unsafe.Add(unsafe.Pointer(FlashDataStart()), uintptr(off))), len(p))
|
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
|
return 0, errFlashCannotWritePastEOF
|
||||||
}
|
}
|
||||||
|
|
||||||
f.ensureInitComplete()
|
|
||||||
|
|
||||||
address := FlashDataStart() + uintptr(off)
|
address := FlashDataStart() + uintptr(off)
|
||||||
padded := f.pad(p)
|
padded := f.pad(p)
|
||||||
|
|
||||||
|
settings := disableFlashCache()
|
||||||
|
defer restoreFlashCache(settings)
|
||||||
|
|
||||||
waitWhileFlashBusy()
|
waitWhileFlashBusy()
|
||||||
|
|
||||||
sam.NVMCTRL.CTRLB.Set(sam.NVMCTRL_CTRLB_CMD_PBC | (sam.NVMCTRL_CTRLB_CMDEX_KEY << sam.NVMCTRL_CTRLB_CMDEX_Pos))
|
sam.NVMCTRL.CTRLB.Set(sam.NVMCTRL_CTRLB_CMD_PBC | (sam.NVMCTRL_CTRLB_CMDEX_KEY << sam.NVMCTRL_CTRLB_CMDEX_Pos))
|
||||||
|
|
||||||
waitWhileFlashBusy()
|
waitWhileFlashBusy()
|
||||||
|
|
||||||
sam.NVMCTRL.SetADDR(uint32(address))
|
|
||||||
|
|
||||||
for j := 0; j < len(padded); j += int(f.WriteBlockSize()) {
|
for j := 0; j < len(padded); j += int(f.WriteBlockSize()) {
|
||||||
// write first word using double-word low order word
|
// write first word using double-word low order word
|
||||||
*(*uint32)(unsafe.Pointer(address)) = binary.LittleEndian.Uint32(padded[j : j+int(f.WriteBlockSize()/2)])
|
*(*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
|
// 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()
|
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))
|
sam.NVMCTRL.CTRLB.Set(sam.NVMCTRL_CTRLB_CMD_WQW | (sam.NVMCTRL_CTRLB_CMDEX_KEY << sam.NVMCTRL_CTRLB_CMDEX_Pos))
|
||||||
|
|
||||||
waitWhileFlashBusy()
|
waitWhileFlashBusy()
|
||||||
|
@ -2148,7 +2144,7 @@ func (f flashBlockDevice) WriteAt(p []byte, off int64) (n int, err error) {
|
||||||
return j, err
|
return j, err
|
||||||
}
|
}
|
||||||
|
|
||||||
address += uintptr(f.WriteBlockSize()) / 2
|
address += uintptr(f.WriteBlockSize())
|
||||||
}
|
}
|
||||||
|
|
||||||
return len(padded), nil
|
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
|
// 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, len int64) error {
|
func (f flashBlockDevice) EraseBlocks(start, len int64) error {
|
||||||
f.ensureInitComplete()
|
|
||||||
|
|
||||||
address := FlashDataStart() + uintptr(start*f.EraseBlockSize())
|
address := FlashDataStart() + uintptr(start*f.EraseBlockSize())
|
||||||
|
|
||||||
|
settings := disableFlashCache()
|
||||||
|
defer restoreFlashCache(settings)
|
||||||
|
|
||||||
waitWhileFlashBusy()
|
waitWhileFlashBusy()
|
||||||
|
|
||||||
for i := start; i < start+len; i++ {
|
for i := start; i < start+len; i++ {
|
||||||
|
@ -2217,10 +2215,8 @@ func (f flashBlockDevice) pad(p []byte) []byte {
|
||||||
return append(p, padding...)
|
return append(p, padding...)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (f flashBlockDevice) ensureInitComplete() {
|
func disableFlashCache() uint16 {
|
||||||
if f.initComplete {
|
settings := sam.NVMCTRL.CTRLA.Get()
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// disable caches
|
// disable caches
|
||||||
sam.NVMCTRL.SetCTRLA_CACHEDIS0(1)
|
sam.NVMCTRL.SetCTRLA_CACHEDIS0(1)
|
||||||
|
@ -2228,7 +2224,12 @@ func (f flashBlockDevice) ensureInitComplete() {
|
||||||
|
|
||||||
waitWhileFlashBusy()
|
waitWhileFlashBusy()
|
||||||
|
|
||||||
f.initComplete = true
|
return settings
|
||||||
|
}
|
||||||
|
|
||||||
|
func restoreFlashCache(settings uint16) {
|
||||||
|
sam.NVMCTRL.CTRLA.Set(settings)
|
||||||
|
waitWhileFlashBusy()
|
||||||
}
|
}
|
||||||
|
|
||||||
func waitWhileFlashBusy() {
|
func waitWhileFlashBusy() {
|
||||||
|
|
Загрузка…
Создание таблицы
Сослаться в новой задаче