create library

This commit is contained in:
Thomas Klaehn 2019-07-25 10:26:27 +02:00
parent 6aa21acac1
commit 86144d9e19
6 changed files with 293 additions and 117 deletions

28
.vscode/launch.json vendored Normal file
View File

@ -0,0 +1,28 @@
{
// Use IntelliSense to learn about possible attributes.
// Hover to view descriptions of existing attributes.
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
"configurations": [
{
"name": "(gdb) Launch unit test",
"type": "cppdbg",
"request": "launch",
"program": "${workspaceFolder}/bin/test/unit/gpio_sys",
"args": [],
"stopAtEntry": true,
"cwd": "${workspaceFolder}",
"environment": [],
"externalConsole": false,
"MIMode": "gdb",
"setupCommands": [
{
"description": "Enable pretty-printing for gdb",
"text": "-enable-pretty-printing",
"ignoreFailures": true
}
]
}
]
}

115
.vscode/tasks.json vendored Normal file
View File

@ -0,0 +1,115 @@
{
// See https://go.microsoft.com/fwlink/?LinkId=733558
// for the documentation about the tasks.json format
"version": "2.0.0",
"tasks": [
{
"label": "all",
"type":"shell",
"command": "make all -j8",
"problemMatcher": {
"base": "$gcc",
"owner": "gcc",
"fileLocation": [
"relative",
"${workspaceFolder}"
]
},
"group": {
"kind": "build",
"isDefault": true
}
},
{
"label": "check",
"type":"shell",
"command": "make check -j8",
"problemMatcher": {
"base": "$gcc",
"owner": "gcc",
"fileLocation": [
"relative",
"${workspaceFolder}"
]
},
"group": {
"kind": "build",
"isDefault": true
}
},
{
"label": "clean",
"type":"shell",
"command": "make clean -j8",
"problemMatcher": {
"base": "$gcc",
"owner": "gcc",
"fileLocation": [
"relative",
"${workspaceFolder}"
]
},
"group": {
"kind": "build",
"isDefault": true
}
},
{
"label": "build_unit_test",
"type":"shell",
"command": "make build_unit_test -j8",
"problemMatcher": {
"base": "$gcc",
"owner": "gcc",
"fileLocation": [
"relative",
"${workspaceFolder}"
]
},
"group": {
"kind": "build",
"isDefault": true
}
},
{
"label": "exec_unit_test",
"type":"shell",
"command": "make exec_unit_test -j1",
"problemMatcher": {
"base": "$gcc",
"owner": "gcc",
"fileLocation": [
"relative",
"${workspaceFolder}"
]
},
"group": {
"kind": "build",
"isDefault": true
}
},
{
"label": "coverage",
"type":"shell",
"command": "make coverage -j1",
"problemMatcher": {
"base": "$gcc",
"owner": "gcc",
"fileLocation": [
"relative",
"${workspaceFolder}"
]
},
"group": {
"kind": "build",
"isDefault": true
}
}
],
"presentation": {
"focus": true,
"reveal": "always",
"panel": "shared",
"clear": true,
}
}

View File

