From acd8baadbf34b65fafd09091fb56ff13c7a057b9 Mon Sep 17 00:00:00 2001 From: Adam Kramer Date: Sat, 7 Mar 2015 17:57:06 -0800 Subject: [PATCH 1/5] Support the new IO port range for raspberry pi 2. --- rpio.go | 32 ++++++++++++++++++++++++++++++-- 1 file changed, 30 insertions(+), 2 deletions(-) diff --git a/rpio.go b/rpio.go index c02353f..a6eb505 100644 --- a/rpio.go +++ b/rpio.go @@ -56,6 +56,8 @@ http://www.raspberrypi.org/wp-content/uploads/2012/02/BCM2835-ARM-Peripherals.pd package rpio import ( + "bytes" + "io/ioutil" "os" "reflect" "sync" @@ -72,9 +74,12 @@ type Pull uint8 // Memory offsets for gpio, see the spec for more details const ( bcm2835Base = 0x20000000 - gpioBase = bcm2835Base + 0x200000 + pi1GPIOBase = bcm2835Base + 0x200000 memLength = 4096 + bcm2836Base = 0x3f000000 + pi2GPIOBase = bcm2836Base + 0x200000 + pinMask uint32 = 7 // 0b111 - pinmode is 3 bits ) @@ -277,10 +282,15 @@ func Open() (err error) { memlock.Lock() defer memlock.Unlock() + GPIOBase := int64(pi1GPIOBase) + if detectPiVersion() == 2 { + GPIOBase = pi2GPIOBase + } + // Memory map GPIO registers to byte array mem8, err = syscall.Mmap( int(file.Fd()), - gpioBase, + GPIOBase, memLength, syscall.PROT_READ|syscall.PROT_WRITE, syscall.MAP_SHARED) @@ -305,3 +315,21 @@ func Close() error { defer memlock.Unlock() return syscall.Munmap(mem8) } + +// Read /proc/cpuinfo and detect whether we're running on an RPI1 or RPI2. +// Returns 1 or 2 depending on platform. +func detectPiVersion() int { + cpuinfo, err := os.Open("/proc/cpuinfo") + if err != nil { + panic(err) + } + data, err := ioutil.ReadAll(cpuinfo) + if err != nil { + panic(err) + } + if bytes.Contains(data, []byte("BCM2709")) { + return 2 + } else { + return 1 + } +} From cf3a8b7ed1418a4d88798ee119c06b77c956833a Mon Sep 17 00:00:00 2001 From: Adam Kramer Date: Sat, 7 Mar 2015 18:45:00 -0800 Subject: [PATCH 2/5] Using a better method of base address detection. --- rpio.go | 37 +++++++++++++++++-------------------- 1 file changed, 17 insertions(+), 20 deletions(-) diff --git a/rpio.go b/rpio.go index a6eb505..15515bc 100644 --- a/rpio.go +++ b/rpio.go @@ -57,7 +57,7 @@ package rpio import ( "bytes" - "io/ioutil" + "encoding/binary" "os" "reflect" "sync" @@ -77,9 +77,6 @@ const ( pi1GPIOBase = bcm2835Base + 0x200000 memLength = 4096 - bcm2836Base = 0x3f000000 - pi2GPIOBase = bcm2836Base + 0x200000 - pinMask uint32 = 7 // 0b111 - pinmode is 3 bits ) @@ -282,15 +279,10 @@ func Open() (err error) { memlock.Lock() defer memlock.Unlock() - GPIOBase := int64(pi1GPIOBase) - if detectPiVersion() == 2 { - GPIOBase = pi2GPIOBase - } - // Memory map GPIO registers to byte array mem8, err = syscall.Mmap( int(file.Fd()), - GPIOBase, + getGPIOBase(), memLength, syscall.PROT_READ|syscall.PROT_WRITE, syscall.MAP_SHARED) @@ -318,18 +310,23 @@ func Close() error { // Read /proc/cpuinfo and detect whether we're running on an RPI1 or RPI2. // Returns 1 or 2 depending on platform. -func detectPiVersion() int { - cpuinfo, err := os.Open("/proc/cpuinfo") +func getGPIOBase() (base int64) { + base = pi1GPIOBase + ranges, err := os.Open("/proc/device-tree/soc/ranges") + defer ranges.Close() if err != nil { - panic(err) + return } - data, err := ioutil.ReadAll(cpuinfo) + b := make([]byte, 4) + n, err := ranges.ReadAt(b, 4) + if n != 4 || err != nil { + return + } + buf := bytes.NewReader(b) + var out int64 + err = binary.Read(buf, binary.LittleEndian, &out) if err != nil { - panic(err) - } - if bytes.Contains(data, []byte("BCM2709")) { - return 2 - } else { - return 1 + return } + return out + 0x200000 } From 733fee47fc432778a91f8e045bf7e7e004b96170 Mon Sep 17 00:00:00 2001 From: Adam Kramer Date: Sat, 7 Mar 2015 18:53:00 -0800 Subject: [PATCH 3/5] Fixing a bug (oops) --- rpio.go | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/rpio.go b/rpio.go index 15515bc..3589068 100644 --- a/rpio.go +++ b/rpio.go @@ -58,6 +58,7 @@ package rpio import ( "bytes" "encoding/binary" + "fmt" "os" "reflect" "sync" @@ -323,10 +324,11 @@ func getGPIOBase() (base int64) { return } buf := bytes.NewReader(b) - var out int64 - err = binary.Read(buf, binary.LittleEndian, &out) + var out uint32 + err = binary.Read(buf, binary.BigEndian, &out) if err != nil { return } - return out + 0x200000 + fmt.Printf("%X", out) + return int64(out + 0x200000) } From 10a90652fdb9d35163cf397fc52e5ece369bf5d3 Mon Sep 17 00:00:00 2001 From: Adam Kramer Date: Sat, 7 Mar 2015 18:54:44 -0800 Subject: [PATCH 4/5] Fixed the comment for getGPIOBase() --- rpio.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/rpio.go b/rpio.go index 3589068..92983b2 100644 --- a/rpio.go +++ b/rpio.go @@ -309,8 +309,8 @@ func Close() error { return syscall.Munmap(mem8) } -// Read /proc/cpuinfo and detect whether we're running on an RPI1 or RPI2. -// Returns 1 or 2 depending on platform. +// Read /proc/device-tree/soc/ranges and determine the base address. +// Use the default Raspberry Pi 1 base address if this fails. func getGPIOBase() (base int64) { base = pi1GPIOBase ranges, err := os.Open("/proc/device-tree/soc/ranges") From 07b12a153915234e6a289b8f1aa4fd0152e68938 Mon Sep 17 00:00:00 2001 From: Adam Kramer Date: Sat, 7 Mar 2015 19:01:39 -0800 Subject: [PATCH 5/5] Removing a debugging statement --- rpio.go | 2 -- 1 file changed, 2 deletions(-) diff --git a/rpio.go b/rpio.go index 92983b2..12cf978 100644 --- a/rpio.go +++ b/rpio.go @@ -58,7 +58,6 @@ package rpio import ( "bytes" "encoding/binary" - "fmt" "os" "reflect" "sync" @@ -329,6 +328,5 @@ func getGPIOBase() (base int64) { if err != nil { return } - fmt.Printf("%X", out) return int64(out + 0x200000) }