# GPIO programming on RPi



## balanga (Feb 3, 2018)

I want to get started on GPIO programming on my RPi and found some tutorials for beginners here

There is some sample code in C and Python, and whilst I know I can't use the Python example (not yet anyway...), should I expect to be able to get this to work?


```
#include <wiringPi.h>
#include <stdio.h>

#define LedPin 0

int main(void)
{
if(wiringPiSetup() == -1){ //when initialize wiring failed,print messageto screen
printf("setup wiringPi failed !");
return 1; 
}
printf("linker LedPin : GPIO %d(wiringPi pin)\n",LedPin); //when initialize wiring successfully,print message to screen

pinMode(LedPin, OUTPUT);

while(1){
digitalWrite(LedPin, LOW); //led on
delay(500);
digitalWrite(LedPin, HIGH); //led off
delay(500);
}

return 0;
}
```


----------



## aragats (Feb 3, 2018)

I believe, we already discussed similar things in another thread here.
The problem is that _wiringPi_ library relies on the virtual filesystem /sys/class/gpio which is a part of Linux kernel and does not exist in FreeBSD.


----------



## balanga (Feb 3, 2018)

Loooks like I'm going to have a problem with wiringPi.h...

I managed to find it here


```
/*
 * wiringPi.h:
 *    Arduino like Wiring library for the Raspberry Pi.
 *    Copyright (c) 2012-2017 Gordon Henderson
 ***********************************************************************
 * This file is part of wiringPi:
 *    https://projects.drogon.net/raspberry-pi/wiringpi/
 *
 *    wiringPi is free software: you can redistribute it and/or modify
 *    it under the terms of the GNU Lesser General Public License as published by
 *    the Free Software Foundation, either version 3 of the License, or
 *    (at your option) any later version.
 *
 *    wiringPi is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *    GNU Lesser General Public License for more details.
 *
 *    You should have received a copy of the GNU Lesser General Public License
 *    along with wiringPi.  If not, see <http://www.gnu.org/licenses/>.
 ***********************************************************************
 */

#ifndef    __WIRING_PI_H__
#define    __WIRING_PI_H__

// C doesn't have true/false by default and I can never remember which
//    way round they are, so ...
//    (and yes, I know about stdbool.h but I like capitals for these and I'm old)

#ifndef    TRUE
#  define    TRUE    (1==1)
#  define    FALSE    (!TRUE)
#endif

// GCC warning suppressor

#define    UNU    __attribute__((unused))

// Mask for the bottom 64 pins which belong to the Raspberry Pi
//    The others are available for the other devices

#define    PI_GPIO_MASK    (0xFFFFFFC0)

// Handy defines

// wiringPi modes

#define    WPI_MODE_PINS         0
#define    WPI_MODE_GPIO         1
#define    WPI_MODE_GPIO_SYS     2
#define    WPI_MODE_PHYS         3
#define    WPI_MODE_PIFACE         4
#define    WPI_MODE_UNINITIALISED    -1

// Pin modes

#define    INPUT             0
#define    OUTPUT             1
#define    PWM_OUTPUT         2
#define    GPIO_CLOCK         3
#define    SOFT_PWM_OUTPUT         4
#define    SOFT_TONE_OUTPUT     5
#define    PWM_TONE_OUTPUT         6

#define    LOW             0
#define    HIGH             1

// Pull up/down/none

#define    PUD_OFF             0
#define    PUD_DOWN         1
#define    PUD_UP             2

// PWM

#define    PWM_MODE_MS        0
#define    PWM_MODE_BAL        1

// Interrupt levels

#define    INT_EDGE_SETUP        0
#define    INT_EDGE_FALLING    1
#define    INT_EDGE_RISING        2
#define    INT_EDGE_BOTH        3

// Pi model types and version numbers
//    Intended for the GPIO program Use at your own risk.

#define    PI_MODEL_A         0
#define    PI_MODEL_B         1
#define    PI_MODEL_AP         2
#define    PI_MODEL_BP         3
#define    PI_MODEL_2         4
#define    PI_ALPHA         5
#define    PI_MODEL_CM         6
#define    PI_MODEL_07         7
#define    PI_MODEL_3         8
#define    PI_MODEL_ZERO         9
#define    PI_MODEL_CM3        10
#define    PI_MODEL_ZERO_W        12

#define    PI_VERSION_1        0
#define    PI_VERSION_1_1        1
#define    PI_VERSION_1_2        2
#define    PI_VERSION_2        3

#define    PI_MAKER_SONY        0
#define    PI_MAKER_EGOMAN        1
#define    PI_MAKER_EMBEST        2
#define    PI_MAKER_UNKNOWN    3

extern const char *piModelNames    [16] ;
extern const char *piRevisionNames [16] ;
extern const char *piMakerNames    [16] ;
extern const int   piMemorySize    [ 8] ;


//    Intended for the GPIO program Use at your own risk.

// Threads

#define    PI_THREAD(X)    void *X (UNU void *dummy)

// Failure modes

#define    WPI_FATAL    (1==1)
#define    WPI_ALMOST    (1==2)


// wiringPiNodeStruct:
//    This describes additional device nodes in the extended wiringPi
//    2.0 scheme of things.
//    It's a simple linked list for now, but will hopefully migrate to
//    a binary tree for efficiency reasons - but then again, the chances
//    of more than 1 or 2 devices being added are fairly slim, so who
//    knows....

struct wiringPiNodeStruct
{
  int     pinBase ;
  int     pinMax ;

  int          fd ;    // Node specific
  unsigned int data0 ;    //  ditto
  unsigned int data1 ;    //  ditto
  unsigned int data2 ;    //  ditto
  unsigned int data3 ;    //  ditto

          void   (*pinMode)          (struct wiringPiNodeStruct *node, int pin, int mode) ;
          void   (*pullUpDnControl)  (struct wiringPiNodeStruct *node, int pin, int mode) ;
          int    (*digitalRead)      (struct wiringPiNodeStruct *node, int pin) ;
//unsigned int    (*digitalRead8)     (struct wiringPiNodeStruct *node, int pin) ;
          void   (*digitalWrite)     (struct wiringPiNodeStruct *node, int pin, int value) ;
//         void   (*digitalWrite8)    (struct wiringPiNodeStruct *node, int pin, int value) ;
          void   (*pwmWrite)         (struct wiringPiNodeStruct *node, int pin, int value) ;
          int    (*analogRead)       (struct wiringPiNodeStruct *node, int pin) ;
          void   (*analogWrite)      (struct wiringPiNodeStruct *node, int pin, int value) ;

  struct wiringPiNodeStruct *next ;
} ;

extern struct wiringPiNodeStruct *wiringPiNodes ;


// Function prototypes
//    c++ wrappers thanks to a comment by Nick Lott
//    (and others on the Raspberry Pi forums)

#ifdef __cplusplus
extern "C" {
#endif

// Data

// Internal

extern int wiringPiFailure (int fatal, const char *message, ...) ;

// Core wiringPi functions

extern struct wiringPiNodeStruct *wiringPiFindNode (int pin) ;
extern struct wiringPiNodeStruct *wiringPiNewNode  (int pinBase, int numPins) ;

extern void wiringPiVersion    (int *major, int *minor) ;
extern int  wiringPiSetup       (void) ;
extern int  wiringPiSetupSys    (void) ;
extern int  wiringPiSetupGpio   (void) ;
extern int  wiringPiSetupPhys   (void) ;

extern          void pinModeAlt          (int pin, int mode) ;
extern          void pinMode             (int pin, int mode) ;
extern          void pullUpDnControl     (int pin, int pud) ;
extern          int  digitalRead         (int pin) ;
extern          void digitalWrite        (int pin, int value) ;
extern unsigned int  digitalRead8        (int pin) ;
extern          void digitalWrite8       (int pin, int value) ;
extern          void pwmWrite            (int pin, int value) ;
extern          int  analogRead          (int pin) ;
extern          void analogWrite         (int pin, int value) ;

// PiFace specifics
//    (Deprecated)

extern int  wiringPiSetupPiFace (void) ;
extern int  wiringPiSetupPiFaceForGpioProg (void) ;    // Don't use this - for gpio program only

// On-Board Raspberry Pi hardware specific stuff

extern          int  piGpioLayout        (void) ;
extern          int  piBoardRev          (void) ;    // Deprecated
extern          void piBoardId           (int *model, int *rev, int *mem, int *maker, int *overVolted) ;
extern          int  wpiPinToGpio        (int wpiPin) ;
extern          int  physPinToGpio       (int physPin) ;
extern          void setPadDrive         (int group, int value) ;
extern          int  getAlt              (int pin) ;
extern          void pwmToneWrite        (int pin, int freq) ;
extern          void pwmSetMode          (int mode) ;
extern          void pwmSetRange         (unsigned int range) ;
extern          void pwmSetClock         (int divisor) ;
extern          void gpioClockSet        (int pin, int freq) ;
extern unsigned int  digitalReadByte     (void) ;
extern unsigned int  digitalReadByte2    (void) ;
extern          void digitalWriteByte    (int value) ;
extern          void digitalWriteByte2   (int value) ;

// Interrupts
//    (Also Pi hardware specific)

extern int  waitForInterrupt    (int pin, int mS) ;
extern int  wiringPiISR         (int pin, int mode, void (*function)(void)) ;

// Threads

extern int  piThreadCreate      (void *(*fn)(void *)) ;
extern void piLock              (int key) ;
extern void piUnlock            (int key) ;

// Schedulling priority

extern int piHiPri (const int pri) ;

// Extras from arduino land

extern void         delay             (unsigned int howLong) ;
extern void         delayMicroseconds (unsigned int howLong) ;
extern unsigned int millis            (void) ;
extern unsigned int micros            (void) ;

#ifdef __cplusplus
}
#endif

#endif
```

