create library
This commit is contained in:
parent
6aa21acac1
commit
86144d9e19
28
.vscode/launch.json
vendored
Normal file
28
.vscode/launch.json
vendored
Normal 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
115
.vscode/tasks.json
vendored
Normal 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,
|
||||
}
|
||||
}
|
46
Makefile
46
Makefile
@ -1,6 +1,8 @@
|
||||
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
|
||||
CPP = $(CROSS_COMPILE)cpp
|
||||
@ -10,22 +12,25 @@ GENHTML = genhtml
|
||||
|
||||
SRC_DIR = src
|
||||
OBJ_DIR = obj
|
||||
LIB_DIR = lib
|
||||
BIN_DIR = bin
|
||||
COVERAGE_DIR = coverage
|
||||
UNIT_TEST_SRC_DIR = test/unit
|
||||
UNIT_TEST_OBJ_DIR = $(OBJ_DIR)/$(UNIT_TEST_SRC_DIR)
|
||||
|
||||
PREFIX ?= /usr
|
||||
BIN_INSTALL_DIR ?= $(PREFIX)/bin/$(TARGET_FILE)
|
||||
LIB_INSTALL_DIR ?= $(PREFIX)/lib
|
||||
INC_INSTALL_DIR ?= $(PREFIX)/include/lib$(TARGET_FILE)
|
||||
|
||||
INCLUDES := inc
|
||||
|
||||
ifneq "$(findstring $(MAKECMDGOALS), build_unit_test exec_unit_test coverage)" ""
|
||||
INCLUDES += test/inc
|
||||
C_FLAGS += --coverage
|
||||
LD_FLAGS += --coverage
|
||||
L_FLAGS += --coverage
|
||||
endif
|
||||
|
||||
L_FLAGS += -shared -Wl,-soname,$(notdir $(DYNAMIC_LIB))
|
||||
C_FLAGS += -fpic
|
||||
|
||||
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)
|
||||
|
||||
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)
|
||||
TARGET = $(BIN_DIR)/$(TARGET_FILE)
|
||||
|
||||
THIS_MAKEFILE := $(lastword $(MAKEFILE_LIST))
|
||||
|
||||
.PHONY: all install uninstall clean distclean
|
||||
all: $(TARGET)
|
||||
.PHONY: all install uninstall clean
|
||||
all: $(STATIC_LIB) $(DYNAMIC_LIB)
|
||||
|
||||
install: all
|
||||
install -d $(BIN_INSTALL_DIR)
|
||||
install -m 0644 $(TARGET) $(BIN_INSTALL_DIR)
|
||||
install -d $(LIB_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:
|
||||
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:
|
||||
rm -f $(TARGET)
|
||||
rm -f $(STATIC_LIB) $(DYNAMIC_LIB)
|
||||
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_OBJ_DIR)/*.gcda
|
||||
@ -63,9 +76,6 @@ clean:
|
||||
rm -f $(OBJ_DIR)/*.gcda $(OBJ_DIR)/*.gcno
|
||||
rm -fr $(COVERAGE_DIR)
|
||||
|
||||
distclean:
|
||||
rm -rf $(OBJ_DIR) $(BIN_DIR) $(COVERAGE_DIR)
|
||||
|
||||
.PHONY: coverage
|
||||
coverage: _cov_genhtml
|
||||
$(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)
|
||||
$(CC) $(C_FLAGS) $(LD_FLAGS) $(UNIT_TEST_OBJS) -o $@
|
||||
|
||||
$(TARGET): $(OBJS) $(THIS_MAKEFILE)
|
||||
@mkdir -p $(BIN_DIR)
|
||||
$(CC) $(C_FLAGS) $(LD_FLAGS) $(OBJS) $(addprefix -l,$(LIBS)) -o $@
|
||||
$(STATIC_LIB): $(OBJS) $(THIS_MAKEFILE)
|
||||
@mkdir -p $(LIB_DIR)
|
||||
$(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
|
||||
$(OBJ_DIR)/%.d: $(SRC_DIR)/%.c
|
||||
|
24
inc/gpio_sys.h
Normal file
24
inc/gpio_sys.h
Normal 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
|
19
inc/i2c_bb.h
19
inc/i2c_bb.h
@ -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
|
@ -9,11 +9,7 @@
|
||||
#include <sys/stat.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
#define IN 0
|
||||
#define OUT 1
|
||||
|
||||
#define LOW 0
|
||||
#define HIGH 1
|
||||
#include <gpio_sys.h>
|
||||
|
||||
#define PIN 24
|
||||
#define POUT 4
|
||||
@ -22,6 +18,97 @@
|
||||
#define DIRECTION_MAX 35
|
||||
#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)
|
||||
{
|
||||
char buffer[BUF_SIZE];
|
||||
@ -30,7 +117,7 @@ static int gpio_export(int pin)
|
||||
|
||||
fd = open("/sys/class/gpio/export", O_WRONLY);
|
||||
if(-1 == fd) {
|
||||
fprintf(stderr, "Failed to open export for writing!\n");
|
||||
syslog(LOG_ERR, "Failed to open export for writing.\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
@ -49,7 +136,7 @@ static int gpio_unexport(int pin)
|
||||
|
||||
fd = open("/sys/class/gpio/unexport", O_WRONLY);
|
||||
if(-1 == fd) {
|
||||
fprintf(stderr, "Failed to open unexport for writing!\n");
|
||||
syslog(LOG_ERR, "Failed to open unexport for writing.\n");
|
||||
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);
|
||||
fd = open(path, O_WRONLY);
|
||||
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;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
close(fd);
|
||||
|
||||
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);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user