gpio driver

This commit is contained in:
Thomas Klaehn 2019-07-13 23:22:43 +02:00
parent cc851fc929
commit 8a897d5668
6 changed files with 275 additions and 56 deletions

5
.vscode/settings.json vendored Normal file
View File

@ -0,0 +1,5 @@
{
"files.associations": {
"stdbool.h": "c"
}
}

34
.vscode/tasks.json vendored
View File

@ -2,16 +2,16 @@
// See https://go.microsoft.com/fwlink/?LinkId=733558 // See https://go.microsoft.com/fwlink/?LinkId=733558
// for the documentation about the tasks.json format // for the documentation about the tasks.json format
"version": "2.0.0", "version": "2.0.0",
"type":"shell",
"command": "make",
"echoCommand": true,
"problemMatcher": {
"base": "gcc",
},
"tasks": [ "tasks": [
{ {
"label": "all", "label": "all",
"args": ["all"], "type":"shell",
"command": "make all -j4",
"problemMatcher": {
"base": "gcc",
"owner": "gcc",
"fileLocation":"absolute"
},
"group": { "group": {
"kind": "build", "kind": "build",
"isDefault": true "isDefault": true
@ -19,7 +19,23 @@
}, },
{ {
"label": "clean", "label": "clean",
"args": ["clean"], "type":"shell",
"command": "make clean -j4",
"problemMatcher": {
"base": "gcc",
"owner": "gcc",
"fileLocation":"absolute"
},
"group": {
"kind": "build",
"isDefault": true
}
}
],
"presentation": {
"focus": true,
"reveal": "always",
"panel": "shared",
"clear": true,
} }
]
} }

View File

@ -1,6 +0,0 @@
#ifndef __INC_DEF_H__
#define __INC_DEF_H__
#define HELLO "Hello world!"
#endif // __INC_DEF_H__

14
inc/gpio.h Normal file
View File

@ -0,0 +1,14 @@
#ifndef __GPIO_H__
#define __GPIO_H__
struct gpio {
unsigned int pin;
};
int gpio_open(const struct gpio *gpio);
int gpio_close(const struct gpio *gpio);
int gpio_read(const struct gpio *gpio, unsigned int *value);
int gpio_write(const struct gpio *gpio, unsigned int value);
void gpio_toggle(const struct gpio *gpio);
#endif

178
src/gpio.c Normal file
View File

@ -0,0 +1,178 @@
#include <stdlib.h>
#include <syslog.h>
#include <stdbool.h>
#include <ftdi.h>
#include <gpio.h>
struct ftdi_obj {
struct ftdi_context *ftdi;
bool is_open;
unsigned int vendor_id;
unsigned int product_id;
unsigned char bit_mask;
};
static struct ftdi_obj ftdi_obj = {
.ftdi = NULL,
.is_open = false,
.vendor_id = 0x0403,
.product_id = 0x6001,
.bit_mask = 0,
};
static int ftdi_open(void)
{
int res;
if((ftdi_obj.ftdi = ftdi_new()) == 0) {
syslog(LOG_ERR, "ftdi_new failed\n");
return EXIT_FAILURE;
}
res = ftdi_usb_open(ftdi_obj.ftdi, ftdi_obj.vendor_id, ftdi_obj.product_id);
if (res < 0 && res != -5) {
syslog(LOG_ERR, "unable to open ftdi device: %d (%s)\n", res,
ftdi_get_error_string(ftdi_obj.ftdi));
ftdi_free(ftdi_obj.ftdi);
return EXIT_FAILURE;
}
return EXIT_SUCCESS;
}
static int gpio_read_mask(const struct gpio *gpio, unsigned char *mask)
{
int res;
if(NULL == gpio || NULL == mask) {
return EXIT_FAILURE;
}
res = ftdi_read_data(ftdi_obj.ftdi, mask, 1);
if(res < 0) {
syslog(LOG_ERR, "unable to readfrom ftdi device: %d (%s)\n", res,
ftdi_get_error_string(ftdi_obj.ftdi));
return EXIT_FAILURE;
}
return EXIT_SUCCESS;
}
int gpio_open(const struct gpio *gpio)
{
int res;
unsigned char init_value = 0;
bool init_write = false;
if(NULL == gpio) {
syslog(LOG_ERR, "No valid gpio object given.\n");
return EXIT_FAILURE;
}
if(!ftdi_obj.is_open) {
res = ftdi_open();
if(res != EXIT_SUCCESS) {
return EXIT_FAILURE;
}
init_write = true;
}
ftdi_obj.bit_mask |= (unsigned char)gpio->pin;
syslog(LOG_DEBUG, "bitmask: 0x%02x\n", ftdi_obj.bit_mask);
res = ftdi_set_bitmode(ftdi_obj.ftdi, ftdi_obj.bit_mask, BITMODE_BITBANG);
if(res < 0) {
syslog(LOG_ERR, "unable to set bit bang mode: %d (%s)\n", res,
ftdi_get_error_string(ftdi_obj.ftdi));
ftdi_free(ftdi_obj.ftdi);
return EXIT_FAILURE;
}
ftdi_obj.is_open = true;
if(init_write) {
ftdi_write_data(ftdi_obj.ftdi, &init_value, 1);
}
return EXIT_SUCCESS;
}
int gpio_close(const struct gpio *gpio)
{
if(NULL == gpio) {
return EXIT_FAILURE;
}
unsigned char pin = (unsigned char)gpio->pin;
ftdi_obj.bit_mask &= ~pin;
if(ftdi_obj.bit_mask == 0) {
ftdi_usb_close(ftdi_obj.ftdi);
ftdi_free(ftdi_obj.ftdi);
}
return EXIT_SUCCESS;
}
int gpio_read(const struct gpio *gpio, unsigned int *value)
{
int res;
unsigned char buf;
if(NULL == gpio || NULL == value) {
return EXIT_FAILURE;
}
res = gpio_read_mask(gpio, &buf);
if(res != EXIT_SUCCESS) {
syslog(LOG_ERR, "unable to readfrom ftdi device: %d (%s)\n", res,
ftdi_get_error_string(ftdi_obj.ftdi));
return EXIT_FAILURE;
}
if(buf & (unsigned char)(gpio->pin)) {
*value = 1;
} else {
*value = 0;
}
return EXIT_SUCCESS;
}
int gpio_write(const struct gpio *gpio, unsigned int value)
{
int res;
unsigned char buf;
if(NULL == gpio) {
return EXIT_FAILURE;
}
res = gpio_read_mask(gpio, &buf);
if(res != EXIT_SUCCESS) {
syslog(LOG_ERR, "write failed for 0x%02x, error %d (%s)\n", buf, res,
ftdi_get_error_string(ftdi_obj.ftdi));
return EXIT_FAILURE;
}
syslog(LOG_DEBUG, "current state: 0x%02x\n", buf);
if(value == 0) {
buf &= ~(unsigned char)(gpio->pin);
}
else {
buf |= (unsigned char)(gpio->pin);
}
syslog(LOG_DEBUG, "new state: 0x%02x\n", buf);
res = ftdi_write_data(ftdi_obj.ftdi, &buf, 1);
if(res < 0) {
syslog(LOG_ERR, "write failed for 0x%x, error %d (%s)\n", value, res,
ftdi_get_error_string(ftdi_obj.ftdi));
return EXIT_FAILURE;
}
return EXIT_SUCCESS;
}
void gpio_toggle(const struct gpio *gpio)
{
}