Are there any Linuxisms in this? And if not where should I copy it to so that I can include it?


----------



## balanga (Feb 3, 2018)

aragats said:


> I believe, we already discussed similar things in another thread here.
> The problem is that _wiringPi_ library relies on the virtual filesystem /sys/class/gpio which is a part of Linux kernel and does not exist in FreeBSD.



I don't claim to understand, and am probably naive in asking if /sys/classgpi/o can be created in FreeBSD...


----------



## aragats (Feb 3, 2018)

This is just a header file. Look at the implementation e.g. in wiringPi.c:
	
	



```
1939 // Now pre-open the [b]/sys/class[/b] node - but it may already be open if
1940 //      we are in Sys mode...
1941
1942   if (sysFds [bcmGpioPin] == -1)
1943   {
1944     sprintf (fName, "[b]/sys/class/gpio/gpio%d/value[/b]", bcmGpioPin) ;
1945     if ((sysFds [bcmGpioPin] = open (fName, O_RDWR)) < 0)
1946       return wiringPiFailure (WPI_FATAL, "wiringPiISR: unable to open %s: %s\n", fName, strerror (errno)) ;
1947   }
```


----------



## aragats (Feb 3, 2018)

balanga said:


> if /sys/classgpi/o can be created in FreeBSD


It's a part of Linux kernel, you will have to implement such a driver for FreeBSD.


