gpio driver Add gpio driver interface.
Signed-off-by: Jan Willeke <willeke@smartmote.de>
This commit is contained in:
parent
9497265e72
commit
1be4ed0679
1
Makefile
1
Makefile
|
@ -145,6 +145,7 @@ OBJ=\
|
|||
drivers/devicelist.o \
|
||||
drivers/fet_olimex_db.o \
|
||||
drivers/jtdev.o \
|
||||
drivers/jtdev_gpio.o \
|
||||
drivers/jtaglib.o \
|
||||
drivers/pif.o \
|
||||
drivers/loadbsl.o \
|
||||
|
|
|
@ -64,5 +64,6 @@ struct jtdev_func{
|
|||
};
|
||||
|
||||
extern const struct jtdev_func jtdev_func_pif;
|
||||
extern const struct jtdev_func jtdev_func_gpio;
|
||||
|
||||
#endif
|
||||
|
|
|
@ -0,0 +1,263 @@
|
|||
/* MSPDebug - gpio device interface
|
||||
* Copyright (C) 2014 TTI GmbH - TGU Smartmote
|
||||
* Author(s): Jan Willeke (willeke@smartmote.de)
|
||||
*
|
||||
* Linux /sys/class/gpio interface to msp430 jtag
|
||||
* inspired by urjtag and jtdev.c
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program 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 General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
#include "jtdev.h"
|
||||
#include "output.h"
|
||||
|
||||
#if defined(__linux__) || \
|
||||
( defined(__FreeBSD__) || defined(__DragonFly__) )
|
||||
/*===== includes =============================================================*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
#include <stdio.h>
|
||||
#include "gpio.h"
|
||||
|
||||
/* pin mapping */
|
||||
enum {
|
||||
GPIO_TDI = 0,
|
||||
GPIO_TCK,
|
||||
GPIO_TMS,
|
||||
GPIO_TDO,
|
||||
GPIO_REQUIRED
|
||||
};
|
||||
|
||||
unsigned int jtag_gpios[4];
|
||||
int fd_gpios[4];
|
||||
|
||||
static int
|
||||
gpio_open ()
|
||||
{
|
||||
int i, ret;
|
||||
|
||||
/* Export all gpios */
|
||||
for (i = 0; i < GPIO_REQUIRED; i++)
|
||||
{
|
||||
unsigned int gpio = jtag_gpios[i];
|
||||
|
||||
ret = gpio_export (gpio);
|
||||
if (ret)
|
||||
{
|
||||
printf("gpio[%d] %u cannot be exported\n", i, gpio);
|
||||
return -1;
|
||||
}
|
||||
gpio_set_dir (gpio, (i == GPIO_TDO) ? 0 : 1);
|
||||
|
||||
fd_gpios[i] = gpio_open_fd(gpio);
|
||||
if (fd_gpios[i] < 0)
|
||||
{
|
||||
printf("gpio: cannot open gpio[%d] %u\n", i, gpio);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
gpio_parse_config (const char *params)
|
||||
{
|
||||
struct option{
|
||||
char* name;
|
||||
int num;
|
||||
};
|
||||
static const struct option ops[] = {
|
||||
{"tms=",GPIO_TMS},
|
||||
{"tdi=",GPIO_TDI},
|
||||
{"tdo=",GPIO_TDO},
|
||||
{"tck=",GPIO_TCK}
|
||||
};
|
||||
int i;
|
||||
|
||||
for( i = 0;i < 4; i++) {
|
||||
char* help;
|
||||
help = strstr(params,ops[i].name);
|
||||
if (help)
|
||||
jtag_gpios[ops[i].num] = atoi(help+4);
|
||||
else
|
||||
return -1;
|
||||
printf("gpio %s %d\n", ops[i].name,jtag_gpios[ops[i].num]);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int jtgpio_open(struct jtdev *p, const char *device)
|
||||
{
|
||||
if (gpio_parse_config(device)){
|
||||
printf("gpio: failed parsing parameters\n");
|
||||
return -1;
|
||||
}
|
||||
return gpio_open();
|
||||
}
|
||||
|
||||
static void jtgpio_close(struct jtdev *p)
|
||||
{
|
||||
int i;
|
||||
printf("JTAG_CLOSE\n");
|
||||
|
||||
for (i = 0; i < GPIO_REQUIRED; i++)
|
||||
{
|
||||
if (fd_gpios[i])
|
||||
close (fd_gpios[i]);
|
||||
gpio_unexport (jtag_gpios[i]);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static void jtgpio_power_on(struct jtdev *p)
|
||||
{
|
||||
printf("JTAG_power on\n");
|
||||
}
|
||||
|
||||
static void jtgpio_power_off(struct jtdev *p)
|
||||
{
|
||||
printf("JTAG_power off\n");
|
||||
}
|
||||
|
||||
static void jtgpio_connect(struct jtdev *p)
|
||||
{
|
||||
printf("JTAG_connct \n");
|
||||
}
|
||||
|
||||
static void jtgpio_release(struct jtdev *p)
|
||||
{
|
||||
printf("JTAG_release\n");
|
||||
}
|
||||
|
||||
static void jtgpio_tck(struct jtdev *p, int out)
|
||||
{
|
||||
gpio_set_value_fd (fd_gpios[GPIO_TCK], out);
|
||||
}
|
||||
|
||||
static void jtgpio_tms(struct jtdev *p, int out)
|
||||
{
|
||||
gpio_set_value_fd (fd_gpios[GPIO_TMS], out);
|
||||
}
|
||||
|
||||
static void jtgpio_tdi(struct jtdev *p, int out)
|
||||
{
|
||||
gpio_set_value_fd (fd_gpios[GPIO_TDI], out);
|
||||
}
|
||||
|
||||
static void jtgpio_rst(struct jtdev *p, int out)
|
||||
{
|
||||
printf("jtag_reset\n");
|
||||
}
|
||||
|
||||
static void jtgpio_tst(struct jtdev *p, int out)
|
||||
{
|
||||
printf("jtag_test\n");
|
||||
}
|
||||
|
||||
static int jtgpio_tdo_get(struct jtdev *p)
|
||||
{
|
||||
return gpio_get_value_fd (fd_gpios[GPIO_TDO],
|
||||
jtag_gpios[GPIO_TDO]);
|
||||
}
|
||||
|
||||
static void jtgpio_tclk(struct jtdev *p, int out)
|
||||
{
|
||||
gpio_set_value_fd (fd_gpios[GPIO_TDI], out);
|
||||
}
|
||||
|
||||
static int jtgpio_tclk_get(struct jtdev *p)
|
||||
{
|
||||
return gpio_get_value_fd (fd_gpios[GPIO_TDI],
|
||||
jtag_gpios[GPIO_TDI]);
|
||||
}
|
||||
|
||||
static void jtgpio_tclk_strobe(struct jtdev *p, unsigned int count)
|
||||
{
|
||||
int i;
|
||||
for (i=0;i<count;i++){
|
||||
gpio_set_value_fd (fd_gpios[GPIO_TDI], 1);
|
||||
gpio_set_value_fd (fd_gpios[GPIO_TDI], 0);
|
||||
}
|
||||
}
|
||||
|
||||
static void jtgpio_led_green(struct jtdev *p, int out)
|
||||
{
|
||||
printf("led green\n");
|
||||
}
|
||||
|
||||
static void jtgpio_led_red(struct jtdev *p, int out)
|
||||
{
|
||||
printf("led red\n");
|
||||
}
|
||||
|
||||
|
||||
#else /* __linux__ */
|
||||
|
||||
|
||||
static int jtgpio_open(struct jtdev *p, const char *device)
|
||||
{
|
||||
printc_err("jtdev: driver is not supported on this platform\n");
|
||||
p->failed = 1;
|
||||
return -1;
|
||||
}
|
||||
|
||||
static void jtgpio_close(struct jtdev *p) { }
|
||||
|
||||
static void jtgpio_power_on(struct jtdev *p) { }
|
||||
static void jtgpio_power_off(struct jtdev *p) { }
|
||||
static void jtgpio_connect(struct jtdev *p) { }
|
||||
static void jtgpio_release(struct jtdev *p) { }
|
||||
|
||||
static void jtgpio_tck(struct jtdev *p, int out) { }
|
||||
static void jtgpio_tms(struct jtdev *p, int out) { }
|
||||
static void jtgpio_tdi(struct jtdev *p, int out) { }
|
||||
static void jtgpio_rst(struct jtdev *p, int out) { }
|
||||
static void jtgpio_tst(struct jtdev *p, int out) { }
|
||||
static int jtgpio_tdo_get(struct jtdev *p) { return 0; }
|
||||
|
||||
static void jtgpio_tclk(struct jtdev *p, int out) { }
|
||||
static int jtgpio_tclk_get(struct jtdev *p) { return 0; }
|
||||
static void jtgpio_tclk_strobe(struct jtdev *p, unsigned int count) { }
|
||||
|
||||
static void jtgpio_led_green(struct jtdev *p, int out) { }
|
||||
static void jtgpio_led_red(struct jtdev *p, int out) { }
|
||||
#endif
|
||||
|
||||
|
||||
const struct jtdev_func jtdev_func_gpio = {
|
||||
.jtdev_open = jtgpio_open,
|
||||
.jtdev_close = jtgpio_close,
|
||||
.jtdev_power_on = jtgpio_power_on,
|
||||
.jtdev_power_off = jtgpio_power_off,
|
||||
.jtdev_connect = jtgpio_connect,
|
||||
.jtdev_release = jtgpio_release,
|
||||
.jtdev_tck = jtgpio_tck,
|
||||
.jtdev_tms = jtgpio_tms,
|
||||
.jtdev_tdi = jtgpio_tdi,
|
||||
.jtdev_rst = jtgpio_rst,
|
||||
.jtdev_tst = jtgpio_tst,
|
||||
.jtdev_tdo_get = jtgpio_tdo_get,
|
||||
.jtdev_tclk = jtgpio_tclk,
|
||||
.jtdev_tclk_get = jtgpio_tclk_get,
|
||||
.jtdev_tclk_strobe = jtgpio_tclk_strobe,
|
||||
.jtdev_led_green = jtgpio_led_green,
|
||||
.jtdev_led_red = jtgpio_led_red
|
||||
};
|
|
@ -330,6 +330,8 @@ static int pif_erase( device_t dev_base,
|
|||
}
|
||||
|
||||
/*----------------------------------------------------------------------------*/
|
||||
|
||||
|
||||
static device_t pif_open(const struct device_args *args)
|
||||
{
|
||||
struct pif_device *dev;
|
||||
|
@ -370,6 +372,49 @@ static device_t pif_open(const struct device_args *args)
|
|||
return &dev->base;
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------------*/
|
||||
|
||||
|
||||
static device_t gpio_open(const struct device_args *args)
|
||||
{
|
||||
struct pif_device *dev;
|
||||
|
||||
if (!(args->flags & DEVICE_FLAG_TTY)) {
|
||||
printc_err("gpio: this driver does not support raw USB access\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (!(args->flags & DEVICE_FLAG_JTAG)) {
|
||||
printc_err("gpio: this driver does not support Spy-Bi-Wire\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
dev = malloc(sizeof(*dev));
|
||||
if (!dev) {
|
||||
printc_err("gpio: malloc: %s\n", last_error());
|
||||
return NULL;
|
||||
}
|
||||
|
||||
memset(dev, 0, sizeof(*dev));
|
||||
dev->base.type = &device_pif;
|
||||
dev->base.max_breakpoints = 0;
|
||||
(&dev->jtag)->f = &jtdev_func_gpio;
|
||||
|
||||
if ((&dev->jtag)->f->jtdev_open(&dev->jtag, args->path) < 0) {
|
||||
printc_err("gpio: can't open port\n");
|
||||
free(dev);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (init_device(&dev->jtag) < 0) {
|
||||
printc_err("gpio: initialization failed\n");
|
||||
free(dev);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return &dev->base;
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------------*/
|
||||
static void pif_destroy(device_t dev_base)
|
||||
{
|
||||
|
@ -396,3 +441,17 @@ const struct device_class device_pif = {
|
|||
.poll = pif_poll,
|
||||
.erase = pif_erase
|
||||
};
|
||||
|
||||
const struct device_class device_gpio = {
|
||||
.name = "gpio",
|
||||
.help = "/sys/class/gpio direct connect",
|
||||
.open = gpio_open,
|
||||
.destroy = pif_destroy,
|
||||
.readmem = pif_readmem,
|
||||
.writemem = pif_writemem,
|
||||
.getregs = pif_getregs,
|
||||
.setregs = pif_setregs,
|
||||
.ctl = pif_ctl,
|
||||
.poll = pif_poll,
|
||||
.erase = pif_erase
|
||||
};
|
||||
|
|
|
@ -32,5 +32,7 @@
|
|||
|
||||
/* pif implementation */
|
||||
extern const struct device_class device_pif;
|
||||
/* share wiht gpio implementation */
|
||||
extern const struct device_class device_gpio;
|
||||
|
||||
#endif
|
||||
|
|
|
@ -199,6 +199,13 @@ only tty access is supported. Currently, this driver is only supported
|
|||
on Linux, FreeBSD and DragonFly BSD. A parallel port device (ppdev on
|
||||
Linux, ppi on FreeBSD and DragonFly BSD) must be specified via the
|
||||
\fB-d\fR option.
|
||||
.IP "\fBgpio\fR"
|
||||
Connect to system gpios. JTAG mode must be used, and
|
||||
only tty access is supported. Currently, this driver is only supported
|
||||
on Linux, FreeBSD and DragonFly BSD. The gpios to used must defined using
|
||||
a string like "tdi=7 tdo=8 tms=9 tck=4" via the
|
||||
\fB-d\fR option. (dont forget the quotes)
|
||||
|
||||
.IP "\fBload-bsl\fR"
|
||||
Connect to a USB bootloader. The stub bootloader will be used to load a
|
||||
fuller-featured bootloader into RAM for execution.
|
||||
|
|
|
@ -87,6 +87,7 @@ static const struct device_class *const driver_table[] = {
|
|||
&device_tilib,
|
||||
&device_goodfet,
|
||||
&device_pif,
|
||||
&device_gpio,
|
||||
&device_loadbsl,
|
||||
&device_ezfet,
|
||||
&device_rom_bsl
|
||||
|
|
63
util/gpio.c
63
util/gpio.c
|
@ -158,4 +158,67 @@ int gpio_get_value ( unsigned int gpio )
|
|||
|
||||
return ( ch != '0' );
|
||||
}
|
||||
/**
|
||||
* Opens GPIO (input/output) pin file descriptor
|
||||
* @param gpio GPIO number
|
||||
* @return file descriptor, -1 if fails
|
||||
*/
|
||||
|
||||
int gpio_open_fd ( unsigned int gpio ) {
|
||||
int fd;
|
||||
char buf[MAX_BUF];
|
||||
|
||||
snprintf ( buf, MAX_BUF, SYSFS_GPIO_DIR "/gpio%d/value", gpio );
|
||||
|
||||
fd = open ( buf, O_RDWR );
|
||||
if ( fd < 0 )
|
||||
{
|
||||
perror ( "gpio/get-value" );
|
||||
return -1;
|
||||
}
|
||||
return fd;
|
||||
}
|
||||
/**
|
||||
* Sets GPIO (output) value with given file descriptor
|
||||
* @param file descriptor
|
||||
* @param gpio GPIO number
|
||||
* @return 0 if OK, -1 if fails
|
||||
*/
|
||||
|
||||
int gpio_set_value_fd (int fd, int value)
|
||||
{
|
||||
ssize_t ret;
|
||||
char gpio_value = value + '0';
|
||||
|
||||
ret = write (fd, &gpio_value, 1);
|
||||
if (ret != 1)
|
||||
{
|
||||
printf("Error setting value gpio\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
/**
|
||||
* Read state of GPIO (input) pin, with file descriptor
|
||||
* @param file descriptor
|
||||
* @param gpio GPIO number
|
||||
* @return 0 if LO, 1 if HI, -1 if fails
|
||||
*/
|
||||
|
||||
int gpio_get_value_fd (int fd, unsigned int gpio)
|
||||
{
|
||||
ssize_t ret;
|
||||
char value;
|
||||
|
||||
ret = pread (fd, &value, 1, 0);
|
||||
|
||||
if (ret != 1)
|
||||
{
|
||||
printf("Error getting value of gpio %u\n", gpio);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return value == '1';
|
||||
}
|
||||
|
||||
|
|
|
@ -17,6 +17,8 @@ int gpio_export ( unsigned int gpio );
|
|||
int gpio_unexport ( unsigned int gpio );
|
||||
int gpio_set_dir ( unsigned int gpio, unsigned int out_flag );
|
||||
int gpio_set_value ( unsigned int gpio, unsigned int value );
|
||||
int gpio_set_value_fd (int fd, int value);
|
||||
int gpio_get_value ( unsigned int gpio );
|
||||
|
||||
#endif
|
||||
int gpio_get_value_fd (int fd, unsigned int gpio);
|
||||
int gpio_open_fd (unsigned int gpio);
|
||||
#endif
|
||||
|
|
Loading…
Reference in New Issue