1、手上的这个hilink的mt7628开发板的系统里面用reg的软件包来控制io口的。
2、用golang操作reg命令不方便。
3、所以用mmap来操作io口。
直接干代码
①、以下是mmap.go
package mmap
import (
"fmt"
"os"
"syscall"
"unsafe"
// "github.com/edsrzf/mmap-go"
)
func check(e error) {
if e != nil {
fmt.Println(e)
}
}
const (
gpioBase = 0x00000000 + 0x10000000 // MT6826寄存器基地址
gpioRegs = 426 // number of GPIO registers
gpioRegBufferSize = gpioRegs * 4 // 32 bits hardcoded here
RALINK_GPIO_DIR_IN = 0
RALINK_GPIO_DIR_OUT = 1
RALINK_REG_PIOINT = 0x690
RALINK_REG_PIOEDGE = 0x6A0
RALINK_REG_PIORENA = 0x650
RALINK_REG_PIOFENA = 0x660
RALINK_REG_PIODATA = 0x620
RALINK_REG_PIODIR = 0x600
RALINK_REG_PIOSET = 0x630
RALINK_REG_PIORESET = 0x640
RALINK_REG_PIO6332INT = 0x694
RALINK_REG_PIO6332EDGE = 0x6A4
RALINK_REG_PIO6332RENA = 0x654
RALINK_REG_PIO6332FENA = 0x664
RALINK_REG_PIO6332DATA = 0x624
RALINK_REG_PIO6332DIR = 0x604
RALINK_REG_PIO6332SET = 0x634
RALINK_REG_PIO6332RESET = 0x644
RALINK_REG_PIO9564INT = 0x698
RALINK_REG_PIO9564EDGE = 0x6A8
RALINK_REG_PIO9564RENA = 0x658
RALINK_REG_PIO9564FENA = 0x668
RALINK_REG_PIO9564DATA = 0x628
RALINK_REG_PIO9564DIR = 0x608
RALINK_REG_PIO9564SET = 0x638
RALINK_REG_PIO9564RESET = 0x648
)
var Gpio_mmap_reg *[gpioRegs]uint32
func Gpio_mmap() int {
f, err := os.OpenFile("/dev/mem", os.O_RDWR|os.O_SYNC, 0644)
check(err)
defer f.Close()
/*第一种方式使用mmap-go库 ("github.com/edsrzf/mmap-go")*/
// mapped, err := mmap.MapRegion(f, gpioRegBufferSize, mmap.RDWR, 0, gpioBase)
// check(err)
/*第一种方式使用syscall库 ("syscall")*/
mapped, err := syscall.Mmap(int(f.Fd()), gpioBase, gpioRegBufferSize, syscall.PROT_WRITE, syscall.MAP_SHARED)
if nil != err {
fmt.Println(err)
return -1
}
Gpio_mmap_reg = (*[gpioRegs]uint32)(unsafe.Pointer(&mapped[0]))
//fmt.Printf("regs1=0x%2x\r\n", &Gpio_mmap_reg[0])
//fmt.Println(reflect.TypeOf(Gpio_mmap_reg))
return 0
}
func mt76x8_gpio_reg_choose(reg *[gpioRegs]uint32, reg_addr uint32) (reg_mmap_addr *uint32) {
var p0 *uint32 = ®[0]
var p1 unsafe.Pointer = unsafe.Pointer(p0)
//fmt.Printf("*p1=0x%2x\r\n", p1)
var p2 uintptr = uintptr(p1)
p2 += uintptr(reg_addr)
// fmt.Println(reflect.TypeOf(p2))
var p3 = unsafe.Pointer(p2)
var p4 *uint32 = (*uint32)(p3)
// fmt.Printf("*p4=0x%2x\r\n", *p4)
return p4
}
func Mt76x8_gpio_get_pin(pin int) int {
var tmp uint32 = 0
/* MT7621, MT7628 */
if pin <= 31 {
// tmp = *mt76x8_gpio_reg_choose(Gpio_mmap_reg, RALINK_REG_PIODIR)
tmp = (tmp >> pin) & uint32(1)
} else if pin <= 63 {
tmp = *mt76x8_gpio_reg_choose(Gpio_mmap_reg, RALINK_REG_PIO6332DATA)
tmp = (tmp >> (pin - 32)) & uint32(1)
//fmt.Printf("tmp=0x%2x\r\n", tmp)
} else if pin <= 95 {
// tmp = *mt76x8_gpio_reg_choose(Gpio_mmap_reg, RALINK_REG_PIO9564DATA)
tmp = (tmp >> (pin - 64)) & uint32(1)
tmp = (tmp >> (pin - 24)) & uint32(1)
}
return int(tmp)
}
func Mt76x8_gpio_set_pin_direction(pin int, is_output int) {
var tmp uint32 = 0
/* MT7621, MT7628 */
if pin <= 31 {
tmp = *mt76x8_gpio_reg_choose(Gpio_mmap_reg, RALINK_REG_PIODIR)
if is_output == 1 {
tmp |= (uint32(1) << pin)
} else {
tmp &= ^(uint32(1) << pin)
}
*mt76x8_gpio_reg_choose(Gpio_mmap_reg, RALINK_REG_PIODIR) = tmp
} else if pin <= 63 {
tmp = *mt76x8_gpio_reg_choose(Gpio_mmap_reg, RALINK_REG_PIO6332DIR)
if is_output == 1 {
tmp |= (uint32(1) << (pin - 32))
} else {
tmp &= ^(uint32(1) << (pin - 32))
}
*mt76x8_gpio_reg_choose(Gpio_mmap_reg, RALINK_REG_PIO6332DIR) = tmp
} else if pin <= 95 {
tmp = *mt76x8_gpio_reg_choose(Gpio_mmap_reg, RALINK_REG_PIO9564DIR)
if is_output == 1 {
tmp |= (uint32(1) << (pin - 64))
} else {
tmp &= ^(uint32(1) << (pin - 64))
}
*mt76x8_gpio_reg_choose(Gpio_mmap_reg, RALINK_REG_PIO9564DIR) = tmp
}
}
func Mt76x8_gpio_set_pin_value(pin int, value int) {
var tmp uint32 = 0
/* MT7621, MT7628 */
if pin <= 31 {
tmp = (uint32(1) << pin)
if value == 1 {
*mt76x8_gpio_reg_choose(Gpio_mmap_reg, RALINK_REG_PIOSET) = tmp
} else {
*mt76x8_gpio_reg_choose(Gpio_mmap_reg, RALINK_REG_PIORESET) = tmp
}
} else if pin <= 63 {
tmp = (uint32(1) << (pin - 32))
if value == 1 {
*mt76x8_gpio_reg_choose(Gpio_mmap_reg, RALINK_REG_PIO6332SET) = tmp
} else {
*mt76x8_gpio_reg_choose(Gpio_mmap_reg, RALINK_REG_PIO6332RESET) = tmp
}
} else if pin <= 95 {
tmp = (uint32(1) << (pin - 64))
if value == 1 {
*mt76x8_gpio_reg_choose(Gpio_mmap_reg, RALINK_REG_PIO9564SET) = tmp
} else {
*mt76x8_gpio_reg_choose(Gpio_mmap_reg, RALINK_REG_PIO9564RESET) = tmp
}
}
}
②、以下是copy.go
package copy
import (
"fmt"
"io"
"os"
)
//自己编写一个函数,接收两个文件路径 srcFileName dstFileName
func CopyFile(srcFileName string, dstFileName string) (err error) {
sFile, err1 := os.Open(srcFileName)
defer sFile.Close() //必须关闭
dFile, err2 := os.OpenFile(dstFileName, os.O_CREATE|os.O_WRONLY|os.O_TRUNC, 0666)
defer dFile.Close() //必须关闭
if err1 != nil {
return err1
}
if err2 != nil {
return err2
}
var tempSlice = make([]byte, 1280)
for {
//读取数据
n1, err := sFile.Read(tempSlice)
if err == io.EOF {
break
}
if err != nil {
return err
}
// 写入数据
if _, err := dFile.Write(tempSlice[:n1]); err != nil {
return err
}
}
return nil
}
func Recover() {
//调用CopyFile 完成文件拷贝
srcFile := "/data/root/NUC980_Sleep/go/NUC980/gpio_test/1.txt"
dstFile := "/data/root/NUC980_Sleep/go/NUC980/gpio_test/2.txt"
err := CopyFile(srcFile, dstFile)
if err == nil {
fmt.Printf("拷贝完成\n")
} else {
fmt.Printf("拷贝错误 err=%v\n", err)
}
}
③、以下是main.go
/*
Playing around with Go on the Raspberry Pi, doing some trivial GPIO stuff
using the unsafe/dangerous/ugly but fast mmap approach.
*/
package main
import (
"fmt"
"io/ioutil"
"mmap/copy"
"mmap/mmap"
"os"
"os/exec"
"sync"
"time"
// "github.com/edsrzf/mmap-go"
)
var wg sync.WaitGroup
var KeyPressNo int = 0
//LED_PC13 绿色指示灯
func LED_GPIO_44() {
mmap.Mt76x8_gpio_set_pin_direction(44, 1)
for {
mmap.Mt76x8_gpio_set_pin_value(44, 1)
time.Sleep(100 * time.Millisecond)
mmap.Mt76x8_gpio_set_pin_value(44, 0)
time.Sleep(100 * time.Millisecond)
}
//wg.Done()
}
func Watchdog() {
file, err := os.OpenFile("/dev/watchdog", os.O_WRONLY, 0666)
if err != nil {
fmt.Println("open file failed, err:", err)
return
}
defer file.Close()
for {
file.WriteString("1")
time.Sleep(500 * time.Millisecond)
}
//wg.Done()
}
func KeyScan() {
for {
KeyValue := mmap.Mt76x8_gpio_get_pin(38)
if KeyValue == 1 {
KeyPressNo = 0
} else if KeyValue == 0 {
KeyPressNo++
if KeyPressNo > 12 {
fmt.Println("Recover system")
copy.Recover()
time.Sleep(2000 * time.Millisecond)
ExecCommand("reboot -f")
}
}
time.Sleep(1000 * time.Millisecond)
}
//wg.Done()
}
func ExecCommand(strCommand string) string {
cmd := exec.Command("sh", "-c", strCommand)
stdout, _ := cmd.StdoutPipe()
if err := cmd.Start(); err != nil {
fmt.Println("Execute failed when Start:" + err.Error())
return ""
}
out_bytes, _ := ioutil.ReadAll(stdout)
stdout.Close()
if err := cmd.Wait(); err != nil {
fmt.Println("Execute failed when Wait:" + err.Error())
return ""
}
return string(out_bytes)
}
func main() {
mmap.Gpio_mmap()
wg.Add(1)
go LED_GPIO_44()
wg.Add(1)
go Watchdog()
wg.Add(1)
go KeyScan()
wg.Wait()
fmt.Println("进程退出")
}
④、vscode上编译为mips架构上的指令:
GOOS=linux GOARCH=mipsle go build -ldflags="-s -w" main.go