----------



## Phishfry (Feb 3, 2018)

There are at least 3 distinct facilities available for GPIO coding on FreeBSD.

Gonzo has a github:
https://github.com/gonzoua/freebsd-gpio

Emmanuael has a github:
https://github.com/evadot/fbsd_gpio_py

And then there is the library included with FreeBSD source.
/usr/src/lib/libgpio/libgpio.c

There is an example of libgpio usage in the manual:
https://www.freebsd.org/cgi/man.cgi?query=gpio&sektion=3

And a snippet of test code over here:
https://www.bidouilliste.com/blog/2016/04/22/FreeBSD-GPIO-Benchmark/


----------



## Phishfry (Feb 3, 2018)

This site has good examples:
http://www.claydowling.com/blog:programming_the_gpio_on_a_raspberry_pi

Here is a good example of blinking an LED with the libgpio library.
http://www.claydowling.com/blog:blinking_lights_with_gpio


----------



## aragats (Feb 3, 2018)

Does it support GPIO interrupts processing? I don't see anything interrupts related...


----------



## balanga (Feb 3, 2018)

Are there any Linuxisms here?


----------



## Phishfry (Feb 4, 2018)

No interrupt support in libgpio.

There is no mcp23s17 FreeBSD driver for your ADC device. Beyond that important detail I don't know about Linux'isms in the code.
It looks to me like it requires interrupts as well.
https://github.com/piface/pifacedigitalio/blob/master/pifacedigitalio/core.py


