嵌入式linux之go语言开发(一)环境搭建

2019-07-13 00:36发布

go语音被称作互联网时代的"c" 。简单和高效率,用在嵌入式上也是非常合适的。应该做一个大胆的尝试...... 意义何在? 现在的设备都在朝着物联网,智能化方面发展,已不是传统的单片机控制就能完成的简单的功能, 普遍带有更高级的操作系统,比如linux和Android.而Android上开发可以使用高级语言java,或者如reaect native的html5混合开发。 但是嵌入式linux上目前还是单纯的c语言开发,涉及到网络https,json格式通信,用c去处理起来开发效率太低。还要用c去拼接字符串?而go语言的强大和高效率,正好满足这方面的要求。在这方面做个尝试,看能否带来开发效率和稳定性方面的提升, 同时也是一种学习,探索,创新的过程...... 一、环境搭建: 嵌入式机器环境Imx6 ARM 虚拟机环境ubutu14.04 64位 先下载go1.4的源码,因为自go1.4版本之后的go版本编译器都是go写的,用go自己编译自己的,go1.4是最后一个用gcc来编译的版本。 下载链接:https://dl.google.com/go/go1.4-bootstrap-20171003.tar.gz go1.4-bootstrap-20171003.tar.gz 编译go1.4: 编译也很简单, tar -zxvf go1.4-bootstrap-20171003.tar.gz -C /home/yang/go1.4/ cd /home/yang/go1.4/go/src GOOS=linux GOARCH=amd64 ./make.bash 编译完后,自动在源码所在目录里生成了bin文件夹,里面带编译好的 go命令二进制文件 要想接下来编译最新的源码使用,需把它先添加到系统的环境变量里 在/home/yang目录里有个隐藏文件 .bashrc,打开它配置环境变量 export GOROOT_BOOTSTRAP=/home/yang/go1.4/go 以下是我的环境变量的设置: export GOROOT_BOOTSTRAP= /home/yang/go1.4/go 编译新版本Go(ARM): 上面完成Go1.4的编译之后,可以利用Go1.4来编译新版本的Go 我下载的最新的go源码是go1.11版本的。 下载链接: https://dl.google.com/go/go1.11.src.tar.gz 为了使编译出来的最新的go支持arm,支持cgo, CC_FOR_TARGET 和 CXX_FOR_TARGET这两个配置项也必须要配置 export CC_FOR_TARGET=/home/yang/b503/ctools/gcc-linaro-arm-linux-gnueabihf-4.9-2014.09_linux/bin/arm-linux-gnueabihf-gcc
export CXX_FOR_TARGET=/home/yang/b503/ctools/gcc-linaro-arm-linux-gnueabihf-4.9-2014.09_linux/bin/arm-linux-gnueabihf-g++   tar -zxvf go1.11.src.tar.gz cd go1.11/src # 开启CGO编译 CGO_ENABLED=1 GOOS=linux GOARCH=arm GOARM=7 ./make.bash # 关闭CGO编译 CGO_ENABLED=0 GOOS=linux GOARCH=arm GOARM=7 ./make.bash 最好开启CGO_ENABLED,因为嵌入式涉及和C的相互调用。我这里也选择了开启。 当选择开启CGO编译时必须配置CC_FOR_TARGETCXX_FOR_TARGET两个环境变量 经过编译之后go1.11/go目录下会生成arm和amd64两个平台的Go命令和依赖包所以这个版本编译的Go命令可以进行两个平台的Go应用程序开发。 先设置好环境变量: export CC_FOR_TARGET=/home/yang/b503/ctools/gcc-linaro-arm-linux-gnueabihf-4.9-2014.09_linux/bin/arm-linux-gnueabihf-gcc
export CXX_FOR_TARGET=/home/yang/b503/ctools/gcc-linaro-arm-linux-gnueabihf-4.9-2014.09_linux/bin/arm-linux-gnueabihf-g++ export GOROOT=/home/yang/go1.11/go
export GOBIN=$GOROOT/bin
export GOPATH=/home/yang/gopath
export PATH=$PATH:$GOBIN:GOPATH/bin source .bashrc后生效 测试下: 验证Go版本
go version
# 正常情况会输出如下内容
go version go1.11 linux/amd64
编译Helloworld程序
新建test.go package main import "fmt" func main() {
    fmt.Println("Hello world")
}
编译电脑上的应用程序使用: go build test.go
编译ARM版本应用程序使用: GOOS=linux GOARCH=arm GOARM=7 go build test.go 可把编译好的test二进制文件放到开发板上验证 root@b503_lcd:/app/city_app/opt# chmod +x test2
root@b503_lcd:/app/city_app/opt# ./test2
Hello c...Go
DES test...
96d0028878d58c89
3132333435363738 go语言访问银联签到demo: package main import ( "flag" "fmt" log "github.com/jeanphorn/log4go" "github.com/larspensjo/config" "go8583/byteutil" "go8583/netutil" "go8583/up8583" "os" "strconv" ) var ( conFile = flag.String("configfile", "/config.ini", "config file") Server string = "127.0.0.1" Port int = 5050 up *up8583.Up8583 cardvailddata string cardholdsn string cardbin string ) func checkErr(err error) { if err != nil { fmt.Fprintf(os.Stderr, "Fatal error: %s", err.Error()) } } func configUP() { //获取当前路径 file, _ := os.Getwd() cfg, err := config.ReadDefault(file + *conFile) checkErr(err) //获取配置文件中的配置项 Server, err = cfg.String("SERVERCONFIG", "Server") Port, err = cfg.Int("SERVERCONFIG", "Port") log.Info("Server:%s ", Server) log.Info("Port:%d ", Port) up8583.ManNum, _ = cfg.String("UPCONFIG", "ManNum") up8583.PosNum, _ = cfg.String("UPCONFIG", "PosNum") up8583.MainKey, _ = cfg.String("UPCONFIG", "MainKey") up8583.TPDU, _ = cfg.String("UPCONFIG", "TPDU") up8583.RecSn, _ = cfg.Int("RECCONFIG", "RecSn") //记录流水 up = up8583.NewUp8583() } /* 签到处理过程 */ func QdProc() error { log.Info("connect:server=%s,port=%d ", Server, Port) conn, err := netutil.Connect(Server, Port) if err == nil { log.Info("connect ok!") } else { log.Info("connect failed!") return err } defer netutil.DisConnect(conn) up.Frame8583QD() up.Ea.PrintFields(up.Ea.Field_S) _, err = netutil.TxData(conn, up.Ea.Txbuf) if err == nil { log.Info("send ok!") } rxbuf := make([]byte, 1024) rxlen := 0 rxlen, err = netutil.RxData(conn, rxbuf) if err == nil { log.Info("recv ok!len=%d ", rxlen) err = up.Ans8583QD(rxbuf, rxlen) if err == nil { log.Info("签到成功") } else { log.Info("签到失败") log.Info(err) } } return err } /* 银联二维码交易 */ func QrcodeProc() error { log.Info("connect:server=%s,port=%d ", Server, Port) conn, err := netutil.Connect(Server, Port) if err == nil { log.Info("connect ok!") } else { log.Info("connect failed!") return err } defer netutil.DisConnect(conn) up.Frame8583Qrcode("6220485073630469936", 1) up.Ea.PrintFields(up.Ea.Field_S) _, err = netutil.TxData(conn, up.Ea.Txbuf) if err == nil { log.Info("send ok!") } rxbuf := make([]byte, 1024) rxlen := 0 rxlen, err = netutil.RxData(conn, rxbuf) if err == nil { log.Info("recv ok!len=%d ", rxlen) up.Ea.Ans8583Fields(rxbuf, rxlen) up.Ea.PrintFields(up.Ea.Field_R) } return err } /* 银联电子现金交易 */ //获取55域 IC卡数据域 /* 9F26 08 9F27 01 9F10 9F37 04 9F36 02 95 05 9A 03 9C 01 9F02 06 5F2A 02 82 02 9F1A 02 9F03 06 9F33 03 9F1E 08 84 9F09 02 9F41 04 9F34 03 9F35 01 9F63 10 9F74 06 8A 02 */ func getField55() []byte { //st := "0000000049c6f6c135bbf05b250000000001900000000000000000000000015601560051406e677c00056013071e0103900000010a010000001580b69553a06013827504000384486d25032240e0e1c80f250300021030313034353530300000000000006000064543433030310a60138275040000" st := "000000005238a6937524c97df200000000019000000000000000000000000156015600263b4f5a7c0002d413071e0103900000010a010000006615bbd6d9706013827504000743301d260522408008c00f260500021030313034353530300000000000006000064543433030310a60138275040000" //money := "190" //1.9元 //cardbin := "601382750400038" l := 0 s := "" l += 5 * 2 s += "9F2608" s += st[l : l+8*2] l += 8 * 2 s += "9F0206" s += st[l : l+6*2] l += 6 * 2 s += "9F0306" s += st[l : l+6*2] l += 6 * 2 s += "9505" s += st[l : l+5*2] l += 5 * 2 s += "9F1A02" s += st[l : l+2*2] l += 2 * 2 s += "5F2A02" s += st[l : l+2*2] l += 2 * 2 s += "9C01" s += st[l : l+1*2] l += 1 * 2 s += "9F3704" s += st[l : l+4*2] l += 4 * 2 s += "8202" s += st[l : l+2*2] l += 2 * 2 s += "9F3602" s += st[l : l+2*2] l += 2 * 2 s += "9F10" tmplen, _ := strconv.ParseInt(st[l:l+1*2], 16, 16) s += st[l : l+1*2] l += 1 * 2 s += st[l : l+int(tmplen)*2] l += 32 * 2 s += "9F2701" s += st[l : l+1*2] l += 1 * 2 s += "9F3303" s += st[l : l+3*2] l += 3 * 2 l += 1 * 2 //可选位元表 //卡有效期 cardvailddata = st[l : l+2*2] l += 2 * 2 fmt.Printf("cardvailddata:%s ", cardvailddata) //卡片序列号 cardholdsn = st[l : l+2*2] l += 2 * 2 fmt.Printf("cardholdsn:%s ", cardholdsn) //卡产品标识 s += "9F63" tmplen, _ = strconv.ParseInt(st[l:l+1*2], 16, 16) s += st[l : l+1*2] l += 1 * 2 s += st[l : l+int(tmplen)*2] l += 16 * 2 //电子现金发卡行授权码9F74 s += "9F74" tmplen, _ = strconv.ParseInt(st[l:l+1*2], 16, 16) s += st[l : l+1*2] l += 1 * 2 s += st[l : l+int(tmplen)*2] //fmt.Println(st) s += "9A03" s += "181206" s += "9F1E083030303030303030" s += "9f0902008c" s += "9f3403000000" s += "9f350136" s += "8A025931" s += "9F4104" s += fmt.Sprintf("%08d", up8583.RecSn) fmt.Println(s) return byteutil.HexStringToBytes(s) } func UpCashProc() error { fmt.Printf("connect:server=%s,port=%d ", Server, Port) conn, err := netutil.Connect(Server, Port) if err == nil { fmt.Println("connect ok!") } else { fmt.Println("connect failed!") return err } defer netutil.DisConnect(conn) field55 := getField55() //cardbin = "601382750400038" cardbin = "601382750400074" up.Frame8583UpCash(cardbin, 190, cardvailddata, cardholdsn, field55) up.Ea.PrintFields(up.Ea.Field_S) log.Info(byteutil.BytesToHexString(up.Ea.Txbuf)) _, err = netutil.TxData(conn, up.Ea.Txbuf) if err == nil { log.Info("send ok!") } rxbuf := make([]byte, 1024) rxlen := 0 rxlen, err = netutil.RxData(conn, rxbuf) if err == nil { log.Info("recv ok!len=%d ", rxlen) err = up.Ans8583UpCash(rxbuf, rxlen) if err == nil { log.Info("上送成功!") } up.Ea.PrintFields(up.Ea.Field_R) } return err } func main() { fmt.Println("test...") //获取当前路径 //file, _ := os.Getwd() // load config file, it's optional // or log.LoadConfiguration("./example.json", "json") // config file could be json or xml //mylog := log.NewDefaultLogger(log.INFO) //mylog.Info("hahaha test ...") //mylog.LoadConfiguration("./logconfig1.json") log.LoadConfiguration("./logconfig.json") up8583.Test() //log.LOGGER("").Info("category Test info test ...") log.LOGGER("Test").Info("category Test info test ...") log.LOGGER("Test").Info("category Test info test message: %s", "new test msg") log.LOGGER("Test").Debug("category Test debug test ...") log.LOGGER("Test1").Debug("category Test1 debug test ...") // Other category not exist, test log.LOGGER("Other").Debug("category Other debug test ...") // socket log test //log.LOGGER("TestSocket").Debug("category TestSocket debug test ...") // original log4go test //// log level: FINE, DEBUG, TRACE, INFO, WARNING,ERROR, CRITICAL //log.AddFilter("file", log.DEBUG, log.NewFileLogWriter("test.log", true, true)) // INFO级别+输出到文件,并开启rotate // original log4go test log.Info("nomal info test ...") log.Debug("nomal debug test ...") configUP() //up.Frame8583QD() //recvstr := "007960000001386131003111080810003800010AC0001450021122130107200800085500323231333031343931333239303039393939393930363030313433303137303131393939390011000005190030004046F161A743497B32EAC760DF5EA57DF5900ECCE3977731A7EA402DDF0000000000000000CFF1592A" //recv := byteutil.HexStringToBytes(recvstr) //ret := up.Ea.Ans8583Fields(recv, len(recv)) //if ret == 0 { // fmt.Println("解析成功") // up.Ea.PrintFields(up.Ea.Field_R) // } else { // fmt.Println("解析失败") // } err := QdProc() checkErr(err) if err == nil { err = QrcodeProc() //err = UpCashProc() checkErr(err) } //UpCashProc() //getField55() }