1.底层接口新增返回值,增加超时判断。2.完善i2c机制,为软件i2c增加ack支持。
This commit is contained in:
@@ -44,6 +44,15 @@ menu "Driver configure"
|
||||
config MR_USING_SPI1
|
||||
bool "Enable SPI1 driver"
|
||||
default n
|
||||
|
||||
menu "SPI1 driver configure"
|
||||
depends on MR_USING_SPI1
|
||||
|
||||
config MR_CFG_SPI1_GROUP
|
||||
int "SPI1 Group"
|
||||
default 1
|
||||
range 1 2
|
||||
endmenu
|
||||
endmenu
|
||||
|
||||
menu "Timer"
|
||||
|
||||
@@ -93,7 +93,11 @@ static ssize_t mr_adc_read(struct mr_dev *dev, void *buf, size_t count)
|
||||
|
||||
for (rd_size = 0; rd_size < MR_ALIGN_DOWN(count, sizeof(*rd_buf)); rd_size += sizeof(*rd_buf))
|
||||
{
|
||||
*rd_buf = ops->read(adc, dev->position);
|
||||
int ret = ops->read(adc, dev->position, rd_buf);
|
||||
if (ret < 0)
|
||||
{
|
||||
return (rd_size == 0) ? ret : rd_size;
|
||||
}
|
||||
rd_buf++;
|
||||
}
|
||||
return rd_size;
|
||||
|
||||
@@ -93,7 +93,11 @@ static ssize_t mr_dac_write(struct mr_dev *dev, const void *buf, size_t count)
|
||||
|
||||
for (wr_size = 0; wr_size < MR_ALIGN_DOWN(count, sizeof(*wr_buf)); wr_size += sizeof(*wr_buf))
|
||||
{
|
||||
ops->write(dac, dev->position, *wr_buf);
|
||||
int ret = ops->write(dac, dev->position, *wr_buf);
|
||||
if (ret < 0)
|
||||
{
|
||||
return (wr_size == 0) ? ret : wr_size;
|
||||
}
|
||||
wr_buf++;
|
||||
}
|
||||
return wr_size;
|
||||
|
||||
@@ -84,8 +84,10 @@ int _mr_fast_pin_mode(int number, int mode)
|
||||
uint8_t _mr_fast_pin_read(int number)
|
||||
{
|
||||
struct mr_dev *dev = *_fast_pin_dev_get(MR_MAGIC_NUMBER);
|
||||
uint8_t value = 0;
|
||||
|
||||
return ((struct mr_pin_ops *)dev->drv->ops)->read((struct mr_pin *)dev, number);
|
||||
((struct mr_pin_ops *)dev->drv->ops)->read((struct mr_pin *)dev, number, &value);
|
||||
return value;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
78
device/i2c.c
78
device/i2c.c
@@ -51,9 +51,14 @@ static ssize_t mr_i2c_bus_isr(struct mr_dev *dev, int event, void *args)
|
||||
case MR_ISR_I2C_RD_INT:
|
||||
{
|
||||
struct mr_i2c_dev *i2c_dev = (struct mr_i2c_dev *)i2c_bus->owner;
|
||||
uint8_t data = ops->read(i2c_bus, MR_ENABLE);
|
||||
uint8_t data;
|
||||
|
||||
/* Read data to FIFO */
|
||||
int ret = ops->read(i2c_bus, &data, MR_ENABLE);
|
||||
if (ret < 0)
|
||||
{
|
||||
return ret;
|
||||
}
|
||||
mr_ringbuf_push_force(&i2c_dev->rd_fifo, data);
|
||||
|
||||
return (ssize_t)mr_ringbuf_get_data_size(&i2c_dev->rd_fifo);
|
||||
@@ -152,7 +157,7 @@ MR_INLINE int i2c_dev_release_bus(struct mr_i2c_dev *i2c_dev)
|
||||
#define MR_I2C_RD (0)
|
||||
#define MR_I2C_WR (1)
|
||||
|
||||
MR_INLINE void i2c_dev_send_addr(struct mr_i2c_dev *i2c_dev, int rdwr)
|
||||
MR_INLINE int i2c_dev_send_addr(struct mr_i2c_dev *i2c_dev, int rdwr)
|
||||
{
|
||||
struct mr_i2c_bus *i2c_bus = (struct mr_i2c_bus *)i2c_dev->dev.parent;
|
||||
struct mr_i2c_bus_ops *ops = (struct mr_i2c_bus_ops *)i2c_bus->dev.drv->ops;
|
||||
@@ -163,13 +168,19 @@ MR_INLINE void i2c_dev_send_addr(struct mr_i2c_dev *i2c_dev, int rdwr)
|
||||
addr_bits = i2c_dev->addr_bits;
|
||||
|
||||
/* Set the read command */
|
||||
addr = (0xf000 | ((addr >> 8) & 0x03) << 9) | (addr & 0xff);
|
||||
if (rdwr == MR_I2C_RD)
|
||||
{
|
||||
addr |= 0x01;
|
||||
addr |= (addr_bits == MR_I2C_ADDR_BITS_7) ? 0x01 : 0x10;
|
||||
}
|
||||
|
||||
ops->start(i2c_bus);
|
||||
ops->send_addr(i2c_bus, addr, addr_bits);
|
||||
int ret = ops->send_addr(i2c_bus, addr, addr_bits);
|
||||
if (ret < 0)
|
||||
{
|
||||
ops->stop(i2c_bus);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
MR_INLINE void i2c_dev_send_stop(struct mr_i2c_dev *i2c_dev)
|
||||
@@ -189,7 +200,13 @@ MR_INLINE ssize_t i2c_dev_read(struct mr_i2c_dev *i2c_dev, uint8_t *buf, size_t
|
||||
|
||||
for (rd_size = 0; rd_size < count; rd_size += sizeof(*rd_buf))
|
||||
{
|
||||
*rd_buf = ops->read(i2c_bus, (count - rd_size) == sizeof(*rd_buf));
|
||||
int ack = ((count - rd_size) == sizeof(*rd_buf));
|
||||
|
||||
int ret = ops->read(i2c_bus, rd_buf, ack);
|
||||
if (ret < 0)
|
||||
{
|
||||
return (rd_size == 0) ? ret : rd_size;
|
||||
}
|
||||
rd_buf++;
|
||||
}
|
||||
return rd_size;
|
||||
@@ -204,7 +221,11 @@ MR_INLINE ssize_t i2c_dev_write(struct mr_i2c_dev *i2c_dev, const uint8_t *buf,
|
||||
|
||||
for (wr_size = 0; wr_size < count; wr_size += sizeof(*wr_buf))
|
||||
{
|
||||
ops->write(i2c_bus, *wr_buf);
|
||||
int ret = ops->write(i2c_bus, *wr_buf);
|
||||
if (ret < 0)
|
||||
{
|
||||
return (wr_size == 0) ? ret : wr_size;
|
||||
}
|
||||
wr_buf++;
|
||||
}
|
||||
return wr_size;
|
||||
@@ -240,24 +261,32 @@ static ssize_t mr_i2c_dev_read(struct mr_dev *dev, void *buf, size_t count)
|
||||
/* Send the address of the register that needs to be read */
|
||||
if (dev->position >= 0)
|
||||
{
|
||||
i2c_dev_send_addr(i2c_dev, MR_I2C_WR);
|
||||
i2c_dev_write(i2c_dev, (uint8_t *)&dev->position, (i2c_dev->config.reg_bits >> 3));
|
||||
ret = i2c_dev_send_addr(i2c_dev, MR_I2C_WR);
|
||||
if (ret < 0)
|
||||
{
|
||||
goto release_bus;
|
||||
}
|
||||
|
||||
ret = i2c_dev_write(i2c_dev, (uint8_t *)&dev->position, (i2c_dev->config.reg_bits >> 3));
|
||||
if (ret < 0)
|
||||
{
|
||||
goto release_bus;
|
||||
}
|
||||
}
|
||||
|
||||
i2c_dev_send_addr(i2c_dev, MR_I2C_RD);
|
||||
ret = i2c_dev_send_addr(i2c_dev, MR_I2C_RD);
|
||||
if (ret < 0)
|
||||
{
|
||||
goto release_bus;
|
||||
}
|
||||
ret = i2c_dev_read(i2c_dev, (uint8_t *)buf, count);
|
||||
i2c_dev_send_stop(i2c_dev);
|
||||
} else
|
||||
{
|
||||
if (mr_ringbuf_get_bufsz(&i2c_dev->rd_fifo) == 0)
|
||||
{
|
||||
ret = i2c_dev_read(i2c_dev, (uint8_t *)buf, count);
|
||||
} else
|
||||
{
|
||||
ret = (ssize_t)mr_ringbuf_read(&i2c_dev->rd_fifo, buf, count);
|
||||
}
|
||||
ret = (ssize_t)mr_ringbuf_read(&i2c_dev->rd_fifo, buf, count);
|
||||
}
|
||||
|
||||
release_bus:
|
||||
i2c_dev_release_bus(i2c_dev);
|
||||
return ret;
|
||||
}
|
||||
@@ -274,12 +303,20 @@ static ssize_t mr_i2c_dev_write(struct mr_dev *dev, const void *buf, size_t coun
|
||||
|
||||
if (i2c_dev->config.host_slave == MR_I2C_HOST)
|
||||
{
|
||||
i2c_dev_send_addr(i2c_dev, MR_I2C_WR);
|
||||
ret = i2c_dev_send_addr(i2c_dev, MR_I2C_WR);
|
||||
if (ret < 0)
|
||||
{
|
||||
goto release_bus;
|
||||
}
|
||||
|
||||
/* Send the address of the register that needs to be written */
|
||||
if (dev->position >= 0)
|
||||
{
|
||||
i2c_dev_write(i2c_dev, (uint8_t *)&dev->position, (i2c_dev->config.reg_bits >> 3));
|
||||
ret = i2c_dev_write(i2c_dev, (uint8_t *)&dev->position, (i2c_dev->config.reg_bits >> 3));
|
||||
if (ret < 0)
|
||||
{
|
||||
goto release_bus;
|
||||
}
|
||||
}
|
||||
|
||||
ret = i2c_dev_write(i2c_dev, (uint8_t *)buf, count);
|
||||
@@ -289,6 +326,7 @@ static ssize_t mr_i2c_dev_write(struct mr_dev *dev, const void *buf, size_t coun
|
||||
ret = i2c_dev_write(i2c_dev, (uint8_t *)buf, count);
|
||||
}
|
||||
|
||||
release_bus:
|
||||
i2c_dev_release_bus(i2c_dev);
|
||||
return ret;
|
||||
}
|
||||
@@ -414,6 +452,8 @@ int mr_i2c_dev_register(struct mr_i2c_dev *i2c_dev, const char *path, int addr,
|
||||
MR_ASSERT(i2c_dev != MR_NULL);
|
||||
MR_ASSERT(path != MR_NULL);
|
||||
MR_ASSERT((addr_bits == MR_I2C_ADDR_BITS_7) || (addr_bits == MR_I2C_ADDR_BITS_10));
|
||||
MR_ASSERT((addr_bits != MR_I2C_ADDR_BITS_7) || (addr >= 0x00 && addr <= 0x7f));
|
||||
MR_ASSERT((addr_bits != MR_I2C_ADDR_BITS_10) || (addr >= 0x00 && addr <= 0x3ff));
|
||||
|
||||
/* Initialize the fields */
|
||||
i2c_dev->config = default_config;
|
||||
@@ -422,7 +462,7 @@ int mr_i2c_dev_register(struct mr_i2c_dev *i2c_dev, const char *path, int addr,
|
||||
#define MR_CFG_I2C_RD_BUFSZ (0)
|
||||
#endif /* MR_CFG_I2C_RD_BUFSZ */
|
||||
i2c_dev->rd_bufsz = MR_CFG_I2C_RD_BUFSZ;
|
||||
i2c_dev->addr = (addr_bits == MR_I2C_ADDR_BITS_7) ? addr : ((0xf0 | ((addr >> 7) & 0x06)) << 8) | (addr & 0xff);
|
||||
i2c_dev->addr = addr;
|
||||
i2c_dev->addr_bits = addr_bits;
|
||||
|
||||
/* Register the i2c-device */
|
||||
|
||||
12
device/pin.c
12
device/pin.c
@@ -41,7 +41,11 @@ static ssize_t mr_pin_read(struct mr_dev *dev, void *buf, size_t count)
|
||||
|
||||
for (rd_size = 0; rd_size < count; rd_size += sizeof(*rd_buf))
|
||||
{
|
||||
*rd_buf = (uint8_t)ops->read(pin, dev->position);
|
||||
int ret = (uint8_t)ops->read(pin, dev->position, rd_buf);
|
||||
if (ret < 0)
|
||||
{
|
||||
return (rd_size == 0) ? ret : rd_size;
|
||||
}
|
||||
rd_buf++;
|
||||
}
|
||||
return rd_size;
|
||||
@@ -64,7 +68,11 @@ static ssize_t mr_pin_write(struct mr_dev *dev, const void *buf, size_t count)
|
||||
|
||||
for (wr_size = 0; wr_size < count; wr_size += sizeof(*wr_buf))
|
||||
{
|
||||
ops->write(pin, dev->position, *wr_buf);
|
||||
int ret = ops->write(pin, dev->position, *wr_buf);
|
||||
if (ret < 0)
|
||||
{
|
||||
return (wr_size == 0) ? ret : wr_size;
|
||||
}
|
||||
wr_buf++;
|
||||
}
|
||||
return wr_size;
|
||||
|
||||
22
device/pwm.c
22
device/pwm.c
@@ -157,8 +157,14 @@ static ssize_t mr_pwm_read(struct mr_dev *dev, void *buf, size_t count)
|
||||
|
||||
for (rd_size = 0; rd_size < MR_ALIGN_DOWN(count, sizeof(*rd_buf)); rd_size += sizeof(*rd_buf))
|
||||
{
|
||||
uint32_t compare_value;
|
||||
|
||||
/* Calculate the duty */
|
||||
uint32_t compare_value = ops->read(pwm, dev->position);
|
||||
int ret = ops->read(pwm, dev->position, &compare_value);
|
||||
if (ret < 0)
|
||||
{
|
||||
return (rd_size == 0) ? ret : rd_size;
|
||||
}
|
||||
*rd_buf = (uint32_t)(((float)compare_value / (float)pwm->period) * 1000000.0f);
|
||||
rd_buf++;
|
||||
}
|
||||
@@ -186,7 +192,11 @@ static ssize_t mr_pwm_write(struct mr_dev *dev, const void *buf, size_t count)
|
||||
uint32_t compare_value = MR_BOUND((uint32_t)(((float)*wr_buf / 1000000.0f) * (float)(pwm->period)),
|
||||
0,
|
||||
pwm->period);
|
||||
ops->write(pwm, dev->position, compare_value);
|
||||
int ret = ops->write(pwm, dev->position, compare_value);
|
||||
if (ret < 0)
|
||||
{
|
||||
return (wr_size == 0) ? ret : wr_size;
|
||||
}
|
||||
wr_buf++;
|
||||
}
|
||||
return wr_size;
|
||||
@@ -236,8 +246,14 @@ static int mr_pwm_ioctl(struct mr_dev *dev, int cmd, void *args)
|
||||
{
|
||||
if (MR_BIT_IS_SET(pwm->channel, (1 << i)) == MR_ENABLE)
|
||||
{
|
||||
uint32_t compare_value;
|
||||
|
||||
/* Get old duty */
|
||||
uint32_t compare_value = ops->read(pwm, (int)i);
|
||||
ret = ops->read(pwm, (int)i, &compare_value);
|
||||
if (ret < 0)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Calculate new compare value */
|
||||
compare_value = (uint32_t)(((float)compare_value / (float)old_period) * (float)(pwm->period));
|
||||
|
||||
@@ -52,7 +52,11 @@ static ssize_t mr_serial_read(struct mr_dev *dev, void *buf, size_t count)
|
||||
{
|
||||
for (rd_size = 0; rd_size < count; rd_size += sizeof(*rd_buf))
|
||||
{
|
||||
*rd_buf = ops->read(serial);
|
||||
int ret = ops->read(serial, rd_buf);
|
||||
if (ret < 0)
|
||||
{
|
||||
return (rd_size == 0) ? ret : rd_size;
|
||||
}
|
||||
rd_buf++;
|
||||
}
|
||||
} else
|
||||
@@ -73,7 +77,11 @@ static ssize_t mr_serial_write(struct mr_dev *dev, const void *buf, size_t count
|
||||
{
|
||||
for (wr_size = 0; wr_size < count; wr_size += sizeof(*wr_buf))
|
||||
{
|
||||
ops->write(serial, *wr_buf);
|
||||
int ret = ops->write(serial, *wr_buf);
|
||||
if (ret < 0)
|
||||
{
|
||||
return (wr_size == 0) ? ret : wr_size;
|
||||
}
|
||||
wr_buf++;
|
||||
}
|
||||
} else
|
||||
@@ -226,16 +234,23 @@ static ssize_t mr_serial_isr(struct mr_dev *dev, int event, void *args)
|
||||
{
|
||||
case MR_ISR_SERIAL_RD_INT:
|
||||
{
|
||||
uint8_t data;
|
||||
|
||||
/* Read data to FIFO */
|
||||
uint8_t data = ops->read(serial);
|
||||
int ret = ops->read(serial, &data);
|
||||
if (ret < 0)
|
||||
{
|
||||
return ret;
|
||||
}
|
||||
mr_ringbuf_push_force(&serial->rd_fifo, data);
|
||||
|
||||
return (ssize_t)mr_ringbuf_get_data_size(&serial->rd_fifo);
|
||||
}
|
||||
case MR_ISR_SERIAL_WR_INT:
|
||||
{
|
||||
/* Write data from FIFO, if FIFO is empty, stop transmit */
|
||||
uint8_t data;
|
||||
|
||||
/* Write data from FIFO, if FIFO is empty, stop transmit */
|
||||
if (mr_ringbuf_pop(&serial->wr_fifo, &data) == sizeof(data))
|
||||
{
|
||||
ops->write(serial, data);
|
||||
|
||||
@@ -37,9 +37,10 @@ MR_INLINE uint8_t soft_i2c_sda_get(struct mr_soft_i2c_bus *soft_i2c_bus)
|
||||
return (uint8_t)_mr_fast_pin_read(soft_i2c_bus->sda_pin);
|
||||
}
|
||||
|
||||
static void soft_i2c_bus_wait_ack(struct mr_i2c_bus *i2c_bus)
|
||||
static int soft_i2c_bus_wait_ack(struct mr_i2c_bus *i2c_bus)
|
||||
{
|
||||
struct mr_soft_i2c_bus *soft_i2c_bus = (struct mr_soft_i2c_bus *)i2c_bus;
|
||||
int ret = MR_ETIMEOUT;
|
||||
|
||||
soft_i2c_scl_set(soft_i2c_bus, SOFT_I2C_LOW);
|
||||
soft_i2c_bus_sda_set(soft_i2c_bus, SOFT_I2C_HIGH);
|
||||
@@ -48,9 +49,13 @@ static void soft_i2c_bus_wait_ack(struct mr_i2c_bus *i2c_bus)
|
||||
soft_i2c_scl_set(soft_i2c_bus, SOFT_I2C_HIGH);
|
||||
mr_delay_us(soft_i2c_bus->delay);
|
||||
|
||||
soft_i2c_sda_get(soft_i2c_bus);
|
||||
if (soft_i2c_sda_get(soft_i2c_bus) == SOFT_I2C_LOW)
|
||||
{
|
||||
ret = MR_EOK;
|
||||
}
|
||||
soft_i2c_scl_set(soft_i2c_bus, SOFT_I2C_LOW);
|
||||
mr_delay_us(soft_i2c_bus->delay);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void soft_i2c_bus_send_ack(struct mr_i2c_bus *i2c_bus, int ack)
|
||||
@@ -58,7 +63,6 @@ static void soft_i2c_bus_send_ack(struct mr_i2c_bus *i2c_bus, int ack)
|
||||
struct mr_soft_i2c_bus *soft_i2c_bus = (struct mr_soft_i2c_bus *)i2c_bus;
|
||||
|
||||
soft_i2c_scl_set(soft_i2c_bus, SOFT_I2C_LOW);
|
||||
mr_delay_us(soft_i2c_bus->delay);
|
||||
if (ack == MR_ENABLE)
|
||||
{
|
||||
soft_i2c_bus_sda_set(soft_i2c_bus, SOFT_I2C_LOW);
|
||||
@@ -67,10 +71,11 @@ static void soft_i2c_bus_send_ack(struct mr_i2c_bus *i2c_bus, int ack)
|
||||
soft_i2c_bus_sda_set(soft_i2c_bus, SOFT_I2C_HIGH);
|
||||
}
|
||||
|
||||
mr_delay_us(soft_i2c_bus->delay);
|
||||
soft_i2c_scl_set(soft_i2c_bus, SOFT_I2C_HIGH);
|
||||
mr_delay_us(soft_i2c_bus->delay);
|
||||
soft_i2c_scl_set(soft_i2c_bus, SOFT_I2C_LOW);
|
||||
mr_delay_us(soft_i2c_bus->delay);
|
||||
soft_i2c_bus_sda_set(soft_i2c_bus, SOFT_I2C_HIGH);
|
||||
}
|
||||
|
||||
static int mr_soft_i2c_bus_configure(struct mr_i2c_bus *i2c_bus, struct mr_i2c_config *config, int addr, int addr_bits)
|
||||
@@ -118,15 +123,25 @@ static void mr_soft_i2c_bus_start(struct mr_i2c_bus *i2c_bus)
|
||||
soft_i2c_scl_set(soft_i2c_bus, SOFT_I2C_LOW);
|
||||
}
|
||||
|
||||
static void mr_soft_i2c_bus_write(struct mr_i2c_bus *i2c_bus, uint8_t data);
|
||||
static int mr_soft_i2c_bus_write(struct mr_i2c_bus *i2c_bus, uint8_t data);
|
||||
|
||||
static void mr_soft_i2c_bus_send_addr(struct mr_i2c_bus *i2c_bus, int addr, int addr_bits)
|
||||
static int mr_soft_i2c_bus_send_addr(struct mr_i2c_bus *i2c_bus, int addr, int addr_bits)
|
||||
{
|
||||
mr_soft_i2c_bus_write(i2c_bus, addr);
|
||||
if (addr_bits == MR_I2C_ADDR_BITS_10)
|
||||
{
|
||||
mr_soft_i2c_bus_write(i2c_bus, (addr >> 8));
|
||||
int ret = mr_soft_i2c_bus_write(i2c_bus, addr >> 8);
|
||||
if (ret < 0)
|
||||
{
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
int ret = mr_soft_i2c_bus_write(i2c_bus, addr);
|
||||
if (ret < 0)
|
||||
{
|
||||
return ret;
|
||||
}
|
||||
return MR_EOK;
|
||||
}
|
||||
|
||||
static void mr_soft_i2c_bus_stop(struct mr_i2c_bus *i2c_bus)
|
||||
@@ -140,50 +155,43 @@ static void mr_soft_i2c_bus_stop(struct mr_i2c_bus *i2c_bus)
|
||||
soft_i2c_scl_set(soft_i2c_bus, SOFT_I2C_HIGH);
|
||||
mr_delay_us(soft_i2c_bus->delay);
|
||||
soft_i2c_bus_sda_set(soft_i2c_bus, SOFT_I2C_HIGH);
|
||||
mr_delay_us(soft_i2c_bus->delay);
|
||||
}
|
||||
|
||||
static uint8_t mr_soft_i2c_bus_read(struct mr_i2c_bus *i2c_bus, int ack_state)
|
||||
static int mr_soft_i2c_bus_read(struct mr_i2c_bus *i2c_bus, uint8_t *data, int ack_state)
|
||||
{
|
||||
struct mr_soft_i2c_bus *soft_i2c_bus = (struct mr_soft_i2c_bus *)i2c_bus;
|
||||
uint8_t data = 0;
|
||||
|
||||
soft_i2c_scl_set(soft_i2c_bus, SOFT_I2C_LOW);
|
||||
mr_delay_us(soft_i2c_bus->delay);
|
||||
soft_i2c_bus_sda_set(soft_i2c_bus, SOFT_I2C_HIGH);
|
||||
|
||||
for (size_t bits = 0; bits < 8; bits++)
|
||||
for (size_t bits = 0; bits < (sizeof(*data) * 8); bits++)
|
||||
{
|
||||
mr_delay_us(soft_i2c_bus->delay);
|
||||
soft_i2c_scl_set(soft_i2c_bus, SOFT_I2C_LOW);
|
||||
mr_delay_us(soft_i2c_bus->delay);
|
||||
soft_i2c_scl_set(soft_i2c_bus, SOFT_I2C_HIGH);
|
||||
mr_delay_us(soft_i2c_bus->delay);
|
||||
data <<= 1;
|
||||
*data <<= 1;
|
||||
if (soft_i2c_sda_get(soft_i2c_bus) == SOFT_I2C_HIGH)
|
||||
{
|
||||
data |= 0x01;
|
||||
*data |= 0x01;
|
||||
}
|
||||
}
|
||||
|
||||
soft_i2c_scl_set(soft_i2c_bus, SOFT_I2C_LOW);
|
||||
mr_delay_us(soft_i2c_bus->delay);
|
||||
soft_i2c_bus_send_ack(i2c_bus, ack_state);
|
||||
return data;
|
||||
return MR_EOK;
|
||||
}
|
||||
|
||||
static void mr_soft_i2c_bus_write(struct mr_i2c_bus *i2c_bus, uint8_t data)
|
||||
static int mr_soft_i2c_bus_write(struct mr_i2c_bus *i2c_bus, uint8_t data)
|
||||
{
|
||||
struct mr_soft_i2c_bus *soft_i2c_bus = (struct mr_soft_i2c_bus *)i2c_bus;
|
||||
|
||||
for (size_t bits = 0; bits < 8; bits++)
|
||||
{
|
||||
if (data & 0x80)
|
||||
{
|
||||
soft_i2c_bus_sda_set(soft_i2c_bus, SOFT_I2C_HIGH);
|
||||
} else
|
||||
{
|
||||
soft_i2c_bus_sda_set(soft_i2c_bus, SOFT_I2C_LOW);
|
||||
}
|
||||
soft_i2c_bus_sda_set(soft_i2c_bus, (data & 0x80) ? SOFT_I2C_HIGH : SOFT_I2C_LOW);
|
||||
data <<= 1;
|
||||
|
||||
mr_delay_us(soft_i2c_bus->delay);
|
||||
@@ -191,7 +199,7 @@ static void mr_soft_i2c_bus_write(struct mr_i2c_bus *i2c_bus, uint8_t data)
|
||||
mr_delay_us(soft_i2c_bus->delay);
|
||||
soft_i2c_scl_set(soft_i2c_bus, SOFT_I2C_LOW);
|
||||
}
|
||||
soft_i2c_bus_wait_ack(i2c_bus);
|
||||
return soft_i2c_bus_wait_ack(i2c_bus);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
181
device/spi.c
181
device/spi.c
@@ -65,11 +65,17 @@ static ssize_t mr_spi_bus_isr(struct mr_dev *dev, int event, void *args)
|
||||
case MR_ISR_SPI_RD_INT:
|
||||
{
|
||||
struct mr_spi_dev *spi_dev = (struct mr_spi_dev *)spi_bus->owner;
|
||||
uint32_t data = ops->read(spi_bus);
|
||||
uint8_t data;
|
||||
|
||||
/* Read data to FIFO. if callback is set, call it */
|
||||
mr_ringbuf_write_force(&spi_dev->rd_fifo, &data, (spi_bus->config.data_bits >> 3));
|
||||
return MR_EOK;
|
||||
/* Read data to FIFO */
|
||||
int ret = ops->read(spi_bus, &data);
|
||||
if (ret < 0)
|
||||
{
|
||||
return ret;
|
||||
}
|
||||
mr_ringbuf_write_force(&spi_dev->rd_fifo, &data, sizeof(data));
|
||||
|
||||
return (ssize_t)mr_ringbuf_get_data_size(&spi_dev->rd_fifo);;
|
||||
}
|
||||
default:
|
||||
{
|
||||
@@ -186,7 +192,6 @@ MR_INLINE int spi_dev_take_bus(struct mr_spi_dev *spi_dev)
|
||||
if (spi_dev->config.baud_rate != spi_bus->config.baud_rate
|
||||
|| spi_dev->config.host_slave != spi_bus->config.host_slave
|
||||
|| spi_dev->config.mode != spi_bus->config.mode
|
||||
|| spi_dev->config.data_bits != spi_bus->config.data_bits
|
||||
|| spi_dev->config.bit_order != spi_bus->config.bit_order)
|
||||
{
|
||||
int ret = ops->configure(spi_bus, &spi_dev->config);
|
||||
@@ -229,143 +234,57 @@ MR_INLINE int spi_dev_release_bus(struct mr_spi_dev *spi_dev)
|
||||
#define MR_SPI_WR (1)
|
||||
#define MR_SPI_RDWR (2)
|
||||
|
||||
static ssize_t spi_dev_transfer(struct mr_spi_dev *spi_dev, void *rd_buf, const void *wr_buf, size_t size, int rdwr)
|
||||
static ssize_t spi_dev_transfer(struct mr_spi_dev *spi_dev,
|
||||
uint8_t *rd_buf,
|
||||
const uint8_t *wr_buf,
|
||||
size_t size,
|
||||
int rdwr)
|
||||
{
|
||||
struct mr_spi_bus *spi_bus = (struct mr_spi_bus *)spi_dev->dev.parent;
|
||||
struct mr_spi_bus_ops *ops = (struct mr_spi_bus_ops *)spi_bus->dev.drv->ops;
|
||||
size_t tf_size;
|
||||
ssize_t tf_size;
|
||||
|
||||
if (rdwr == MR_SPI_RD)
|
||||
{
|
||||
switch (spi_dev->config.data_bits)
|
||||
for (tf_size = 0; tf_size < size; tf_size += sizeof(*rd_buf))
|
||||
{
|
||||
case MR_SPI_DATA_BITS_8:
|
||||
ops->write(spi_bus, 0);
|
||||
int ret = ops->read(spi_bus, rd_buf);
|
||||
if (ret < 0)
|
||||
{
|
||||
uint8_t *rd_data = (uint8_t *)rd_buf;
|
||||
for (tf_size = 0; tf_size < MR_ALIGN_DOWN(size, sizeof(*rd_data)); tf_size += sizeof(*rd_data))
|
||||
{
|
||||
ops->write(spi_bus, 0);
|
||||
*rd_data = ops->read(spi_bus);
|
||||
rd_data++;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case MR_SPI_DATA_BITS_16:
|
||||
{
|
||||
uint16_t *rd_data = (uint16_t *)rd_buf;
|
||||
for (tf_size = 0; tf_size < MR_ALIGN_DOWN(size, sizeof(*rd_data)); tf_size += sizeof(*rd_data))
|
||||
{
|
||||
ops->write(spi_bus, 0);
|
||||
*rd_data = ops->read(spi_bus);
|
||||
rd_data++;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case MR_SPI_DATA_BITS_32:
|
||||
{
|
||||
uint32_t *rd_data = (uint32_t *)rd_buf;
|
||||
for (tf_size = 0; tf_size < MR_ALIGN_DOWN(size, sizeof(*rd_data)); tf_size += sizeof(*rd_data))
|
||||
{
|
||||
ops->write(spi_bus, 0);
|
||||
*rd_data = ops->read(spi_bus);
|
||||
rd_data++;
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
return MR_EINVAL;
|
||||
return (tf_size == 0) ? ret : tf_size;
|
||||
}
|
||||
rd_buf++;
|
||||
}
|
||||
} else if (rdwr == MR_SPI_WR)
|
||||
{
|
||||
switch (spi_dev->config.data_bits)
|
||||
for (tf_size = 0; tf_size < size; tf_size += sizeof(*wr_buf))
|
||||
{
|
||||
case MR_SPI_DATA_BITS_8:
|
||||
int ret = ops->write(spi_bus, *wr_buf);
|
||||
if (ret < 0)
|
||||
{
|
||||
uint8_t *wr_data = (uint8_t *)wr_buf;
|
||||
for (tf_size = 0; tf_size < MR_ALIGN_DOWN(size, sizeof(*wr_data)); tf_size += sizeof(*wr_data))
|
||||
{
|
||||
ops->write(spi_bus, *wr_data);
|
||||
ops->read(spi_bus);
|
||||
wr_data++;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case MR_SPI_DATA_BITS_16:
|
||||
{
|
||||
uint16_t *wr_data = (uint16_t *)wr_buf;
|
||||
for (tf_size = 0; tf_size < MR_ALIGN_DOWN(size, sizeof(*wr_data)); tf_size += sizeof(*wr_data))
|
||||
{
|
||||
ops->write(spi_bus, *wr_data);
|
||||
ops->read(spi_bus);
|
||||
wr_data++;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case MR_SPI_DATA_BITS_32:
|
||||
{
|
||||
uint32_t *wr_data = (uint32_t *)wr_buf;
|
||||
for (tf_size = 0; tf_size < MR_ALIGN_DOWN(size, sizeof(*wr_data)); tf_size += sizeof(*wr_data))
|
||||
{
|
||||
ops->write(spi_bus, *wr_data);
|
||||
ops->read(spi_bus);
|
||||
wr_data++;
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
return MR_EINVAL;
|
||||
return (tf_size == 0) ? ret : tf_size;
|
||||
}
|
||||
ops->read(spi_bus, MR_MAKE_LOCAL(uint8_t, 0));
|
||||
wr_buf++;
|
||||
}
|
||||
} else
|
||||
{
|
||||
switch (spi_dev->config.data_bits)
|
||||
for (tf_size = 0; tf_size < MR_ALIGN_DOWN(size, sizeof(*wr_buf)); tf_size += sizeof(*wr_buf))
|
||||
{
|
||||
case MR_SPI_DATA_BITS_8:
|
||||
int ret = ops->write(spi_bus, *wr_buf);
|
||||
if (ret < 0)
|
||||
{
|
||||
uint8_t *rd_data = (uint8_t *)rd_buf;
|
||||
uint8_t *wr_data = (uint8_t *)wr_buf;
|
||||
for (tf_size = 0; tf_size < MR_ALIGN_DOWN(size, sizeof(*wr_data)); tf_size += sizeof(*wr_data))
|
||||
{
|
||||
ops->write(spi_bus, *wr_data);
|
||||
*rd_data = ops->read(spi_bus);
|
||||
rd_data++;
|
||||
wr_data++;
|
||||
}
|
||||
break;
|
||||
return (tf_size == 0) ? ret : tf_size;
|
||||
}
|
||||
case MR_SPI_DATA_BITS_16:
|
||||
|
||||
ret = ops->read(spi_bus, rd_buf);
|
||||
if (ret < 0)
|
||||
{
|
||||
uint16_t *wr_data = (uint16_t *)wr_buf;
|
||||
uint16_t *rd_data = (uint16_t *)rd_buf;
|
||||
for (tf_size = 0; tf_size < MR_ALIGN_DOWN(size, sizeof(*wr_data)); tf_size += sizeof(*wr_data))
|
||||
{
|
||||
ops->write(spi_bus, *wr_data);
|
||||
*rd_data = ops->read(spi_bus);
|
||||
rd_data++;
|
||||
wr_data++;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case MR_SPI_DATA_BITS_32:
|
||||
{
|
||||
uint32_t *wr_data = (uint32_t *)wr_buf;
|
||||
uint32_t *rd_data = (uint32_t *)rd_buf;
|
||||
for (tf_size = 0; tf_size < MR_ALIGN_DOWN(size, sizeof(*wr_data)); tf_size += sizeof(*wr_data))
|
||||
{
|
||||
ops->write(spi_bus, *wr_data);
|
||||
*rd_data = ops->read(spi_bus);
|
||||
rd_data++;
|
||||
wr_data++;
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
return MR_EINVAL;
|
||||
return (tf_size == 0) ? ret : tf_size;
|
||||
}
|
||||
rd_buf++;
|
||||
wr_buf++;
|
||||
}
|
||||
}
|
||||
return (ssize_t)tf_size;
|
||||
@@ -413,7 +332,17 @@ static ssize_t mr_spi_dev_read(struct mr_dev *dev, void *buf, size_t count)
|
||||
/* Send the address of the register that needs to be read */
|
||||
if (dev->position >= 0)
|
||||
{
|
||||
spi_dev_transfer(spi_dev, MR_NULL, &dev->position, (spi_dev->config.reg_bits >> 3), MR_SPI_WR);
|
||||
ret = spi_dev_transfer(spi_dev,
|
||||
MR_NULL,
|
||||
(uint8_t *)&dev->position,
|
||||
(spi_dev->config.reg_bits >> 3),
|
||||
MR_SPI_WR);
|
||||
if (ret < 0)
|
||||
{
|
||||
spi_dev_cs_set(spi_dev, MR_DISABLE);
|
||||
spi_dev_release_bus(spi_dev);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
ret = spi_dev_transfer(spi_dev, buf, MR_NULL, count, MR_SPI_RD);
|
||||
@@ -444,7 +373,17 @@ static ssize_t mr_spi_dev_write(struct mr_dev *dev, const void *buf, size_t coun
|
||||
/* Send the address of the register that needs to be written */
|
||||
if (dev->position >= 0)
|
||||
{
|
||||
spi_dev_transfer(spi_dev, MR_NULL, &dev->position, (spi_dev->config.reg_bits >> 3), MR_SPI_WR);
|
||||
ret = spi_dev_transfer(spi_dev,
|
||||
MR_NULL,
|
||||
(uint8_t *)&dev->position,
|
||||
(spi_dev->config.reg_bits >> 3),
|
||||
MR_SPI_WR);
|
||||
if (ret < 0)
|
||||
{
|
||||
spi_dev_cs_set(spi_dev, MR_DISABLE);
|
||||
spi_dev_release_bus(spi_dev);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
ret = spi_dev_transfer(spi_dev, MR_NULL, buf, count, MR_SPI_WR);
|
||||
|
||||
@@ -61,7 +61,7 @@ struct mr_adc_ops
|
||||
{
|
||||
int (*configure)(struct mr_adc *adc, int state);
|
||||
int (*channel_configure)(struct mr_adc *adc, int channel, int state);
|
||||
uint32_t (*read)(struct mr_adc *adc, int channel);
|
||||
int (*read)(struct mr_adc *adc, int channel, uint32_t *data);
|
||||
};
|
||||
|
||||
int mr_adc_register(struct mr_adc *adc, const char *path, struct mr_drv *drv);
|
||||
|
||||
@@ -61,7 +61,7 @@ struct mr_dac_ops
|
||||
{
|
||||
int (*configure)(struct mr_dac *dac, int state);
|
||||
int (*channel_configure)(struct mr_dac *dac, int channel, int state);
|
||||
void (*write)(struct mr_dac *dac, int channel, uint32_t data);
|
||||
int (*write)(struct mr_dac *dac, int channel, uint32_t data);
|
||||
};
|
||||
|
||||
int mr_dac_register(struct mr_dac *dac, const char *path, struct mr_drv *drv);
|
||||
|
||||
@@ -99,10 +99,10 @@ struct mr_i2c_bus_ops
|
||||
{
|
||||
int (*configure)(struct mr_i2c_bus *i2c_bus, struct mr_i2c_config *config, int addr, int addr_bits);
|
||||
void (*start)(struct mr_i2c_bus *i2c_bus);
|
||||
void (*send_addr)(struct mr_i2c_bus *i2c_bus, int addr, int addr_bits);
|
||||
int (*send_addr)(struct mr_i2c_bus *i2c_bus, int addr, int addr_bits);
|
||||
void (*stop)(struct mr_i2c_bus *i2c_bus);
|
||||
uint8_t (*read)(struct mr_i2c_bus *i2c_bus, int ack_state);
|
||||
void (*write)(struct mr_i2c_bus *i2c_bus, uint8_t data);
|
||||
int (*read)(struct mr_i2c_bus *i2c_bus, uint8_t *data, int ack_state);
|
||||
int (*write)(struct mr_i2c_bus *i2c_bus, uint8_t data);
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
@@ -83,8 +83,8 @@ struct mr_pin
|
||||
struct mr_pin_ops
|
||||
{
|
||||
int (*configure)(struct mr_pin *pin, int number, int mode);
|
||||
uint8_t (*read)(struct mr_pin *pin, int number);
|
||||
void (*write)(struct mr_pin *pin, int number, uint8_t value);
|
||||
int (*read)(struct mr_pin *pin, int number, uint8_t *value);
|
||||
int (*write)(struct mr_pin *pin, int number, uint8_t value);
|
||||
};
|
||||
|
||||
int mr_pin_register(struct mr_pin *pin, const char *path, struct mr_drv *drv);
|
||||
|
||||
@@ -87,8 +87,8 @@ struct mr_pwm_ops
|
||||
int (*configure)(struct mr_pwm *pwm, int state);
|
||||
int (*channel_configure)(struct mr_pwm *pwm, int channel, int state, int polarity);
|
||||
void (*start)(struct mr_pwm *pwm, uint32_t prescaler, uint32_t period);
|
||||
void (*write)(struct mr_pwm *pwm, int channel, uint32_t compare_value);
|
||||
uint32_t (*read)(struct mr_pwm *pwm, int channel);
|
||||
int (*read)(struct mr_pwm *pwm, int channel, uint32_t *compare_value);
|
||||
int (*write)(struct mr_pwm *pwm, int channel, uint32_t compare_value);
|
||||
};
|
||||
|
||||
int mr_pwm_register(struct mr_pwm *pwm, const char *path, struct mr_drv *drv, struct mr_pwm_info *info);
|
||||
|
||||
@@ -112,6 +112,7 @@ typedef uint8_t mr_serial_data_t; /**< Serial
|
||||
*/
|
||||
#define MR_ISR_SERIAL_RD_INT (MR_ISR_RD | (0x01)) /**< Read interrupt */
|
||||
#define MR_ISR_SERIAL_WR_INT (MR_ISR_WR | (0x02)) /**< Write interrupt */
|
||||
#define MR_ISR_SERIAL_RD_IDLE (MR_ISR_RD | (0x03)) /**< Read idle */
|
||||
|
||||
/**
|
||||
* @brief Serial structure.
|
||||
@@ -133,8 +134,8 @@ struct mr_serial
|
||||
struct mr_serial_ops
|
||||
{
|
||||
int (*configure)(struct mr_serial *serial, struct mr_serial_config *config);
|
||||
uint8_t (*read)(struct mr_serial *serial);
|
||||
void (*write)(struct mr_serial *serial, uint8_t data);
|
||||
int (*read)(struct mr_serial *serial, uint8_t *data);
|
||||
int (*write)(struct mr_serial *serial, uint8_t data);
|
||||
void (*start_tx)(struct mr_serial *serial);
|
||||
void (*stop_tx)(struct mr_serial *serial);
|
||||
};
|
||||
|
||||
@@ -36,13 +36,6 @@ extern "C" {
|
||||
#define MR_SPI_MODE_2 (2) /**< CPOL = 1, CPHA = 0 */
|
||||
#define MR_SPI_MODE_3 (3) /**< CPOL = 1, CPHA = 1 */
|
||||
|
||||
/**
|
||||
* @brief SPI data bits.
|
||||
*/
|
||||
#define MR_SPI_DATA_BITS_8 (8) /**< 8 bits data */
|
||||
#define MR_SPI_DATA_BITS_16 (16) /**< 16 bits data */
|
||||
#define MR_SPI_DATA_BITS_32 (32) /**< 32 bits data */
|
||||
|
||||
/**
|
||||
* @brief SPI bit order.
|
||||
*/
|
||||
@@ -64,7 +57,6 @@ extern "C" {
|
||||
3000000, \
|
||||
MR_SPI_HOST, \
|
||||
MR_SPI_MODE_0, \
|
||||
MR_SPI_DATA_BITS_8, \
|
||||
MR_SPI_BIT_ORDER_MSB, \
|
||||
MR_SPI_REG_BITS_8, \
|
||||
}
|
||||
@@ -77,7 +69,6 @@ struct mr_spi_config
|
||||
uint32_t baud_rate; /**< Baud rate */
|
||||
int host_slave; /**< Host/slave */
|
||||
int mode; /**< Mode */
|
||||
int data_bits; /**< Data bits */
|
||||
int bit_order; /**< Bit order */
|
||||
int reg_bits; /**< Register bits */
|
||||
};
|
||||
@@ -137,8 +128,8 @@ struct mr_spi_bus
|
||||
struct mr_spi_bus_ops
|
||||
{
|
||||
int (*configure)(struct mr_spi_bus *spi_bus, struct mr_spi_config *config);
|
||||
uint32_t (*read)(struct mr_spi_bus *spi_bus);
|
||||
void (*write)(struct mr_spi_bus *spi_bus, uint32_t data);
|
||||
int (*read)(struct mr_spi_bus *spi_bus, uint8_t *data);
|
||||
int (*write)(struct mr_spi_bus *spi_bus, uint8_t data);
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
@@ -115,6 +115,7 @@ typedef void (*mr_init_fn_t)(void); /**< Auto in
|
||||
#define MR_EEXIST (-5) /**< Exists */
|
||||
#define MR_ENOTSUP (-6) /**< Operation not supported */
|
||||
#define MR_EINVAL (-7) /**< Invalid argument */
|
||||
#define MR_ETIMEOUT (-8) /**< Timeout */
|
||||
/** @} */
|
||||
|
||||
/**
|
||||
|
||||
@@ -170,6 +170,8 @@ const char *mr_strerror(int err)
|
||||
return "operation not supported";
|
||||
case MR_EINVAL:
|
||||
return "invalid argument";
|
||||
case MR_ETIMEOUT:
|
||||
return "timeout";
|
||||
default:
|
||||
return "unknown error";
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user