@ -1,6 +1,8 @@
CROSS_COMPILE ?= CROSS_COMPILE ?=
TARGET_FILE ?= blink TARGET_FILE ?= gpio_sys
STATIC_LIB_FILE ?= lib$(TARGET_FILE).a
DYNAMIC_LIB_FILE ?= lib$(TARGET_FILE).so
CC = $(CROSS_COMPILE)gcc CC = $(CROSS_COMPILE)gcc
CPP = $(CROSS_COMPILE)cpp CPP = $(CROSS_COMPILE)cpp
@ -10,22 +12,25 @@ GENHTML = genhtml
SRC_DIR = src SRC_DIR = src
OBJ_DIR = obj OBJ_DIR = obj
LIB_DIR = lib
BIN_DIR = bin BIN_DIR = bin
COVERAGE_DIR = coverage COVERAGE_DIR = coverage
UNIT_TEST_SRC_DIR = test/unit UNIT_TEST_SRC_DIR = test/unit
UNIT_TEST_OBJ_DIR = $(OBJ_DIR)/$(UNIT_TEST_SRC_DIR) UNIT_TEST_OBJ_DIR = $(OBJ_DIR)/$(UNIT_TEST_SRC_DIR)
PREFIX ?= /usr PREFIX ?= /usr
BIN_INSTALL_DIR ?= $(PREFIX)/bin/$(TARGET_FILE) LIB_INSTALL_DIR ?= $(PREFIX)/lib
INC_INSTALL_DIR ?= $(PREFIX)/include/lib$(TARGET_FILE)
INCLUDES := inc INCLUDES := inc
ifneq "$(findstring $(MAKECMDGOALS), build_unit_test exec_unit_test coverage)" "" ifneq "$(findstring $(MAKECMDGOALS), build_unit_test exec_unit_test coverage)" ""
INCLUDES += test/inc INCLUDES += test/inc
C_FLAGS += --coverage C_FLAGS += --coverage
LD_FLAGS += --coverage L_FLAGS += --coverage
endif endif
L_FLAGS += -shared -Wl,-soname,$(notdir $(DYNAMIC_LIB))
C_FLAGS += -fpic C_FLAGS += -fpic
C_FLAGS += -O0 -g -Wall -Wextra -Werror C_FLAGS += -O0 -g -Wall -Wextra -Werror
@ -40,22 +45,30 @@ UNIT_TEST_OBJS = $(patsubst $(SRC_DIR)%,$(OBJ_DIR)%,$(patsubst $(UNIT_TEST_SRC_D
OBJS = $(C_OBJS) OBJS = $(C_OBJS)
STATIC_LIB = $(LIB_DIR)/$(STATIC_LIB_FILE)
DYNAMIC_LIB = $(LIB_DIR)/$(DYNAMIC_LIB_FILE)
UNIT_TEST_TARGET = $(BIN_DIR)/$(UNIT_TEST_SRC_DIR)/$(TARGET_FILE) UNIT_TEST_TARGET = $(BIN_DIR)/$(UNIT_TEST_SRC_DIR)/$(TARGET_FILE)
TARGET = $(BIN_DIR)/$(TARGET_FILE)
THIS_MAKEFILE := $(lastword $(MAKEFILE_LIST)) THIS_MAKEFILE := $(lastword $(MAKEFILE_LIST))
.PHONY: all install uninstall clean distclean .PHONY: all install uninstall clean
all: $(TARGET) all: $(STATIC_LIB) $(DYNAMIC_LIB)
install: all install: all
install -d $(BIN_INSTALL_DIR) install -d $(LIB_INSTALL_DIR)
install -m 0644 $(TARGET) $(BIN_INSTALL_DIR) install -d $(INC_INSTALL_DIR)
install -m 0644 $(STATIC_LIB) $(LIB_INSTALL_DIR)
install -m 0777 $(DYNAMIC_LIB) $(LIB_INSTALL_DIR)
install -m 0644 inc/* $(INC_INSTALL_DIR)
uninstall: uninstall:
rm -f $(BIN_INSTALL_DIR)/$(TARGET_FILE) rm -f $(LIB_INSTALL_DIR)/$(STATIC_LIB)
rm -f $(LIB_INSTALL_DIR)/$(DYNAMIC_LIB)
rm -f $(addprefix $(INC_INSTALL_DIR)/,$(shell ls inc))
rm -rf $(INC_INSTALL_DIR)
clean: clean:
rm -f $(TARGET) rm -f $(STATIC_LIB) $(DYNAMIC_LIB)
rm -f $(OBJS) $(patsubst %.o,%.d,$(OBJS)) rm -f $(OBJS) $(patsubst %.o,%.d,$(OBJS))
rm -f $(UNIT_TEST_OBJS) $(patsubst %.o,%.d,$(UNIT_TEST_OBJS)) $(UNIT_TEST_TARGET) rm -f $(UNIT_TEST_OBJS) $(patsubst %.o,%.d,$(UNIT_TEST_OBJS)) $(UNIT_TEST_TARGET)
rm -f $(UNIT_TEST_OBJ_DIR)/*.gcda rm -f $(UNIT_TEST_OBJ_DIR)/*.gcda
@ -63,9 +76,6 @@ clean:
rm -f $(OBJ_DIR)/*.gcda $(OBJ_DIR)/*.gcno rm -f $(OBJ_DIR)/*.gcda $(OBJ_DIR)/*.gcno
rm -fr $(COVERAGE_DIR) rm -fr $(COVERAGE_DIR)
distclean:
rm -rf $(OBJ_DIR) $(BIN_DIR) $(COVERAGE_DIR)
.PHONY: coverage .PHONY: coverage
coverage: _cov_genhtml coverage: _cov_genhtml
$(eval COVERAGE:=$(shell grep 'lines' .coverage.tmp | egrep -o '[0-9]+.[0-9]+%')) $(eval COVERAGE:=$(shell grep 'lines' .coverage.tmp | egrep -o '[0-9]+.[0-9]+%'))
@ -100,9 +110,13 @@ $(UNIT_TEST_TARGET): $(UNIT_TEST_OBJS) $(THIS_MAKEFILE)
@mkdir -p $(BIN_DIR)/$(UNIT_TEST_SRC_DIR) @mkdir -p $(BIN_DIR)/$(UNIT_TEST_SRC_DIR)
$(CC) $(C_FLAGS) $(LD_FLAGS) $(UNIT_TEST_OBJS) -o $@ $(CC) $(C_FLAGS) $(LD_FLAGS) $(UNIT_TEST_OBJS) -o $@
$(TARGET): $(OBJS) $(THIS_MAKEFILE) $(STATIC_LIB): $(OBJS) $(THIS_MAKEFILE)
@mkdir -p $(BIN_DIR) @mkdir -p $(LIB_DIR)
$(CC) $(C_FLAGS) $(LD_FLAGS) $(OBJS) $(addprefix -l,$(LIBS)) -o $@ $(AR) rcs $(STATIC_LIB) $(OBJS)
$(DYNAMIC_LIB): $(OBJS) $(THIS_MAKEFILE)
@mkdir -p $(LIB_DIR)
$(CC) $(L_FLAGS) -o $(DYNAMIC_LIB) $(OBJS)
.PRECIOUS: $(OBJ_DIR)/%.d .PRECIOUS: $(OBJ_DIR)/%.d
$(OBJ_DIR)/%.d: $(SRC_DIR)/%.c $(OBJ_DIR)/%.d: $(SRC_DIR)/%.c

24
inc/gpio_sys.h Normal file
View File

@ -0,0 +1,24 @@
#ifndef __GPIO_SYS__
#define __GPIO_SYS__
enum direction {
IN = 0,
OUT
};
enum pin_state {
LOW = 0,
HIGH
};
struct gpio_sys {
int pin;
int direction;
};
int gpio_open(const struct gpio_sys *gpio);
int gpio_close(const struct gpio_sys *gpio);
int gpio_read(const struct gpio_sys *gpio);
int gpio_write(const struct gpio_sys *gpio, int value);
#endif

View File

@ -1,19 +0,0 @@
#ifndef __I2C_BB_H__
#define __I2C_BB_H__
#include <gpio_ftdi/gpio.h>
struct i2c_bb {
struct gpio *sda;
struct gpio *scl;
};
int i2c_open(const struct i2c_bb *i2c);
int i2c_close(const struct i2c_bb *i2c);
void start_condition(const struct i2c_bb *i2c);
void stop_condition(const struct i2c_bb *i2c);
bool write_byte(const struct i2c_bb *i2c, unsigned char byte);
unsigned char read_byte(const struct i2c_bb *i2c, bool ack);
#endif

View File

@ -9,11 +9,7 @@
#include <sys/stat.h> #include <sys/stat.h>
#include <sys/types.h> #include <sys/types.h>
#define IN 0 #include <gpio_sys.h>
#define OUT 1
#define LOW 0
#define HIGH 1
#define PIN 24 #define PIN 24
#define POUT 4 #define POUT 4
@ -22,6 +18,97 @@
#define DIRECTION_MAX 35 #define DIRECTION_MAX 35
#define VALUE_MAX 30 #define VALUE_MAX 30
static int gpio_export(int pin);
static int gpio_unexport(int pin);
static int gpio_direction(int pin, int dir);
int gpio_open(const struct gpio_sys *gpio)
{
int res;
assert(NULL != gpio);
syslog(LOG_DEBUG, "Start opening gpio pin %d.\n", gpio->pin);
res = gpio_export(gpio->pin);
if(res < 0) {
syslog(LOG_ERR, "Unable to export pin %d.\n", gpio->pin);
return res;
}
res = gpio_direction(gpio->pin, gpio->direction);
if(res < 0) {
syslog(LOG_ERR, "Unable to set direction for pin %d.\n", gpio->pin);
return res;
}
syslog(LOG_DEBUG, "Gpio pin %d successfully opened.\n", gpio->pin);
return 0;
}
int gpio_close(const struct gpio_sys *gpio)
{
int res;
assert(NULL != gpio);
syslog(LOG_DEBUG, "Start closing gpio pin %d\n.", gpio->pin);
res = gpio_unexport(gpio->pin);
if(res < 0) {
syslog(LOG_ERR, "Unable to unexport pin %d.\n", gpio->pin);
return res;
}
syslog(LOG_DEBUG, "Gpio pin %d successfully closed.\n", gpio->pin);
return 0;
}
int gpio_read(const struct gpio_sys *gpio)
{
char path[VALUE_MAX];
char value_str[BUF_SIZE];
int fd;
assert(NULL != gpio);
snprintf(path, VALUE_MAX, "/sys/class/gpio/gpio%d/value", gpio->pin);
fd = open(path, O_RDONLY);
if(-1 == fd) {
syslog(LOG_ERR, "Failed to open pin %d value for reading.\n", gpio->pin);
return -1;
}
if(-1 == read(fd, value_str, BUF_SIZE)) {
syslog(LOG_ERR, "Failed to read value for pin %d.\n", gpio->pin);
return -1;
}
close(fd);
return(atoi(value_str));
}
int gpio_write(const struct gpio_sys *gpio, int value)
{
static const char s_values_str[] = "01";
char path[VALUE_MAX];
int fd;
assert(NULL != gpio);
snprintf(path, VALUE_MAX, "/sys/class/gpio/gpio%d/value", gpio->pin);
fd = open(path, O_WRONLY);
if(-1 == fd) {
syslog(LOG_ERR, "Failed to open pin %d value for writing.\n", gpio->pin);
return -1;
}
if(1 != write(fd, &s_values_str[LOW == value ? 0 : 1], 1)) {
syslog(LOG_ERR, "Failed to write value for pin %d.\n", gpio->pin);
return -1;
}
close(fd);
return 0;
}
static int gpio_export(int pin) static int gpio_export(int pin)
{ {
char buffer[BUF_SIZE]; char buffer[BUF_SIZE];
@ -30,7 +117,7 @@ static int gpio_export(int pin)
fd = open("/sys/class/gpio/export", O_WRONLY); fd = open("/sys/class/gpio/export", O_WRONLY);
if(-1 == fd) { if(-1 == fd) {
fprintf(stderr, "Failed to open export for writing!\n"); syslog(LOG_ERR, "Failed to open export for writing.\n");
return -1; return -1;
} }
@ -49,7 +136,7 @@ static int gpio_unexport(int pin)
fd = open("/sys/class/gpio/unexport", O_WRONLY); fd = open("/sys/class/gpio/unexport", O_WRONLY);
if(-1 == fd) { if(-1 == fd) {
fprintf(stderr, "Failed to open unexport for writing!\n"); syslog(LOG_ERR, "Failed to open unexport for writing.\n");
return -1; return -1;
} }
@ -69,88 +156,15 @@ static int gpio_direction(int pin, int dir)
snprintf(path, DIRECTION_MAX, "/sys/class/gpio/gpio%d/direction", pin); snprintf(path, DIRECTION_MAX, "/sys/class/gpio/gpio%d/direction", pin);
fd = open(path, O_WRONLY); fd = open(path, O_WRONLY);
if(-1 == fd) { if(-1 == fd) {
fprintf(stderr, "Failed to open gpio direction for writing!\n"); syslog(LOG_ERR, "Failed to open direction for writing.\n");
return -1; return -1;
} }
if(-1 == write(fd, &directions_str[IN == dir ? 0 : 3], IN == dir ? 2 : 3)) { if(-1 == write(fd, &directions_str[IN == dir ? 0 : 3], IN == dir ? 2 : 3)) {
fprintf(stderr, "Failed to set direction!\n"); syslog(LOG_ERR, "Failed to set direction.\n");
return -1; return -1;
} }
close(fd); close(fd);
return 0; return 0;
} }
static int gpio_read(int pin)
{
char path[VALUE_MAX];
char value_str[BUF_SIZE];
int fd;
snprintf(path, VALUE_MAX, "/sys/class/gpio/gpio%d/value", pin);
fd = open(path, O_RDONLY);
if(-1 == fd) {
fprintf(stderr, "Failed to open gpio value for reading!\n");
return -1;
}
if(-1 == read(fd, value_str, BUF_SIZE)) {
fprintf(stderr, "Failed to read value!\n");
return -1;
}
close(fd);
return(atoi(value_str));
}
static int gpio_write(int pin, int value)
{
static const char s_values_str[] = "01";
char path[VALUE_MAX];
int fd;
snprintf(path, VALUE_MAX, "/sys/class/gpio/gpio%d/value", pin);
fd = open(path, O_WRONLY);
if(-1 == fd) {
fprintf(stderr, "Failed to open gpio value for writing!\n");
return -1;
}
if(1 != write(fd, &s_values_str[LOW == value ? 0 : 1], 1)) {
fprintf(stderr, "Failed to write value!\n");
return -1;
}
close(fd);
return 0;
}
int main(void)
{
int repeat = 10;
if(-1 == gpio_export(POUT) || -1 == gpio_export(PIN)) {
return(1);
}
if(-1 == gpio_direction(POUT, OUT) || -1 == gpio_direction(PIN, IN)) {
return(2);
}
do {
if(-1 == gpio_write(POUT, repeat % 2)) {
return(3);
}
printf("I'm reading %d in GPIO %d\n", gpio_read(PIN), PIN);
usleep(500 * 1000);
} while(repeat--);
if(-1 == gpio_unexport(POUT) || -1 == gpio_unexport(PIN)) {
return(4);
}
return(0);
}