machine/flash: refactor to keep use of pure offset relative to start

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

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

@ -34,6 +34,7 @@ var (
errFlashCannotWriteData = errors.New("cannot write flash data") errFlashCannotWriteData = errors.New("cannot write flash data")
errFlashCannotReadPastEOF = errors.New("cannot read beyond end of flash data") errFlashCannotReadPastEOF = errors.New("cannot read beyond end of flash data")
errFlashCannotWritePastEOF = errors.New("cannot write beyond end of flash data") errFlashCannotWritePastEOF = errors.New("cannot write beyond end of flash data")
errFlashCannotErasePastEOF = errors.New("cannot erase beyond end of flash data")
) )
// BlockDevice is the raw device that is meant to store flash data. // BlockDevice is the raw device that is meant to store flash data.
@ -67,22 +68,25 @@ type BlockDevice interface {
// FlashBuffer implements the ReadWriteCloser interface using the BlockDevice interface. // FlashBuffer implements the ReadWriteCloser interface using the BlockDevice interface.
type FlashBuffer struct { type FlashBuffer struct {
b BlockDevice b BlockDevice
// start is actual address
start uintptr start uintptr
current uintptr
// offset is relative to start
offset uintptr
} }
// OpenFlashBuffer opens a FlashBuffer. // OpenFlashBuffer opens a FlashBuffer.
func OpenFlashBuffer(b BlockDevice, address uintptr) *FlashBuffer { func OpenFlashBuffer(b BlockDevice, address uintptr) *FlashBuffer {
return &FlashBuffer{b: b, start: address, current: address} return &FlashBuffer{b: b, start: address}
} }
// Read data from a FlashBuffer. // Read data from a FlashBuffer.
func (fl *FlashBuffer) Read(p []byte) (n int, err error) { func (fl *FlashBuffer) Read(p []byte) (n int, err error) {
fl.b.ReadAt(p, int64(fl.current)) n, err = fl.b.ReadAt(p, int64(fl.offset))
fl.offset += uintptr(n)
fl.current += uintptr(len(p)) return
return len(p), nil
} }
// Write data to a FlashBuffer. // Write data to a FlashBuffer.
@ -91,21 +95,19 @@ func (fl *FlashBuffer) Write(p []byte) (n int, err error) {
// NOTE probably will not work as expected if you try to write over page boundary // NOTE probably will not work as expected if you try to write over page boundary
// of pages with different sizes. // of pages with different sizes.
pagesize := uintptr(fl.b.EraseBlockSize()) pagesize := uintptr(fl.b.EraseBlockSize())
currentPageCount := (fl.current - fl.start + pagesize - 1) / pagesize
totalPagesNeeded := (fl.current - fl.start + uintptr(len(p)) + pagesize - 1) / pagesize // calculate currentPageBlock relative to fl.start, meaning that
if currentPageCount == totalPagesNeeded { // block 0 -> fl.start
// just write the data // block 1 -> fl.start + pagesize
n, err := fl.b.WriteAt(p, int64(fl.current)) // block 2 -> fl.start + pagesize*2
if err != nil { // ...
return 0, err currentPageBlock := (fl.start + fl.offset - FlashDataStart()) + (pagesize-1)/pagesize
} lastPageBlockNeeded := (fl.start + fl.offset + uintptr(len(p)) - FlashDataStart()) + (pagesize-1)/pagesize
fl.current += uintptr(n)
return n, nil
}
// erase enough blocks to hold the data // erase enough blocks to hold the data
page := fl.flashPageFromAddress(fl.start + (currentPageCount * pagesize)) if err := fl.b.EraseBlocks(int64(currentPageBlock), int64(lastPageBlockNeeded-currentPageBlock)); err != nil {
fl.b.EraseBlocks(page, int64(totalPagesNeeded-currentPageCount)) return 0, err
}
// write the data // write the data
for i := 0; i < len(p); i += int(pagesize) { for i := 0; i < len(p); i += int(pagesize) {
@ -114,11 +116,11 @@ func (fl *FlashBuffer) Write(p []byte) (n int, err error) {
last = len(p) last = len(p)
} }
_, err := fl.b.WriteAt(p[i:last], int64(fl.current)) _, err := fl.b.WriteAt(p[i:last], int64(fl.offset))
if err != nil { if err != nil {
return 0, err return 0, err
} }
fl.current += uintptr(last - i) fl.offset += uintptr(len(p[i:last]))
} }
return len(p), nil return len(p), nil
@ -133,12 +135,11 @@ func (fl *FlashBuffer) Close() error {
// You can only seek relative to the start. // You can only seek relative to the start.
// Also, you cannot use seek before write operations, only read. // Also, you cannot use seek before write operations, only read.
func (fl *FlashBuffer) Seek(offset int64, whence int) (int64, error) { func (fl *FlashBuffer) Seek(offset int64, whence int) (int64, error) {
fl.current = fl.start + uintptr(offset) if whence != io.SeekStart {
panic("you can only Seek relative to Start")
}
fl.offset = uintptr(offset)
return offset, nil return offset, nil
} }
// calculate page number from address
func (fl *FlashBuffer) flashPageFromAddress(address uintptr) int64 {
return int64(address-memoryStart) / fl.b.EraseBlockSize()
}