您尚未登录。

楼主 #1 2018-11-12 09:20:24

晕哥
管理员
注册时间: 2017-09-06
已发帖子: 9,342
积分: 9202

网友 @chong 提供的 f1c100s linux 下直接写 spi nand u-boot的golang程序代码

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 := tx

    if 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 := 0

    index := 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)
    */

}





离线

楼主 #3 2018-11-12 14:47:22

晕哥
管理员
注册时间: 2017-09-06
已发帖子: 9,342
积分: 9202

Re: 网友 @chong 提供的 f1c100s linux 下直接写 spi nand u-boot的golang程序代码

arphone 说:

cool .... 感谢分享!

因为 linux4.19 支持 spi nand, 然后利用linux驱动写u-boot到spi nand, 个人猜测.





离线

页脚

工信部备案:粤ICP备20025096号 Powered by FluxBB

感谢为中文互联网持续输出优质内容的各位老铁们。 QQ: 516333132, 微信(wechat): whycan_cn (哇酷网/挖坑网/填坑网) service@whycan.cn