1
0
mirror of https://github.com/aolofsson/oh.git synced 2025-01-30 02:32:53 +08:00

Merge pull request #61 from olajep/gpio-driver

GPIO driver
This commit is contained in:
Andreas Olofsson 2016-04-13 09:56:37 -04:00
commit 3ccd72016e
8 changed files with 441 additions and 76 deletions

View File

@ -1,4 +1,102 @@
Driver layer for GPIO
# Driver layer for GPIO
* Don't hard code, initialize correctly
* uctions?
* uctions?
## User API
```c
/*** API */
#define GPIO_DIR_IN (0 << 0)
#define GPIO_DIR_OUT (1 << 0)
#define GPIO_LOW 0
#define GPIO_HIGH 1
/**
* gpio_init - GPIO init
*
* @param dev uninitialized device structure
* @param arg target argument (depends on target)
*
* @return 0 on success. Negative on error
*/
int gpio_init(gpio_dev_t *dev, void *arg);
/**
* gpio_set_direction - Set pin direction
*
* @param dev device structure
* @param gpio gpio pin identifier
* @param direction GPIO_DIR_OUT or GPIO_DIR_IN
*
* @return 0 on success. Negative on error
*/
int gpio_set_direction(gpio_dev_t *dev, unsigned gpio, unsigned direction);
/**
* gpio_read - Read pin value
*
* @param dev device structure
* @param gpio gpio pin identifier
*
* @return 0 on low. 1 on high, negative on error.
*/
int gpio_read(gpio_dev_t *dev, unsigned gpio);
/**
* gpio_write - Set pin value
*
* @param dev device structure
* @param gpio gpio pin identifier
* @param value 0 on low, 1 on high
*
* @return 0 on success, negative on error.
*/
int gpio_write(gpio_dev_t *dev, unsigned gpio, int value);
/**
* gpio_toggle - Toggle pin value
*
* @param dev device structure
* @param gpio gpio pin identifier
*
* @return 0 on success, negative on error.
*/
int gpio_toggle(gpio_dev_t *dev, unsigned gpio);
/*** Raw register access API */
#define GPIO_REG_DIR (0x0 << 3)
#define GPIO_REG_IN (0x1 << 3)
#define GPIO_REG_OUT (0x2 << 3)
#define GPIO_REG_OUTCLR (0x3 << 3)
#define GPIO_REG_OUTSET (0x4 << 3)
#define GPIO_REG_OUTXORA (0x5 << 3)
#define GPIO_REG_IMASK (0x6 << 3)
#define GPIO_REG_ITYPE (0x7 << 3)
#define GPIO_REG_IPOL (0x8 << 3)
#define GPIO_REG_ILAT (0x9 << 3)
#define GPIO_REG_ILATCLR (0xA << 3)
/**
* gpio_reg_read - Read a GPIO register
*
* @param dev device structure
* @param reg gpio register
*
* @return Register value, no error checking.
*/
//uint64_t gpio_reg_read(gpio_dev_t *dev, unsigned reg);
/**
* gpio_reg_write - write to a GPIO register
*
* @param dev device structure
* @param reg gpio register
*
*/
//void gpio_reg_write(gpio_dev_t *dev, unsigned reg, uint64_t value);
```

View File

@ -0,0 +1,8 @@
#pragma once
#ifndef _GPIO_INTERNAL
# error "Don't include this file directly"
#endif
#include "gpio-generic.h"
#error "Epiphany target not implemented"

View File

@ -0,0 +1,81 @@
#pragma once
#ifndef _GPIO_INTERNAL
# error "Don't include this file directly"
#endif
struct gpio_generic_dev {
volatile struct gpio_registers *regs;
uint64_t dircache;
};
__unused
static int _gpio_set_direction(struct gpio_generic_dev *dev, unsigned gpio,
unsigned direction)
{
if (63 < gpio)
return -EINVAL;
if (direction == GPIO_DIR_OUT)
dev->dircache |= (1ULL << gpio);
else if (direction == GPIO_DIR_IN)
dev->dircache &= ~(1ULL << gpio);
else
return -EINVAL;
dev->regs->dir = dev->dircache;
return 0;
}
__unused
static int _gpio_read(struct gpio_generic_dev *dev, unsigned gpio)
{
if (63 < gpio)
return -EINVAL;
return (dev->regs->in >> gpio) & 1;
}
__unused
static int _gpio_write(struct gpio_generic_dev *dev, unsigned gpio,
int value)
{
if (63 < gpio)
return -EINVAL;
if (value < 0)
return -EINVAL;
if (value)
dev->regs->outset = (1ULL << gpio);
else
dev->regs->outclr = (1ULL << gpio);
return 0;
}
__unused
static int _gpio_toggle(struct gpio_generic_dev *dev, unsigned gpio)
{
if (63 < gpio)
return -EINVAL;
dev->regs->outxor = (1ULL << gpio);
return 0;
}
__unused
static uint64_t _gpio_reg_read(struct gpio_generic_dev *dev, unsigned reg)
{
uint64_t *regs = (uint64_t *) dev->regs;
return regs[reg];
}
__unused
static void _gpio_reg_write(struct gpio_generic_dev *dev, unsigned reg,
uint64_t value)
{
uint64_t *regs = (uint64_t *) dev->regs;
regs[reg] = value;
}

