• This site uses cookies. By continuing to use this site, you are agreeing to our use of cookies. Learn more.

GPIO programming on RPi

balanga

Daemon

Thanks: 59
Messages: 1,961

#1
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?

Code:
#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

Aspiring Daemon

Thanks: 339
Messages: 854

#2
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

Daemon

Thanks: 59
Messages: 1,961

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

I managed to find it here

Code:
/*
 * 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

Daemon

Thanks: 59
Messages: 1,961

#4
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

Aspiring Daemon

Thanks: 339
Messages: 854

#5
This is just a header file. Look at the implementation e.g. in wiringPi.c:
Code:
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   }
 

Phishfry

Daemon

Thanks: 761
Best answers: 1
Messages: 2,352

#7
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/
 

aragats

Aspiring Daemon

Thanks: 339
Messages: 854

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

Phishfry

Daemon

Thanks: 761
Best answers: 1
Messages: 2,352

#15
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

Aspiring Daemon

Thanks: 339
Messages: 854

#16
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

Daemon

Thanks: 761
Best answers: 1
Messages: 2,352

#17
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

Aspiring Daemon

Thanks: 339
Messages: 854

#18
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

Daemon

Thanks: 59
Messages: 1,961

#19
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?
 

balanga

Daemon

Thanks: 59
Messages: 1,961

#22
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

Code:
from time import sleep
import pifacedigitalio

DELAY = 1.0  # seconds

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

balanga

Daemon

Thanks: 59
Messages: 1,961

#24
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....

Code:
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
Code:
  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
Code:
 No module named 'gpio'
Not sure what to do now...
 
Top