View File

@ -1,58 +1,70 @@
#include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <unistd.h> #include <unistd.h>
#include <syslog.h> #include <syslog.h>
#include <ftdi.h>
#include <def.h> #include <gpio.h>
/*
#define GPIO1 0x08 // TX (brown)
#define GPIO2 0x01 // TX (orange)
#define GPIO3 0x02 // RX (yellow)
#define GPIO4 0x14 // RTS (green on FTDI) + DTR (on SparkFun breakout)
*/
static const struct gpio gpio_1 = {
.pin = 0x08, /* CTS (brown wire on FTDI cable) */
};
static const struct gpio gpio_2 = {
.pin = 0x01, /* TX (orange wire on FTDI cable) */
};
#define LED 0x08
int main(int argc, char *argv[]) int main(int argc, char *argv[])
{ {
struct ftdi_context *ftdi; int res, cnt;
int f, retval, cnt; unsigned int value;
unsigned char buf[1];
openlog("ftdi_gpio", LOG_CONS | LOG_PID | LOG_NDELAY, LOG_LOCAL1); openlog("ftdi_gpio", LOG_CONS | LOG_PID | LOG_NDELAY, LOG_LOCAL1);
setlogmask(LOG_DEBUG);
if ((ftdi = ftdi_new()) == 0) { res = gpio_open(&gpio_1);
syslog(LOG_ERR, "ftdi_new failed\n"); res |= gpio_open(&gpio_2);
return EXIT_FAILURE; if(res != EXIT_SUCCESS) {
syslog(LOG_ERR, "Unable to open gpio\n");
return res;
} }
f = ftdi_usb_open(ftdi, 0x0403, 0x6001);
if (f < 0 && f != -5) {
syslog(LOG_ERR, "unable to open ftdi device: %d (%s)\n", f, ftdi_get_error_string(ftdi));
retval = 1;
goto done;
}
f = ftdi_set_bitmode(ftdi, LED, BITMODE_BITBANG);
if(f < 0) {
syslog(LOG_ERR, "unable to set bit bang mode: %d (%s)\n", f, ftdi_get_error_string(ftdi));
retval = 1;
goto done;
}
buf[0] = 0;
for(cnt = 0; cnt < 10; cnt++) { for(cnt = 0; cnt < 10; cnt++) {
buf[0] ^= LED, value = cnt & 0x01;
f = ftdi_write_data(ftdi, buf, 1); res = gpio_write(&gpio_1, value);
if(f < 0) { if(cnt % 2) {
syslog(LOG_ERR, "write failed for 0x%x, error %d (%s)\n",buf[0], f, ftdi_get_error_string(ftdi)); res |= gpio_write(&gpio_2, value);
cnt = 10; }
} else { if(res != EXIT_SUCCESS) {
syslog(LOG_DEBUG, "set LED to: %u\n", (unsigned int)buf[0]); syslog(LOG_ERR, "Unable to write to gpio\n");
gpio_close(&gpio_1);
gpio_close(&gpio_2);
return res;
} }
res = gpio_read(&gpio_1, &value);
if(res != EXIT_SUCCESS) {
syslog(LOG_ERR, "Unable to read from gpio pin %u\n", gpio_1.pin);
gpio_close(&gpio_1);
return res;
}
printf("read 1 value: 0x%02x\n", value);
if(cnt % 2) {
res = gpio_read(&gpio_2, &value);
if(res != EXIT_SUCCESS) {
syslog(LOG_ERR, "Unable to read from gpio pin %u\n", gpio_2.pin);
gpio_close(&gpio_2);
return res;
}
printf("read 2 value: 0x%02x\n", value);
}
sleep(1); sleep(1);
} }
gpio_close(&gpio_1);
ftdi_usb_close(ftdi); return EXIT_SUCCESS;
done:
ftdi_free(ftdi);
closelog();
return retval;
} }