View File

@ -0,0 +1,31 @@
#pragma once
#ifndef _GPIO_INTERNAL
# error "Don't include this file directly"
#endif
#include "gpio-generic.h"
typedef struct gpio_generic_dev gpio_dev_t;
__unused
static int gpio_init(gpio_dev_t *dev, void *arg)
{
if (!arg)
#ifdef GPIO_SIMPLE_DEFAULT_ADDR
arg = (void *) GPIO_SIMPLE_DEFAULT_ADDR;
#else
return -EINVAL;
#endif
dev->regs = (struct gpio_registers *) arg;
dev->dircache = 0;
return 0;
}
#define gpio_set_direction _gpio_set_direction
#define gpio_read _gpio_read
#define gpio_write _gpio_write
#define gpio_toggle _gpio_toggle
#define gpio_reg_read _gpio_reg_read
#define gpio_reg_write _gpio_reg_write

View File

@ -1,24 +0,0 @@
#include "gpio.h"
#include <stdio.h>
void gpio_init(gpio_t *dev){
printf("GPIO INIT\n");
}
void gpio_dir(gpio_t *dev, int pin, int val){
if(val){
printf("PIN %d set to OUTPUT\n", pin);
}
else{
printf("PIN %d set to INPUT\n", pin);
}
}
void gpio_write(gpio_t *dev, int pin, int val){
printf("PIN %d set to %d\n", pin, val);
}
int gpio_read(gpio_t *dev, int pin){
printf("PIN %d input is %d\n", pin, 0);
}

View File

@ -1,42 +1,160 @@
//Register number addr[6:3]
#define GPIO_DIR 0
#define GPIO_IN 1
#define GPIO_OUT 2
#define GPIO_OUTCLR 3
#define GPIO_OUTSET 4
#define GPIO_OUTXOR 5
#define GPIO_IMASK 6
#define GPIO_ITYPE 7
#define GPIO_IPOL 8
#define GPIO_ILAT 9
#define GPIO_ILATCLR 10
#pragma once
#include <stdint.h>
#include <errno.h>
#include <stddef.h>
#define GPIO_TX 1
#define GPIO_RX 0
/*** API */
// define global struct...
//parameters per struct
//An oderered list of SPI interfaces
//-each interface has: N pins, a global offset
typedef struct {
} gpio_t;
#define GPIO_DIR_IN (0 << 0)
#define GPIO_DIR_OUT (1 << 0)
// Provide pointer to GPIO module
void gpio_init(gpio_t *dev);
#define GPIO_LOW 0
#define GPIO_HIGH 1
// Set pin mode
void gpio_dir(gpio_t *dev, int pin, int dir);
/**
* gpio_init - GPIO init
*
* @param dev uninitialized device structure
* @param arg target argument (depends on target)
*
* @return 0 on success. Negative on error
*/
//int gpio_init(gpio_dev_t *dev, void *arg);
// Write to a pin
void gpio_write(gpio_t *dev, int pin, int val);
/**
* gpio_set_direction - Set pin direction
*
* @param dev device structure
* @param gpio gpio pin identifier
* @param direction GPIO_DIR_OUT or GPIO_DIR_IN
*
* @return 0 on success. Negative on error
*/
//int gpio_set_direction(gpio_dev_t *dev, unsigned gpio, unsigned direction);
// Toggle a pin
void gpio_toggle(gpio_t *dev, int pin);
/**
* gpio_read - Read pin value
*
* @param dev device structure
* @param gpio gpio pin identifier
*
* @return 0 on low. 1 on high, negative on error.
*/
//int gpio_read(gpio_dev_t *dev, unsigned gpio);
// Read from a pin
int gpio_read(gpio_t *dev, int pin);
/**
* gpio_write - Set pin value
*
* @param dev device structure
* @param gpio gpio pin identifier
* @param value 0 on low, 1 on high
*
* @return 0 on success, negative on error.
*/
//int gpio_write(gpio_dev_t *dev, unsigned gpio, int value);
/**
* gpio_toggle - Toggle pin value
*
* @param dev device structure
* @param gpio gpio pin identifier
*
* @return 0 on success, negative on error.
*/
//int gpio_toggle(gpio_dev_t *dev, unsigned gpio);
/*** Raw register access API */
#define GPIO_REG_DIR (0x0 << 3)
#define GPIO_REG_IN (0x1 << 3)
#define GPIO_REG_OUT (0x2 << 3)
#define GPIO_REG_OUTCLR (0x3 << 3)
#define GPIO_REG_OUTSET (0x4 << 3)
#define GPIO_REG_OUTXORA (0x5 << 3)
#define GPIO_REG_IMASK (0x6 << 3)
#define GPIO_REG_ITYPE (0x7 << 3)
#define GPIO_REG_IPOL (0x8 << 3)
#define GPIO_REG_ILAT (0x9 << 3)
#define GPIO_REG_ILATCLR (0xA << 3)
/**
* gpio_reg_read - Read a GPIO register
*
* @param dev device structure
* @param reg gpio register
*
* @return Register value, no error checking.
*/
//uint64_t gpio_reg_read(gpio_dev_t *dev, unsigned reg);
/**
* gpio_reg_write - write to a GPIO register
*
* @param dev device structure
* @param reg gpio register
*
*/
//void gpio_reg_write(gpio_dev_t *dev, unsigned reg, uint64_t value);
#ifndef __unused
# if defined(__GNUC__) || defined(__clang__)
# define __unused __attribute__((unused))
# else
# define __unused
# endif
#endif
#ifndef __packed
# if defined(__GNUC__) || defined(__clang__)
# define __packed __attribute__((packed))
# else
# define __packed
# endif
#endif
#ifndef __aligned
# if defined(__GNUC__) || defined(__clang__)
# define __aligned(X) __attribute__((aligned(X)))
# else
# define __aligned(X)
# endif
#endif
struct gpio_registers {
uint64_t dir;
uint64_t in;
uint64_t out;
uint64_t outclr;
uint64_t outset;
uint64_t outxor;
uint64_t imask;
uint64_t itype;
uint64_t ipol;
uint64_t ilat;
uint64_t ilatclr;
} __packed __aligned(8);
#define GPIO_TARGET_SIMPLE 0
#define GPIO_TARGET_EPIPHANY 1
/* Autodetect target */
#ifndef GPIO_TARGET
# ifdef __epiphany__
# define GPIO_TARGET GPIO_TARGET_EPIPHANY
# else
# define GPIO_TARGET GPIO_TARGET_SIMPLE
# endif
#endif
#define _GPIO_INTERNAL
#if GPIO_TARGET == GPIO_TARGET_SIMPLE
# include "gpio-simple.h"
#elif GPIO_TARGET == GPIO_TARGET_EPIPHANY
# include "gpio-epiphany.h"
#else
# error "Invalid GPIO_TARGET"
#endif
#undef _GPIO_INTERNAL

