mirror of
https://github.com/aolofsson/oh.git
synced 2025-01-30 02:32:53 +08:00
commit
3ccd72016e
@ -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);
|
||||
```
|
||||
|
8
src/gpio/driver/gpio-epiphany.h
Normal file
8
src/gpio/driver/gpio-epiphany.h
Normal 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"
|
81
src/gpio/driver/gpio-generic.h
Normal file
81
src/gpio/driver/gpio-generic.h
Normal 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;
|
||||
}
|
31
src/gpio/driver/gpio-simple.h
Normal file
31
src/gpio/driver/gpio-simple.h
Normal 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
|
@ -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);
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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
27
src/gpio/driver/test.c
Normal 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;
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user