Include first driver: SHT31

Make I2C reads blocking w/ timeout
Add SHT31 driver, roughly :)
Fix mg_time() to return a double.
This commit is contained in:
Pim van Pelt
2018-04-02 17:29:13 +02:00
parent cef7c5107d
commit b1d92a32a8
9 changed files with 396 additions and 35 deletions

View File

@ -6,16 +6,35 @@
#include <i2c/smbus.h>
#include <sys/ioctl.h>
#include <unistd.h>
#include <errno.h>
struct mgos_i2c {
int fd;
uint16_t read_timeout_ms; // in msec
char *filename;
};
static struct mgos_i2c *s_global_i2c_bus = NULL;
static size_t i2c_read_timeout(struct mgos_i2c *i2c, void *data, size_t len) {
uint16_t tries;
size_t ret=-1;
if (!i2c) return -1;
ret = read(i2c->fd, data, len);
for(tries=i2c->read_timeout_ms; tries && ret!=len && len>0; tries--) {
usleep(1000);
ret = read(i2c->fd, data, len);
}
if (ret!=len) {
// LOG(LL_ERROR, ("Read timeout on I2C"));
return -1;
}
return len;
}
bool mgos_i2c_read(struct mgos_i2c *i2c, uint16_t addr, void *data, size_t len, bool stop) {
size_t ret;
@ -28,8 +47,12 @@ bool mgos_i2c_read(struct mgos_i2c *i2c, uint16_t addr, void *data, size_t len,
LOG(LL_ERROR, ("Cannot select slave 0x%04x on I2C bus", addr));
return false;
}
ret = read(i2c->fd, data, len);
return (ret == len);
ret = i2c_read_timeout(i2c, data, len);
if (ret != len) {
// LOG(LL_DEBUG, ("RECV %ld bytes (wanted %lu) from 0x%02x: %s", ret, len, addr, strerror(errno)));
return false;
}
return true;
}
bool mgos_i2c_write(struct mgos_i2c *i2c, uint16_t addr, const void *data, size_t len, bool stop) {
@ -45,7 +68,11 @@ bool mgos_i2c_write(struct mgos_i2c *i2c, uint16_t addr, const void *data, size_
return false;
}
ret = write(i2c->fd, data, len);
return (ret == len);
if (ret != len) {
// LOG(LL_DEBUG, ("XMIT %ld bytes (wanted %lu) from 0x%02x: %s", ret, len, addr, strerror(errno)));
return false;
}
return true;
}
void mgos_i2c_stop(struct mgos_i2c *i2c) {
@ -70,15 +97,15 @@ int mgos_i2c_read_reg_b(struct mgos_i2c *i2c, uint16_t addr, uint8_t reg) {
}
if (ioctl(i2c->fd,I2C_SLAVE,addr) < 0) {
LOG(LL_ERROR, ("Cannot select slave 0x%04x on I2C bus", addr));
LOG(LL_ERROR, ("Cannot select slave 0x%04x on I2C bus: %s", addr, strerror(errno)));
return -1;
}
if (1 != write(i2c->fd, &reg, 1)) {
LOG(LL_ERROR, ("Cannot select register 0x%02x on device 0x%04x", reg, addr));
LOG(LL_ERROR, ("Cannot select register 0x%02x on device 0x%04x: %s", reg, addr, strerror(errno)));
return -1;
}
if (1 != read(i2c->fd, &data, 1)) {
LOG(LL_ERROR, ("Cannot read register 0x%02x on device 0x%04x", reg, addr));
if (1 != i2c_read_timeout(i2c, &data, 1)) {
LOG(LL_ERROR, ("Cannot read register 0x%02x on device 0x%04x: %s", reg, addr, strerror(errno)));
return -1;
}
return data;
@ -93,15 +120,15 @@ int mgos_i2c_read_reg_w(struct mgos_i2c *i2c, uint16_t addr, uint8_t reg) {
}
if (ioctl(i2c->fd,I2C_SLAVE,addr) < 0) {
LOG(LL_ERROR, ("Cannot select slave 0x%04x on I2C bus", addr));
LOG(LL_ERROR, ("Cannot select slave 0x%04x on I2C bus: %s", addr, strerror(errno)));
return -1;
}
if (1 != write(i2c->fd, &reg, 1)) {
LOG(LL_ERROR, ("Cannot select register 0x%02x on device 0x%04x", reg, addr));
LOG(LL_ERROR, ("Cannot select register 0x%02x on device 0x%04x: %s", reg, addr, strerror(errno)));
return -1;
}
if (2 != read(i2c->fd, &data, 2)) {
LOG(LL_ERROR, ("Cannot read register 0x%02x on device 0x%04x", reg, addr));
if (2 != i2c_read_timeout(i2c, &data, 2)) {
LOG(LL_ERROR, ("Cannot read register 0x%02x on device 0x%04x: %s", reg, addr, strerror(errno)));
return -1;
}
return data;
@ -114,15 +141,15 @@ bool mgos_i2c_read_reg_n(struct mgos_i2c *i2c, uint16_t addr, uint8_t reg, size_
}
if (ioctl(i2c->fd,I2C_SLAVE,addr) < 0) {
LOG(LL_ERROR, ("Cannot select slave 0x%04x on I2C bus", addr));
LOG(LL_ERROR, ("Cannot select slave 0x%04x on I2C bus: %s", addr, strerror(errno)));
return false;
}
if (1 != write(i2c->fd, &reg, 1)) {
LOG(LL_ERROR, ("Cannot select register 0x%02x on device 0x%04x", reg, addr));
LOG(LL_ERROR, ("Cannot select register 0x%02x on device 0x%04x: %s", reg, addr, strerror(errno)));
return false;
}
if (n != read(i2c->fd, buf, n)) {
LOG(LL_ERROR, ("Cannot read %lu bytes at register 0x%02x on device 0x%04x", n, reg, addr));
if (n != i2c_read_timeout(i2c, buf, n)) {
LOG(LL_ERROR, ("Cannot read %lu bytes at register 0x%02x on device 0x%04x: %s", n, reg, addr, strerror(errno)));
return false;
}
return true;
@ -137,13 +164,13 @@ bool mgos_i2c_write_reg_b(struct mgos_i2c *i2c, uint16_t addr, uint8_t reg, uint
}
if (ioctl(i2c->fd,I2C_SLAVE,addr) < 0) {
LOG(LL_ERROR, ("Cannot select slave 0x%04x on I2C bus", addr));
LOG(LL_ERROR, ("Cannot select slave 0x%04x on I2C bus: %s", addr, strerror(errno)));
return false;
}
data[0]=reg;
data[1]=value;
if (2 != write(i2c->fd, data, 2)) {
LOG(LL_ERROR, ("Cannot write to register 0x%02x on device 0x%04x", reg, addr));
LOG(LL_ERROR, ("Cannot write to register 0x%02x on device 0x%04x: %s", reg, addr, strerror(errno)));
return false;
}
return true;
@ -158,7 +185,7 @@ bool mgos_i2c_write_reg_w(struct mgos_i2c *i2c, uint16_t addr, uint8_t reg, uint
}
if (ioctl(i2c->fd,I2C_SLAVE,addr) < 0) {
LOG(LL_ERROR, ("Cannot select slave 0x%04x on I2C bus", addr));
LOG(LL_ERROR, ("Cannot select slave 0x%04x on I2C bus: %s", addr, strerror(errno)));
return false;
}
data[0]=reg;
@ -166,7 +193,7 @@ bool mgos_i2c_write_reg_w(struct mgos_i2c *i2c, uint16_t addr, uint8_t reg, uint
data[2]=(uint8_t)(0xFF & (value >> 8));
if (3 != write(i2c->fd, data, 3)) {
LOG(LL_ERROR, ("Cannot write to register 0x%02x on device 0x%04x", reg, addr));
LOG(LL_ERROR, ("Cannot write to register 0x%02x on device 0x%04x: %s", reg, addr, strerror(errno)));
return false;
}
return true;
@ -179,16 +206,16 @@ bool mgos_i2c_write_reg_n(struct mgos_i2c *i2c, uint16_t addr, uint8_t reg, size
}
if (ioctl(i2c->fd,I2C_SLAVE,addr) < 0) {
LOG(LL_ERROR, ("Cannot select slave 0x%04x on I2C bus", addr));
LOG(LL_ERROR, ("Cannot select slave 0x%04x on I2C bus: %s", addr, strerror(errno)));
return false;
}
if (1 != write(i2c->fd, &reg, 1)) {
LOG(LL_ERROR, ("Cannot select register 0x%02x on device 0x%04x", reg, addr));
LOG(LL_ERROR, ("Cannot select register 0x%02x on device 0x%04x: %s", reg, addr, strerror(errno)));
return false;
}
if (n != write(i2c->fd, buf, n)) {
LOG(LL_ERROR, ("Cannot write to register 0x%02x on device 0x%04x", reg, addr));
LOG(LL_ERROR, ("Cannot write to register 0x%02x on device 0x%04x: %s", reg, addr, strerror(errno)));
return false;
}
return true;
@ -202,6 +229,42 @@ struct mgos_i2c *mgos_i2c_get_global(void) {
return s_global_i2c_bus;
}
int get_i2c_register(struct mgos_i2c *i2c, uint8_t addr, uint8_t reg, uint8_t *val) {
unsigned char inbuf, outbuf;
struct i2c_rdwr_ioctl_data packets;
struct i2c_msg messages[2];
/*
* In order to read a register, we first do a "dummy write" by writing
* 0 bytes to the register we want to read from. This is similar to
* the packet in set_i2c_register, except it's 1 byte rather than 2.
*/
outbuf = reg;
messages[0].addr = addr;
messages[0].flags = 0;
messages[0].len = sizeof(outbuf);
messages[0].buf = &outbuf;
/* The data will get returned in this structure */
messages[1].addr = addr;
messages[1].flags = I2C_M_RD/* | I2C_M_NOSTART*/;
messages[1].len = sizeof(inbuf);
messages[1].buf = &inbuf;
/* Send the request to the kernel and get the result back */
packets.msgs = messages;
packets.nmsgs = 2;
if(ioctl(i2c->fd, I2C_RDWR, &packets) < 0) {
LOG(LL_ERROR, ("Unable to send data"));
return 1;
}
*val = inbuf;
return 0;
}
// User provided function to interface with Linux I2C driver
bool mgos_i2c_open(int busnr) {
int fd;
@ -220,6 +283,7 @@ bool mgos_i2c_open(int busnr) {
}
i2c->fd=fd;
i2c->filename=strdup(filename);
i2c->read_timeout_ms=1000;
s_global_i2c_bus=i2c;
LOG(LL_INFO, ("Opened I2C bus on %s", filename));