View File

@ -1,24 +1,50 @@
#define GPIO_TARGET GPIO_TARGET_SIMPLE
#define MY_GPIO_ADDR 0x810f0c00
#include <stdlib.h>
#include <unistd.h>
#include "gpio.h"
void main(){
int main()
{
gpio_dev_t dev;
// set up the pin numbers
int west = 8;
int N = 8;
int led = N*west;
// init gpio
gpio_t gdev, *pdev;
pdev = &gdev;
gpio_init(pdev);
// set up the pin numbers
const unsigned west = 4;
const unsigned N = 4;
const unsigned led = N * west + 0;
const unsigned button = N * west + 1;
const unsigned clk = N * west + 2;
// set pin as output
gpio_dir(pdev,led,GPIO_TX);
// create a clock pattern
while(1){
gpio_write(pdev,led,1);
usleep(1e6);
gpio_write(pdev,led,0);
usleep(1e6);
}
// init gpio (argument to SIMPLE is pointer to regs)
if (gpio_init(&dev, (void *) MY_GPIO_ADDR))
exit(EXIT_FAILURE);
// set pin as output
gpio_set_direction(&dev, led, GPIO_DIR_OUT);
// set pin as output
gpio_set_direction(&dev, clk, GPIO_DIR_OUT);
// set pin as input
gpio_set_direction(&dev, button, GPIO_DIR_IN);
// init outputs
gpio_write(&dev, clk, 0);
gpio_write(&dev, led, 0);
while (1) {
usleep(1e6);
// create clock pattern
gpio_toggle(&dev, clk);
// set led to button value
if (gpio_read(&dev, button))
gpio_write(&dev, led, 1);
else
gpio_write(&dev, led, 0);
}
return 0;
}

27
src/gpio/driver/test.c Normal file
View File

@ -0,0 +1,27 @@
#define GPIO_TARGET GPIO_TARGET_SIMPLE
#define GPIO_SIMPLE_DEFAULT_ADDR 0xdeadbee0
#include <stdlib.h>
#include "gpio.h"
int main()
{
int val;
gpio_dev_t dev;
if (gpio_init(&dev, NULL))
exit(EXIT_FAILURE);
gpio_set_direction(&dev, 63, GPIO_DIR_IN);
gpio_set_direction(&dev, 0, GPIO_DIR_OUT);
val = 1;
gpio_write(&dev, 0, val);
val = gpio_read(&dev, 63);
gpio_write(&dev, 0, ~val & 1);
val = gpio_read(&dev, 63);
gpio_toggle(&dev, 0);
val = gpio_read(&dev, 63);
return val;
}