Compare commits
4 Commits
1.0
..
c12d49bca0
| Author | SHA1 | Date | |
|---|---|---|---|
| c12d49bca0 | |||
| 39592bc80e | |||
| 1d317af410 | |||
| 82becab1cc |
Vendored
+1
-1
@@ -4,7 +4,7 @@
|
||||
"name": "Linux",
|
||||
"includePath": [
|
||||
"${workspaceFolder}/**",
|
||||
"/usr/include/libgpio_sys"
|
||||
"/usr/include/gpio_ftdi"
|
||||
],
|
||||
"defines": [],
|
||||
"compilerPath": "/usr/bin/clang",
|
||||
|
||||
Vendored
-17
@@ -54,23 +54,6 @@
|
||||
"isDefault": true
|
||||
}
|
||||
},
|
||||
{
|
||||
"label": "distclean",
|
||||
"type":"shell",
|
||||
"command": "make distclean -j8",
|
||||
"problemMatcher": {
|
||||
"base": "$gcc",
|
||||
"owner": "gcc",
|
||||
"fileLocation": [
|
||||
"relative",
|
||||
"${workspaceFolder}"
|
||||
]
|
||||
},
|
||||
"group": {
|
||||
"kind": "build",
|
||||
"isDefault": true
|
||||
}
|
||||
},
|
||||
{
|
||||
"label": "build_unit_test",
|
||||
"type":"shell",
|
||||
|
||||
@@ -19,12 +19,11 @@ UNIT_TEST_SRC_DIR = test/unit
|
||||
UNIT_TEST_OBJ_DIR = $(OBJ_DIR)/$(UNIT_TEST_SRC_DIR)
|
||||
|
||||
PREFIX ?= /usr
|
||||
LIB_INSTALL_DIR ?= $(PREFIX)/lib
|
||||
LIB_INSTALL_DIR ?= $(PREFIX)/lib/$(TARGET_FILE)
|
||||
INC_INSTALL_DIR ?= $(PREFIX)/include/lib$(TARGET_FILE)
|
||||
|
||||
INCLUDES := inc
|
||||
INCLUDES += $(PREFIX)/include/
|
||||
INCLUDES += $(EXTRA_INC)
|
||||
|
||||
ifneq "$(findstring $(MAKECMDGOALS), build_unit_test exec_unit_test coverage)" ""
|
||||
INCLUDES += test/inc
|
||||
@@ -37,9 +36,7 @@ C_FLAGS += -fpic
|
||||
|
||||
C_FLAGS += -O0 -g -Wall -Wextra -Werror
|
||||
CPP_FLAGS += $(addprefix -I, $(INCLUDES))
|
||||
|
||||
CHECK_FLAGS = $(addprefix -I,$(filter-out $(PREFIX)/include/,$(INCLUDES)))
|
||||
CHECK_FLAGS += --enable=all --template=gcc --error-exitcode=1 --suppress=missingIncludeSystem --inline-suppr --force
|
||||
CHECK_FLAGS = --enable=all --template=gcc --error-exitcode=1 --suppress=missingIncludeSystem --inline-suppr
|
||||
|
||||
C_SRCS = $(wildcard $(SRC_DIR)/*.c)
|
||||
C_OBJS = $(patsubst $(SRC_DIR)%,$(OBJ_DIR)%,$(patsubst %.c,%.o,$(C_SRCS)))
|
||||
@@ -55,7 +52,7 @@ UNIT_TEST_TARGET = $(BIN_DIR)/$(UNIT_TEST_SRC_DIR)/$(TARGET_FILE)
|
||||
|
||||
THIS_MAKEFILE := $(lastword $(MAKEFILE_LIST))
|
||||
|
||||
.PHONY: all install uninstall clean distclean
|
||||
.PHONY: all install uninstall clean
|
||||
all: $(STATIC_LIB) $(DYNAMIC_LIB)
|
||||
|
||||
install: all
|
||||
@@ -66,8 +63,8 @@ install: all
|
||||
install -m 0644 inc/* $(INC_INSTALL_DIR)
|
||||
|
||||
uninstall:
|
||||
rm -f $(LIB_INSTALL_DIR)/$(STATIC_LIB_FILE)
|
||||
rm -f $(LIB_INSTALL_DIR)/$(DYNAMIC_LIB_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)
|
||||
|
||||
@@ -80,9 +77,6 @@ clean:
|
||||
rm -f $(OBJ_DIR)/*.gcda $(OBJ_DIR)/*.gcno
|
||||
rm -fr $(COVERAGE_DIR)
|
||||
|
||||
distclean:
|
||||
rm -fr $(BIN_DIR) $(OBJ_DIR) $(LIB_DIR) $(COVERAGE_DIR)
|
||||
|
||||
.PHONY: coverage
|
||||
coverage: _cov_genhtml
|
||||
$(eval COVERAGE:=$(shell grep 'lines' .coverage.tmp | egrep -o '[0-9]+.[0-9]+%'))
|
||||
@@ -111,7 +105,7 @@ exec_unit_test: $(UNIT_TEST_TARGET)
|
||||
|
||||
.PHONY: check
|
||||
check: $(C_SRCS)
|
||||
$(CHECK) $(CHECK_FLAGS) $(C_SRCS)
|
||||
$(CHECK) $(CPP_FLAGS) $(CHECK_FLAGS) $(C_SRCS)
|
||||
|
||||
$(UNIT_TEST_TARGET): $(UNIT_TEST_OBJS) $(THIS_MAKEFILE)
|
||||
@mkdir -p $(BIN_DIR)/$(UNIT_TEST_SRC_DIR)
|
||||
|
||||
@@ -1,105 +0,0 @@
|
||||
# I2C BB
|
||||
|
||||
I2C bitbang gpio driver using gpio_sys gpio driver
|
||||
|
||||
## Installation
|
||||
|
||||
```shell
|
||||
make install
|
||||
```
|
||||
|
||||
Installs `libi2c_bb.a` and `libi2c_bb.so` in the directory `$(PREFIX)/lib/`. It also installs the include header file `i2c.h` in the directory `$(PREFIX)/include/i2c_bb/`. The default value for `PREFIX` is: `PREFIX=usr`. To use another location for installation changing the value of the `PREFIX` variable is needed. E.g.:
|
||||
|
||||
```shell
|
||||
PREFIX=/usr/local/ make install
|
||||
```
|
||||
|
||||
## Uninstallation
|
||||
|
||||
```shell
|
||||
make install
|
||||
```
|
||||
|
||||
Removes the files installed with the `install` make target.
|
||||
> **NOTE:** If `PREFIX` variable was changed during installation process the same value needs to be set for uninstallation. E.g.:
|
||||
|
||||
```shell
|
||||
PREFIX=/usr/local/ make install
|
||||
```
|
||||
|
||||
## Example
|
||||
|
||||
```C
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <syslog.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#include <i2c_bb/i2c.h>
|
||||
|
||||
#define I2C_SLAVE_ADDR 0x48
|
||||
#define BUFFER_SIZE 3
|
||||
|
||||
static const struct gpio_sys gpio_sda = {
|
||||
.pin = 4,
|
||||
.direction = 0, // out
|
||||
};
|
||||
|
||||
static const struct gpio_sys gpio_scl = {
|
||||
.pin = 24,
|
||||
.direction = 0, // out
|
||||
};
|
||||
|
||||
const static struct i2c_bb i2c_dev = {
|
||||
.sda = &gpio_sda,
|
||||
.scl = &gpio_scl,
|
||||
};
|
||||
|
||||
int main(void)
|
||||
{
|
||||
int res;
|
||||
char buffer[BUFFER_SIZE]
|
||||
|
||||
openlog("i2c_bb", LOG_CONS | LOG_PID | LOG_NDELAY, LOG_LOCAL1);
|
||||
|
||||
res = i2c_open(&i2c_dev);
|
||||
if(res != EXIT_SUCCESS) {
|
||||
syslog(LOG_ERR, "Unable to open i2c device.\n");
|
||||
return res;
|
||||
}
|
||||
|
||||
buffer[0] = 0x01;
|
||||
buffer[1] = 0xc1;
|
||||
buffer[2] = 0x87;
|
||||
|
||||
// Write to register address 0x01 value 0xc187:
|
||||
i2c_write(&i2c_dev, I2C_SLAVE_ADDR, buffer, BUFFER_SIZE);
|
||||
|
||||
buffer[0] = 0x00;
|
||||
|
||||
// Set register address 0x00:
|
||||
i2c_write(&i2c_dev, addr, buffer, 1);
|
||||
|
||||
// Read from register 0x00 two bytes:
|
||||
i2c_read(&i2c_dev, I2C_SLAVE_ADDR, buffer, 2);
|
||||
|
||||
i2c_close(&i2c_dev);
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
```
|
||||
|
||||
## Additional make targets
|
||||
|
||||
| Target | Meaning |
|
||||
| --------------- | ----------------------------------------------------------- |
|
||||
| all | Build the code, assemble the static and shared library. |
|
||||
| install | Install the libraries and necessary include header files. |
|
||||
| uninstall | Uninstall the libraries and necessary include header files. |
|
||||
| clean | Clean up build artifacts. |
|
||||
| distclean | Remove all folders created during any build step. |
|
||||
| build_unit_test | Build the unit tests. |
|
||||
| exec_unit_test | Execute the unit tests. |
|
||||
| coverage | Determine code coverage of the unit tests. |
|
||||
| check | Static code analysis (cppcheck). |
|
||||
@@ -1,17 +0,0 @@
|
||||
#ifndef __I2C_BB_H__
|
||||
#define __I2C_BB_H__
|
||||
|
||||
#include <libgpio_sys/gpio.h>
|
||||
|
||||
struct i2c_bb {
|
||||
struct gpio_sys *sda;
|
||||
struct gpio_sys *scl;
|
||||
};
|
||||
|
||||
int i2c_open(const struct i2c_bb *i2c);
|
||||
int i2c_close(const struct i2c_bb *i2c);
|
||||
|
||||
int i2c_read(const struct i2c_bb *i2c, uint8_t slave_addr, char *buffer, unsigned int len);
|
||||
int i2c_write(const struct i2c_bb *i2c, uint8_t slave_addr, const char *buffer, unsigned int len);
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,19 @@
|
||||
#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
|
||||
@@ -5,15 +5,11 @@
|
||||
#include <stdint.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <i2c.h>
|
||||
#include <i2c_bb.h>
|
||||
|
||||
|
||||
static void write_bit(const struct i2c_bb *i2c, uint8_t bit);
|
||||
static uint8_t read_bit(const struct i2c_bb *i2c);
|
||||
static void start_condition(const struct i2c_bb *i2c);
|
||||
static void stop_condition(const struct i2c_bb *i2c);
|
||||
static bool write_byte(const struct i2c_bb *i2c, uint8_t byte);
|
||||
static uint8_t read_byte(const struct i2c_bb *i2c, bool ack);
|
||||
|
||||
// cppcheck-suppress unusedFunction
|
||||
int i2c_open(const struct i2c_bb *i2c)
|
||||
@@ -23,11 +19,7 @@ int i2c_open(const struct i2c_bb *i2c)
|
||||
assert(NULL != i2c);
|
||||
|
||||
res = gpio_open(i2c->sda);
|
||||
res |= gpio_direction(i2c->sda, 1);
|
||||
res |= gpio_open(i2c->scl);
|
||||
res |= gpio_direction(i2c->scl, 1);
|
||||
res |= gpio_write(i2c->sda, 1);
|
||||
res |= gpio_write(i2c->scl, 1);
|
||||
res |= gpio_open(i2c->sda);
|
||||
|
||||
return res;
|
||||
}
|
||||
@@ -39,53 +31,13 @@ int i2c_close(const struct i2c_bb *i2c)
|
||||
assert(NULL != i2c);
|
||||
|
||||
res = gpio_close(i2c->sda);
|
||||
res |= gpio_close(i2c->scl);
|
||||
res |= gpio_close(i2c->sda);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
// cppcheck-suppress unusedFunction
|
||||
int i2c_read(const struct i2c_bb *i2c, uint8_t slave_addr, char *buffer, unsigned int len)
|
||||
{
|
||||
unsigned int i;
|
||||
assert(NULL != i2c);
|
||||
|
||||
if((NULL == buffer) || len == 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
start_condition(i2c);
|
||||
write_byte(i2c, (slave_addr << 1) | 1);
|
||||
for(i = 0; i < len; i++) {
|
||||
buffer[i] = read_byte(i2c, true);
|
||||
}
|
||||
stop_condition(i2c);
|
||||
|
||||
return (int)i;
|
||||
}
|
||||
|
||||
// cppcheck-suppress unusedFunction
|
||||
int i2c_write(const struct i2c_bb *i2c, uint8_t slave_addr, const char *buffer, unsigned int len)
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
assert(NULL != i2c);
|
||||
|
||||
if((NULL == buffer) || len == 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
start_condition(i2c);
|
||||
write_byte(i2c, slave_addr << 1);
|
||||
for(i = 0; i < len; i++) {
|
||||
write_byte(i2c, buffer[i]);
|
||||
}
|
||||
stop_condition(i2c);
|
||||
|
||||
return (int)i;
|
||||
}
|
||||
|
||||
static void start_condition(const struct i2c_bb *i2c)
|
||||
void start_condition(const struct i2c_bb *i2c)
|
||||
{
|
||||
assert( NULL != i2c);
|
||||
|
||||
@@ -98,7 +50,8 @@ static void start_condition(const struct i2c_bb *i2c)
|
||||
usleep(5);
|
||||
}
|
||||
|
||||
static void stop_condition(const struct i2c_bb *i2c)
|
||||
// cppcheck-suppress unusedFunction
|
||||
void stop_condition(const struct i2c_bb *i2c)
|
||||
{
|
||||
assert( NULL != i2c);
|
||||
|
||||
@@ -110,7 +63,8 @@ static void stop_condition(const struct i2c_bb *i2c)
|
||||
usleep(5);
|
||||
}
|
||||
|
||||
static bool write_byte(const struct i2c_bb *i2c, uint8_t byte)
|
||||
// cppcheck-suppress unusedFunction
|
||||
bool write_byte(const struct i2c_bb *i2c, unsigned char byte)
|
||||
{
|
||||
uint8_t ack, i;
|
||||
|
||||
@@ -126,7 +80,8 @@ static bool write_byte(const struct i2c_bb *i2c, uint8_t byte)
|
||||
return (bool)(ack & 0x01);
|
||||
}
|
||||
|
||||
static uint8_t read_byte(const struct i2c_bb *i2c, bool ack)
|
||||
// cppcheck-suppress unusedFunction
|
||||
unsigned char read_byte(const struct i2c_bb *i2c, bool ack)
|
||||
{
|
||||
uint8_t res = 0, i;
|
||||
|
||||
@@ -140,7 +95,7 @@ static uint8_t read_byte(const struct i2c_bb *i2c, bool ack)
|
||||
if(ack) {
|
||||
write_bit(i2c, 0);
|
||||
} else {
|
||||
write_bit(i2c, 1);
|
||||
write_bit(i2c, 0);
|
||||
}
|
||||
|
||||
return res;
|
||||
@@ -150,35 +105,29 @@ static void write_bit(const struct i2c_bb *i2c, uint8_t bit)
|
||||
{
|
||||
assert( NULL != i2c);
|
||||
|
||||
if(bit > 0) {
|
||||
if((bit & 0x01) > 0) {
|
||||
gpio_write(i2c->sda, 1);
|
||||
} else {
|
||||
gpio_write(i2c->sda, 0);
|
||||
gpio_write(i2c->sda, 1);
|
||||
}
|
||||
usleep(5);
|
||||
gpio_write(i2c->scl, 1);
|
||||
usleep(5);
|
||||
gpio_write(i2c->scl, 0);
|
||||
gpio_write(i2c->scl, 1);
|
||||
}
|
||||
|
||||
static uint8_t read_bit(const struct i2c_bb *i2c)
|
||||
{
|
||||
int res;
|
||||
unsigned int res;
|
||||
|
||||
assert(NULL != i2c);
|
||||
|
||||
gpio_write(i2c->sda, 1);
|
||||
usleep(5);
|
||||
gpio_write(i2c->scl, 1);
|
||||
gpio_direction(i2c->sda, 0);
|
||||
usleep(5);
|
||||
res = gpio_read(i2c->sda);
|
||||
gpio_write(i2c->scl, 0);
|
||||
gpio_direction(i2c->sda, 1);
|
||||
|
||||
if(res < 0) {
|
||||
res = 0;
|
||||
}
|
||||
gpio_read(i2c->sda, &res);
|
||||
gpio_write(i2c->scl, 1);
|
||||
|
||||
return (uint8_t) res;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
#ifndef __MOCK_FTDI_H__
|
||||
#define __MOCK_FTDI_H__
|
||||
|
||||
#include <fff.h>
|
||||
|
||||
DEFINE_FFF_GLOBALS;
|
||||
|
||||
DECLARE_FAKE_VALUE_FUNC(int, gpio_open, const struct gpio *);
|
||||
DECLARE_FAKE_VALUE_FUNC(int, gpio_close, const struct gpio *);
|
||||
DECLARE_FAKE_VALUE_FUNC(int, gpio_read, const struct gpio *, unsigned int *);
|
||||
DECLARE_FAKE_VALUE_FUNC(int, gpio_write, const struct gpio *, unsigned int);
|
||||
DECLARE_FAKE_VALUE_FUNC(int, gpio_toggle, const struct gpio *);
|
||||
|
||||
#endif
|
||||
@@ -1,14 +0,0 @@
|
||||
#ifndef __MOCK_GPIO_H__
|
||||
#define __MOCK_GPIO_H__
|
||||
|
||||
#include <fff.h>
|
||||
|
||||
DEFINE_FFF_GLOBALS;
|
||||
|
||||
DECLARE_FAKE_VALUE_FUNC(int, gpio_open, const struct gpio_sys *);
|
||||
DECLARE_FAKE_VALUE_FUNC(int, gpio_close, const struct gpio_sys *);
|
||||
DECLARE_FAKE_VALUE_FUNC(int, gpio_direction, struct gpio_sys *, int);
|
||||
DECLARE_FAKE_VALUE_FUNC(int, gpio_read, const struct gpio_sys *);
|
||||
DECLARE_FAKE_VALUE_FUNC(int, gpio_write, const struct gpio_sys *, int);
|
||||
|
||||
#endif
|
||||
@@ -4,9 +4,9 @@
|
||||
#include <sys/syscall.h>
|
||||
|
||||
#include <utest.h>
|
||||
#include <mock_gpio.h>
|
||||
#include <mock_ftdi.h>
|
||||
|
||||
#include <i2c.h>
|
||||
#include <i2c_bb.h>
|
||||
|
||||
UTEST(i2c_close, success)
|
||||
{
|
||||
|
||||
@@ -4,9 +4,9 @@
|
||||
#include <sys/syscall.h>
|
||||
|
||||
#include <utest.h>
|
||||
#include <mock_gpio.h>
|
||||
#include <mock_ftdi.h>
|
||||
|
||||
#include <i2c.h>
|
||||
#include <i2c_bb.h>
|
||||
|
||||
UTEST(i2c_open, success)
|
||||
{
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
#include <mock_ftdi.h>
|
||||
|
||||
DEFINE_FFF_GLOBALS;
|
||||
|
||||
DEFINE_FAKE_VALUE_FUNC(int, gpio_open, const struct gpio *);
|
||||
DEFINE_FAKE_VALUE_FUNC(int, gpio_close, const struct gpio *);
|
||||
DEFINE_FAKE_VALUE_FUNC(int, gpio_read, const struct gpio *, unsigned int *);
|
||||
DEFINE_FAKE_VALUE_FUNC(int, gpio_write, const struct gpio *, unsigned int);
|
||||
DEFINE_FAKE_VALUE_FUNC(int, gpio_toggle, const struct gpio *);
|
||||
@@ -1,9 +0,0 @@
|
||||
#include <mock_gpio.h>
|
||||
|
||||
DEFINE_FFF_GLOBALS;
|
||||
|
||||
DEFINE_FAKE_VALUE_FUNC(int, gpio_open, const struct gpio_sys *);
|
||||
DEFINE_FAKE_VALUE_FUNC(int, gpio_close, const struct gpio_sys *);
|
||||
DEFINE_FAKE_VALUE_FUNC(int, gpio_direction, struct gpio_sys *, int);
|
||||
DEFINE_FAKE_VALUE_FUNC(int, gpio_read, const struct gpio_sys *);
|
||||
DEFINE_FAKE_VALUE_FUNC(int, gpio_write, const struct gpio_sys *, int);
|
||||
Reference in New Issue
Block a user