spinand_GD5F1GQ4UAYIG_uboot_debug_code.go 文件内容:
package main
import (
"encoding/hex"
"flag"
"fmt"
"io/ioutil"
"log"
//"math/rand"
//"os"
"strings""periph.io/x/periph/conn/physic"
"periph.io/x/periph/conn/spi"
"periph.io/x/periph/conn/spi/spireg"
"periph.io/x/periph/host"
)var spiConn spi.Conn
var (
FEATURE_PROTECION = byte(0xa0)
FEATURE_FEATURE = byte(0xb0)
FEATURE_STATUS = byte(0xc0)
)var (
CMD_GET_ID = byte(0x9f)
CMD_GET_FEATURE = byte(0xf)
CMD_SET_FEATURE = byte(0x1f)
CMD_ERASE = byte(0xd8)
CMD_WRITE_ENABLE = byte(0x06)
CMD_WRITE_DISABLE = byte(0x04)
CMD_PAGE_READ = byte(0x13)
CMD_CACHE_READ = byte(0x03)
CMD_PROGRAM_LOAD = byte(0x02)
CMD_PROGRAM_EXECUTE = byte(0x10)
CMD_RESET = byte(0xff)
)var (
STATUS_QIP = byte(1) << 0
STATUS_WEL = byte(1) << 1
STATUS_E_FAIL = byte(1) << 2
STATUS_P_FAIL = byte(1) << 3
STATUS_ECCS0 = byte(1) << 4
STATUS_ECCS1 = byte(1) << 5
)var (
FEATURE_OTP_EN = 1 << 6
FEATURE_ECC_EN = 1 << 4
)func sendCmd(cmd []byte, size int) []byte {
data := make([]byte, size)
tx := append(cmd, data...)
rx := txif err := spiConn.Tx(tx, rx); err != nil {
log.Fatal(err)
}if size == 0 {
return nil
}return rx[len(cmd):]
}func readID() {
id := sendCmd([]byte{CMD_GET_ID, 0x00}, 2)
fmt.Println("Read id : ", hex.EncodeToString(id))
}func readPage(page int) []byte {
sendCmd([]byte{CMD_PAGE_READ, 0xaa, byte(page >> 8 & 0xff), byte(page & 0xff)}, 0)
busyWaitUntilReady()
data := sendCmd([]byte{CMD_CACHE_READ, 0x0, 0x0, 0x0}, 2048)
fmt.Println("Read Page: ", hex.EncodeToString(data))
return data
}func erasePage(page int) {
fmt.Println("erasing", page)
sendCmd([]byte{CMD_WRITE_ENABLE}, 0)sendCmd([]byte{CMD_ERASE, 0, byte(page >> 8 & 0xff), byte(page & 0xff)}, 0)
busyWaitUntilReady()
status := readStatus()if status != 0 {
fmt.Println("erase status: ", status)
}if readStatus()&STATUS_E_FAIL == 1 {
fmt.Println("erase failed: ", page)
panic("erase failed:")
}
}func readStatus() byte {
status := sendCmd([]byte{CMD_GET_FEATURE, FEATURE_STATUS}, 1)
return status[0]
}func busyWaitUntilReady() bool {
for {
status := readStatus()
if status&STATUS_QIP == 0 {
break
}
}return true
}func dumpOtp() {
//dump feature
write := []byte{0xf, 0xB0, 0xAA}
read := make([]byte, len(write))
if err := spiConn.Tx(write, read); err != nil {
log.Fatal(err)
}fmt.Println("get feature: ", hex.EncodeToString(read))
//set feature
write = []byte{0x1f, 0xB0, 0x40}
read = make([]byte, len(write))
if err := spiConn.Tx(write, read); err != nil {
log.Fatal(err)
}
write = []byte{0xf, 0xB0, 0xAA}
read = make([]byte, len(write))
if err := spiConn.Tx(write, read); err != nil {
log.Fatal(err)
}fmt.Println("get feature: ", hex.EncodeToString(read))
readPage(0)
readPage(1)
readPage(2)
readPage(3)}
func unlockAll() {
//unlock
write := []byte{0x1f, 0xa0, 0x0}
read := make([]byte, len(write))
if err := spiConn.Tx(write, read); err != nil {
log.Fatal(err)
}}
func writePage(page int32, data []byte) {
send := append([]byte{CMD_PROGRAM_LOAD, byte(0x0), byte(0x0)}, data...)
sendCmd(send, 0)
sendCmd([]byte{CMD_WRITE_ENABLE}, 0)
sendCmd([]byte{CMD_PROGRAM_EXECUTE, 0, byte(page >> 8 & 0xff), byte(page & 0xff)}, 0)
busyWaitUntilReady()
fmt.Println("status :", readStatus())}
func reset() {
sendCmd([]byte{CMD_RESET}, 0)
}
func main() {fmt.Println(flag.NArg())
// SPI.max_speed_hz = 2000000
// SPI.mode = 0b00
// # SPI device, bus = 0, device = 0
// SPI = spidev.SpiDev(0, 0)
// if err := embd.InitSPI(); err != nil {
// log.Println("Unable to Init SPI ", err)
// }
// spibus = embd.NewSPIBus(embd.SPIMode0, channel, speed, bpw, delay)if _, err := host.Init(); err != nil {
log.Fatal(err)
}// Enumerate all SPI ports available and the corresponding pins.
fmt.Print("SPI ports available---:\n")
for _, ref := range spireg.All() {
fmt.Printf("- %s\n", ref.Name)
if ref.Number != -1 {
fmt.Printf(" %d\n", ref.Number)
}
if len(ref.Aliases) != 0 {
fmt.Printf(" %s\n", strings.Join(ref.Aliases, " "))
}spiPort, err := ref.Open()
if err != nil {
fmt.Printf(" Failed to open: %v", err)
}spiConn, err = spiPort.Connect(40*physic.MegaHertz, spi.Mode0, 8)
if err != nil {
log.Fatal(err)
}}
unlockAll()
//program otp
//dumpOtp()
/*
for i := 0; i < 4; i++ {
token := make([]byte, 2112)
rand.Read(token)
writePage(int32(i), token)
busyWaitUntilReady()
}
*///erase all
for i := 0; i < 1024*64; i += 64 {
erasePage(i)
}/*
f, err := os.Create("data")
if err != nil {
panic(err)
}defer f.Close()
for i := 0; i < 1024*64; i++ {
dat := readPage(int32(i))
f.Write(dat)
// fmt.Println("write page", i)
}
*/
//program random data test/*
for i := 0; i < 1024*64; i++ {
readPage(i)
token := make([]byte, 2112)
rand.Read(token)
writePage(int32(i), token)
busyWaitUntilReady()
}
*/dat, err := ioutil.ReadFile("/home/root/u-boot.img")
if err != nil {
fmt.Println("read file failed")
}
p := 0index := 0
count := 0
for i := len(dat); i > 0; {
count = 2048
if i < 2048 {
count = i
}
p = index / 2048
fmt.Println("write uboot write page: ", p)
writePage(int32(p), dat[index:index+count])
busyWaitUntilReady()
i -= count
index += count}
//this is the key point
// f1c100s start load uboot spl from 224 page
// f1c100s assume flash was 1024 byte per page
// uboot spl should not exceed 20k bytes ?
//
dat, err = ioutil.ReadFile("/home/root/sunxi-spl.bin")
if err != nil {
fmt.Println("read file failed")
}
p = 224
for i := 0; i < len(dat)/1024; i++ {
fmt.Println("write spl write page: ", p)
writePage(int32(p), dat[i*1024:(i+1)*1024])
busyWaitUntilReady()
p++
}// erasePage(0)
//writePage(0, []byte{0xaa, 0xaa, 0xaa, 0xaa})
//writePage(1, []byte{0xaa, 0xaa, 0xaa, 0xaa})
//writePage(2, []byte{0xaa, 0xaa, 0xaa, 0xaa})
/*
erasePage(192)
readPage(224)
readPage(225)
*/}
离线