----------



## aragats (Feb 4, 2018)

Phishfry said:


> It looks to me like it requires interrupts as well


It does, and even worse, _interrupts_ module requires mcp23s17 and Linux's /sys/class/gpio, see interrupts.py:
	
	



```
....
import pifacecommon.mcp23s17
....
GPIO_INTERRUPT_DEVICE = "/sys/class/gpio/gpio%d" % GPIO_INTERRUPT_PIN 
....
```


----------



## aragats (Feb 4, 2018)

Phishfry said:


> No interrupt support in libgpio.


Does it mean I will need to write a kernel module to handle interrupts? I wouldn't like to do it from scratch though...
There was a discussion back in 2016 which refers another one from 2014.


----------



## Phishfry (Feb 4, 2018)

I wish I had the skills to add some PWM handles in there too...
It's better than nothing.


----------



## Phishfry (Feb 4, 2018)

I saw a post where phk has built a BCM PWM driver on the -current mailing list from December..
Not released yet.

I would like to use Pruss on the BBB and do the PWM on the PRU instead of depending on the CPU.
No instructions around on that dandy.


----------



## aragats (Feb 4, 2018)

Phishfry said:


> do the PWM on the PRU instead of depending on the CPU


I guess, PWM doesn't consume CPU resources at all. PRU is good for real time digital and analog IOs.
I'm working in a commercial project with BBB (unfortunately, with Linux), currently we decided to not use PRU since even with interrupts processing we are fine running web apps and a Qt application.


----------



## Phishfry (Feb 4, 2018)

I can't imagine a pulse generator not creating a cpu load. I guess I am going to have to do some testing. See how much load pwm creates.
I would think the higher frequencies would take a beating on the BBB. A 200mhz Aux CPU sounds perfect for the task.
https://github.com/omcaree/bbb-prupwm
Plus 24 channels instead of 4 GPIO pins that are paired (1a,1b,2a,2b)


----------



## aragats (Feb 4, 2018)

Phishfry said:


> I can't imagine a pulse generator not creating a cpu load.


In this PWM HW Overview there is a link to the Technical reference Manual, on the page 2330 you can find the corresponding description.
_«An effective PWM peripheral must be able to generate complex pulse width waveforms with minimal CPU overhead or intervention. It needs to be highly programmable and very flexible while being easy to understand and use. The ePWM unit described here addresses these requirements by allocating all needed timing and control resources on a per PWM channel basis.»_
The idea is to write values into the corresponding registers and start generation by a separate piece of hardware.


----------



## balanga (Feb 4, 2018)

Is there any chance of being able to use one of these with FreeBSD? I just want to be able to switch lights on and off, at least to start with, and there seem to be so many barriers. I appreciate I can't use sample Linux code, but are there alternative FreeBSD modules, libraries which can be used?


----------



## Phishfry (Feb 4, 2018)

I dunno about that piface_digital.
Maybe some of it will work. Leds and switches should work.


----------



## aragats (Feb 4, 2018)

balanga said:


> I just want to be able to switch lights on and off


I have one of such relay boards, perfectly works with RPis and costs significantly less.


----------



## balanga (Feb 4, 2018)

Phishfry said:


