machine/flash: remove FlashBuffer, modify flash example to use BlockDevice interface
Signed-off-by: deadprogram <ron@hybridgroup.com>
Этот коммит содержится в:
родитель
6435f62dcc
коммит
b56a263d0d
2 изменённых файлов: 38 добавлений и 90 удалений
|
@ -7,7 +7,10 @@ import (
|
||||||
|
|
||||||
var (
|
var (
|
||||||
err error
|
err error
|
||||||
message = "1234567887654321123456788765432112345678876543211234567887654321"
|
message = "1234567887654321123456788765432112345678876543211234567887654321" +
|
||||||
|
"1234567887654321123456788765432112345678876543211234567887654321" +
|
||||||
|
"1234567887654321123456788765432112345678876543211234567887654321" +
|
||||||
|
"1234567887654321123456788765432112345678876543211234567887654321"
|
||||||
)
|
)
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
|
@ -21,30 +24,54 @@ func main() {
|
||||||
println("Flash erase block size:", machine.Flash.EraseBlockSize())
|
println("Flash erase block size:", machine.Flash.EraseBlockSize())
|
||||||
println()
|
println()
|
||||||
|
|
||||||
flash := machine.OpenFlashBuffer(machine.Flash, machine.FlashDataStart())
|
|
||||||
original := make([]byte, len(message))
|
original := make([]byte, len(message))
|
||||||
saved := make([]byte, len(message))
|
saved := make([]byte, len(message))
|
||||||
|
|
||||||
// Read flash contents on start (data shall survive power off)
|
// Read flash contents on start (data shall survive power off)
|
||||||
print("Reading data from flash: ")
|
println("Reading original data from flash:")
|
||||||
_, err = flash.Read(original)
|
_, err = machine.Flash.ReadAt(original, 0)
|
||||||
checkError(err)
|
checkError(err)
|
||||||
println(string(original))
|
println(string(original))
|
||||||
|
|
||||||
|
// erase flash
|
||||||
|
println("Erasing flash...")
|
||||||
|
needed := int64(len(message)) / machine.Flash.EraseBlockSize()
|
||||||
|
if needed == 0 {
|
||||||
|
// have to erase at least 1 block
|
||||||
|
needed = 1
|
||||||
|
}
|
||||||
|
|
||||||
|
err := machine.Flash.EraseBlocks(0, needed)
|
||||||
|
checkError(err)
|
||||||
|
|
||||||
// Write the message to flash
|
// Write the message to flash
|
||||||
print("Writing data to flash: ")
|
println("Writing new data to flash:")
|
||||||
flash.Seek(0, 0) // rewind back to beginning
|
_, err = machine.Flash.WriteAt([]byte(message), 0)
|
||||||
_, err = flash.Write([]byte(message))
|
|
||||||
checkError(err)
|
checkError(err)
|
||||||
println(string(message))
|
println(string(message))
|
||||||
|
|
||||||
// Read back flash contents after write (verify data is the same as written)
|
// Read back flash contents after write (verify data is the same as written)
|
||||||
print("Reading data back from flash: ")
|
println("Reading data back from flash: ")
|
||||||
flash.Seek(0, 0) // rewind back to beginning
|
_, err = machine.Flash.ReadAt(saved, 0)
|
||||||
_, err = flash.Read(saved)
|
|
||||||
checkError(err)
|
checkError(err)
|
||||||
|
if !equal(saved, []byte(message)) {
|
||||||
|
println("data verify error")
|
||||||
|
}
|
||||||
|
|
||||||
println(string(saved))
|
println(string(saved))
|
||||||
println()
|
println("Done.")
|
||||||
|
}
|
||||||
|
|
||||||
|
func equal(a, b []byte) bool {
|
||||||
|
if len(a) != len(b) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
for i, v := range a {
|
||||||
|
if v != b[i] {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
func checkError(err error) {
|
func checkError(err error) {
|
||||||
|
|
|
@ -64,82 +64,3 @@ type BlockDevice interface {
|
||||||
// EraseBlockSize to map addresses to blocks.
|
// EraseBlockSize to map addresses to blocks.
|
||||||
EraseBlocks(start, len int64) error
|
EraseBlocks(start, len int64) error
|
||||||
}
|
}
|
||||||
|
|
||||||
// FlashBuffer implements the ReadWriteCloser interface using the BlockDevice interface.
|
|
||||||
type FlashBuffer struct {
|
|
||||||
b BlockDevice
|
|
||||||
|
|
||||||
// start is actual address
|
|
||||||
start uintptr
|
|
||||||
|
|
||||||
// offset is relative to start
|
|
||||||
offset uintptr
|
|
||||||
}
|
|
||||||
|
|
||||||
// OpenFlashBuffer opens a FlashBuffer.
|
|
||||||
func OpenFlashBuffer(b BlockDevice, address uintptr) *FlashBuffer {
|
|
||||||
return &FlashBuffer{b: b, start: address}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Read data from a FlashBuffer.
|
|
||||||
func (fl *FlashBuffer) Read(p []byte) (n int, err error) {
|
|
||||||
n, err = fl.b.ReadAt(p, int64(fl.offset))
|
|
||||||
fl.offset += uintptr(n)
|
|
||||||
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// Write data to a FlashBuffer.
|
|
||||||
func (fl *FlashBuffer) Write(p []byte) (n int, err error) {
|
|
||||||
// any new pages needed?
|
|
||||||
// NOTE probably will not work as expected if you try to write over page boundary
|
|
||||||
// of pages with different sizes.
|
|
||||||
pagesize := uintptr(fl.b.EraseBlockSize())
|
|
||||||
|
|
||||||
// calculate currentPageBlock relative to fl.start, meaning that
|
|
||||||
// block 0 -> fl.start
|
|
||||||
// block 1 -> fl.start + pagesize
|
|
||||||
// block 2 -> fl.start + pagesize*2
|
|
||||||
// ...
|
|
||||||
currentPageBlock := (fl.start + fl.offset - FlashDataStart()) + (pagesize-1)/pagesize
|
|
||||||
lastPageBlockNeeded := (fl.start + fl.offset + uintptr(len(p)) - FlashDataStart()) + (pagesize-1)/pagesize
|
|
||||||
|
|
||||||
// erase enough blocks to hold the data
|
|
||||||
if err := fl.b.EraseBlocks(int64(currentPageBlock), int64(lastPageBlockNeeded-currentPageBlock)); err != nil {
|
|
||||||
return 0, err
|
|
||||||
}
|
|
||||||
|
|
||||||
// write the data
|
|
||||||
for i := 0; i < len(p); i += int(pagesize) {
|
|
||||||
var last int = i + int(pagesize)
|
|
||||||
if i+int(pagesize) > len(p) {
|
|
||||||
last = len(p)
|
|
||||||
}
|
|
||||||
|
|
||||||
_, err := fl.b.WriteAt(p[i:last], int64(fl.offset))
|
|
||||||
if err != nil {
|
|
||||||
return 0, err
|
|
||||||
}
|
|
||||||
fl.offset += uintptr(len(p[i:last]))
|
|
||||||
}
|
|
||||||
|
|
||||||
return len(p), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Close the FlashBuffer.
|
|
||||||
func (fl *FlashBuffer) Close() error {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Seek implements io.Seeker interface, but with limitations.
|
|
||||||
// You can only seek relative to the start.
|
|
||||||
// Also, you cannot use seek before write operations, only read.
|
|
||||||
func (fl *FlashBuffer) Seek(offset int64, whence int) (int64, error) {
|
|
||||||
if whence != io.SeekStart {
|
|
||||||
panic("you can only Seek relative to Start")
|
|
||||||
}
|
|
||||||
|
|
||||||
fl.offset = uintptr(offset)
|
|
||||||
|
|
||||||
return offset, nil
|
|
||||||
}
|
|
||||||
|
|
Загрузка…
Создание таблицы
Сослаться в новой задаче