> I dunno about that piface_digital.
> Maybe some of it will work. Leds and switches should work.



Do you know of an samples equivalent to this short Python program which makes one of the LEDs blink


```
from time import sleep
import pifacedigitalio

DELAY = 1.0  # seconds

if __name__ == "__main__":
    pifacedigital = pifacedigitalio.PiFaceDigital()
    while True:
        pifacedigital.leds[7].toggle()
        sleep(DELAY)
```


----------



## aragats (Feb 4, 2018)

Isn't it already in the demo Phishfry pointed above?
https://github.com/gonzoua/freebsd-gpio/blob/master/python/rpi-gpio-demo.py


----------



## balanga (Feb 4, 2018)

aragats said:


> Isn't it already in the demo Phishfry pointed above?
> https://github.com/gonzoua/freebsd-gpio/blob/master/python/rpi-gpio-demo.py



I don't really know python but I just installed python36 and got syntax errors when trying to run it. I ran it as python3.6....


```
root@rpi-b:~/projects/rpi # python3.6 freebsd-test.py
  File "freebsd-test.py", line 35
    print "Max pin #: %d" % max_pin
                        ^
SyntaxError: Missing parentheses in call to 'print'. Did you mean print("Max pin #: %d" % max_pin)?
```

After changing the above I get 

```
File "freebsd-test.py", line 51
    print "#%3d: %s, value=%d, config=<%s>, caps=<%s>" % (p, name, value, config, caps)
                                                     ^
SyntaxError: invalid syntax
```

After correcting that I get 
	
	



```
No module named 'gpio'
```

Not sure what to do now...


----------



## aragats (Feb 4, 2018)

balanga said:


> SyntaxError: Missing parentheses in call to 'print'


That's an evidence that you need _python2_ instead of _python3_.



balanga said:


> No module named 'gpio'


It's in the same directory, see https://github.com/gonzoua/freebsd-gpio/tree/master/python.
There is also setup.py, which, I assume, you should run at the very beginning.

(I'm not a python expert by the way...)


----------



## aragats (Feb 6, 2018)

balanga , here is an article about (in particular) using that (mentioned above) Python module:
https://vzaigrin.wordpress.com/2015/02/02/web-control-of-raspberry-pi-gpio-in-freebsd/


----------



## balanga (Feb 6, 2018)

Thanks, I'll take a look, although it looks as though I'll have to give up on the idea of using FreeBSD on my RPi-B with its Piface Digital interface because there are too many obstacles to getting it working.

I'll probably try out a few of the examples on my RPi2.


----------



## Phishfry (Feb 6, 2018)

I think the 7 dollar relay card aragats recommended is spot on. it has relays and LEDs. Really simple to show on off.

With specialty Hats or Capes you really need to check to see if base chip driver is present on FreeBSD.
Then you got to deal with making a custom DTB/DTS or modding the Linux one, if it exists, for the hardware to work.


----------



## munocat (May 20, 2021)

just found this thread. Has GPIO for the raspberry pi been added? meaning can I write programs like I would on a Raspberry Pi OS. I am wanting to use C and Python


----------



## Phishfry (May 20, 2021)

See the manual for gpio(3) library functions.
Pi2 and Pi3 defiantly have GPIO support. Pi4 is a WIP.
OneWire drivers, I2C and SPI too. You can use some Linux overlays with work.


----------



## aragats (May 21, 2021)

munocat said:


> Has GPIO for the raspberry pi been added?


The GPIOs always worked, the GPIO interrupts didn't. I'm not sure whether the GPIO interrupts handling is added now.


----------



## obsigna (May 21, 2021)

See a respective thread on the ARM mailing list:


			Porting FreeBSD to ARM processors: User Space GPIO Interrupt programming - GSoC-2018
		


This resulted into the implementation of "userland gpio interrupts“ in December 2020.





						rS368585
					






					reviews.freebsd.org
				




This is working perfectly with FreeBSD 13.0-RELEASE on a BeagleBone Black. I cannot tell anything about the various Raspberry Pis, though.


----------

