Skip to content

Commit

Permalink
drivers: i2c_ll_stm32: Use I2C API flags
Browse files Browse the repository at this point in the history
STM32 I2C driver doesn't use the I2C API flags STOP/RESTART,
instead it uses its own RESTART flag. As a result, I2C API's
i2c_burst_write* funtions doesn't work. This patch makes
STM32 I2C driver to use I2C API flags.

Tested on: 96b_carbon, olimexino_stm32 (i2c_ll_stm32_v1)
Tested on: stm32f3_disco, disco_l475_iot1 (i2c_ll_stm32_v2)

Fixes: #4459

Signed-off-by: Yannis Damigos <[email protected]>
Signed-off-by: Daniel Wagenknecht <[email protected]>
  • Loading branch information
ydamigos authored and galak committed Nov 9, 2017
1 parent 3a5ca91 commit aa5853c
Show file tree
Hide file tree
Showing 4 changed files with 166 additions and 111 deletions.
39 changes: 31 additions & 8 deletions drivers/i2c/i2c_ll_stm32.c
Original file line number Diff line number Diff line change
Expand Up @@ -61,24 +61,47 @@ static int i2c_stm32_transfer(struct device *dev, struct i2c_msg *msg,
LL_I2C_Enable(i2c);

current = msg;
/*
* Set I2C_MSG_RESTART flag on first message in order to send start
* condition
*/
current->flags |= I2C_MSG_RESTART;
while (num_msgs > 0) {
unsigned int flags = 0;

if (current->len > 255)
return -EINVAL;
u8_t *next_msg_flags = NULL;

/* do NOT issue the i2c stop condition at the end of transfer */
if (num_msgs > 1) {
next = current + 1;
next_msg_flags = &(next->flags);

/*
* Stop or restart condition between messages
* of different directions is required
*/
if (OPERATION(current) != OPERATION(next)) {
flags = I2C_MSG_RESTART;
if (!(next->flags & I2C_MSG_RESTART)) {
ret = -EINVAL;
break;
}
}
}

if (current->len > 255) {
ret = -EINVAL;
break;
}

/* Stop condition is required for the last message */
if ((num_msgs == 1) && !(current->flags & I2C_MSG_STOP)) {
ret = -EINVAL;
break;
}

if ((current->flags & I2C_MSG_RW_MASK) == I2C_MSG_WRITE) {
ret = stm32_i2c_msg_write(dev, current, flags, slave);
ret = stm32_i2c_msg_write(dev, current, next_msg_flags,
slave);
} else {
ret = stm32_i2c_msg_read(dev, current, flags, slave);
ret = stm32_i2c_msg_read(dev, current, next_msg_flags,
slave);
}

if (ret < 0) {
Expand Down
4 changes: 2 additions & 2 deletions drivers/i2c/i2c_ll_stm32.h
Original file line number Diff line number Diff line change
Expand Up @@ -42,9 +42,9 @@ struct i2c_stm32_data {
} current;
};

s32_t stm32_i2c_msg_write(struct device *dev, struct i2c_msg *msg, u32_t flg,
s32_t stm32_i2c_msg_write(struct device *dev, struct i2c_msg *msg, u8_t *flg,
u16_t sadr);
s32_t stm32_i2c_msg_read(struct device *dev, struct i2c_msg *msg, u32_t flg,
s32_t stm32_i2c_msg_read(struct device *dev, struct i2c_msg *msg, u8_t *flg,
u16_t sadr);
s32_t stm32_i2c_configure_timing(struct device *dev, u32_t clk);

Expand Down
152 changes: 87 additions & 65 deletions drivers/i2c/i2c_ll_stm32_v1.c
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ static inline void handle_txe(I2C_TypeDef *i2c, struct i2c_stm32_data *data)
LL_I2C_TransmitData8(i2c, *data->current.buf);
data->current.buf++;
} else {
if ((data->current.flags & I2C_MSG_RESTART) == 0) {
if (data->current.flags & I2C_MSG_STOP) {
LL_I2C_GenerateStopCondition(i2c);
}
if (LL_I2C_IsActiveFlag_BTF(i2c)) {
Expand All @@ -107,7 +107,7 @@ static inline void handle_rxne(I2C_TypeDef *i2c, struct i2c_stm32_data *data)
switch (data->current.len) {
case 1:
/* Single byte reception */
if ((data->current.flags & I2C_MSG_RESTART) == 0) {
if (data->current.flags & I2C_MSG_STOP) {
LL_I2C_GenerateStopCondition(i2c);
}
LL_I2C_DisableIT_BUF(i2c);
Expand Down Expand Up @@ -146,7 +146,7 @@ static inline void handle_btf(I2C_TypeDef *i2c, struct i2c_stm32_data *data)
* Stop condition must be generated before reading the
* last two bytes.
*/
if ((data->current.flags & I2C_MSG_RESTART) == 0) {
if (data->current.flags & I2C_MSG_STOP) {
LL_I2C_GenerateStopCondition(i2c);
}

Expand Down Expand Up @@ -209,16 +209,18 @@ void stm32_i2c_error_isr(void *arg)
}

s32_t stm32_i2c_msg_write(struct device *dev, struct i2c_msg *msg,
u32_t flags, u16_t saddr)
u8_t *next_msg_flags, u16_t saddr)
{
const struct i2c_stm32_config *cfg = DEV_CFG(dev);
struct i2c_stm32_data *data = DEV_DATA(dev);
I2C_TypeDef *i2c = cfg->i2c;
s32_t ret = 0;

ARG_UNUSED(next_msg_flags);

data->current.len = msg->len;
data->current.buf = msg->buf;
data->current.flags = flags;
data->current.flags = msg->flags;
data->current.is_restart = 0;
data->current.is_write = 1;
data->current.is_nack = 0;
Expand All @@ -228,7 +230,9 @@ s32_t stm32_i2c_msg_write(struct device *dev, struct i2c_msg *msg,
LL_I2C_EnableIT_EVT(i2c);
LL_I2C_EnableIT_ERR(i2c);
LL_I2C_AcknowledgeNextData(i2c, LL_I2C_ACK);
LL_I2C_GenerateStartCondition(i2c);
if (msg->flags & I2C_MSG_RESTART) {
LL_I2C_GenerateStartCondition(i2c);
}
LL_I2C_EnableIT_BUF(i2c);

k_sem_take(&data->device_sync_sem, K_FOREVER);
Expand All @@ -255,16 +259,18 @@ s32_t stm32_i2c_msg_write(struct device *dev, struct i2c_msg *msg,
}

s32_t stm32_i2c_msg_read(struct device *dev, struct i2c_msg *msg,
u32_t flags, u16_t saddr)
u8_t *next_msg_flags, u16_t saddr)
{
const struct i2c_stm32_config *cfg = DEV_CFG(dev);
struct i2c_stm32_data *data = DEV_DATA(dev);
I2C_TypeDef *i2c = cfg->i2c;
s32_t ret = 0;

ARG_UNUSED(next_msg_flags);

data->current.len = msg->len;
data->current.buf = msg->buf;
data->current.flags = flags;
data->current.flags = msg->flags;
data->current.is_restart = 0;
data->current.is_write = 0;
data->current.is_err = 0;
Expand Down Expand Up @@ -294,39 +300,45 @@ s32_t stm32_i2c_msg_read(struct device *dev, struct i2c_msg *msg,
#else

s32_t stm32_i2c_msg_write(struct device *dev, struct i2c_msg *msg,
u32_t flags, u16_t saddr)
u8_t *next_msg_flags, u16_t saddr)
{
const struct i2c_stm32_config *cfg = DEV_CFG(dev);
struct i2c_stm32_data *data = DEV_DATA(dev);
I2C_TypeDef *i2c = cfg->i2c;
u32_t len = msg->len;
u8_t *buf = msg->buf;

LL_I2C_AcknowledgeNextData(i2c, LL_I2C_ACK);
LL_I2C_GenerateStartCondition(i2c);
while (!LL_I2C_IsActiveFlag_SB(i2c)) {
;
}
ARG_UNUSED(next_msg_flags);

if (I2C_ADDR_10_BITS & data->dev_config) {
u8_t slave = (((saddr & 0x0300) >> 7) & 0xFF);
u8_t header = slave | HEADER;
LL_I2C_AcknowledgeNextData(i2c, LL_I2C_ACK);

LL_I2C_TransmitData8(i2c, header);
while (!LL_I2C_IsActiveFlag_ADD10(i2c)) {
if (msg->flags & I2C_MSG_RESTART) {
LL_I2C_GenerateStartCondition(i2c);
while (!LL_I2C_IsActiveFlag_SB(i2c)) {
;
}
slave = data->slave_address & 0xFF;
LL_I2C_TransmitData8(i2c, slave);
} else {
u8_t slave = (saddr << 1) & 0xFF;

LL_I2C_TransmitData8(i2c, slave | I2C_REQUEST_WRITE);
}
while (!LL_I2C_IsActiveFlag_ADDR(i2c)) {
;
if (I2C_ADDR_10_BITS & data->dev_config) {
u8_t slave = (((saddr & 0x0300) >> 7) & 0xFF);
u8_t header = slave | HEADER;

LL_I2C_TransmitData8(i2c, header);
while (!LL_I2C_IsActiveFlag_ADD10(i2c)) {
;
}
slave = data->slave_address & 0xFF;
LL_I2C_TransmitData8(i2c, slave);
} else {
u8_t slave = (saddr << 1) & 0xFF;

LL_I2C_TransmitData8(i2c, slave | I2C_REQUEST_WRITE);
}
while (!LL_I2C_IsActiveFlag_ADDR(i2c)) {
;
}
LL_I2C_ClearFlag_ADDR(i2c);
}
LL_I2C_ClearFlag_ADDR(i2c);

while (len) {
while (1) {
if (LL_I2C_IsActiveFlag_TXE(i2c)) {
Expand All @@ -343,76 +355,86 @@ s32_t stm32_i2c_msg_write(struct device *dev, struct i2c_msg *msg,
buf++;
len--;
}

while (!LL_I2C_IsActiveFlag_BTF(i2c)) {
;
}
if ((flags & I2C_MSG_RESTART) == 0) {

if (msg->flags & I2C_MSG_STOP) {
LL_I2C_GenerateStopCondition(i2c);
}

return 0;
}

s32_t stm32_i2c_msg_read(struct device *dev, struct i2c_msg *msg,
u32_t flags, u16_t saddr)
u8_t *next_msg_flags, u16_t saddr)
{
const struct i2c_stm32_config *cfg = DEV_CFG(dev);
struct i2c_stm32_data *data = DEV_DATA(dev);
I2C_TypeDef *i2c = cfg->i2c;
u32_t len = msg->len;
u8_t *buf = msg->buf;

LL_I2C_AcknowledgeNextData(i2c, LL_I2C_ACK);
LL_I2C_GenerateStartCondition(i2c);
while (!LL_I2C_IsActiveFlag_SB(i2c)) {
;
}
ARG_UNUSED(next_msg_flags);

if (I2C_ADDR_10_BITS & data->dev_config) {
u8_t slave = (((saddr & 0x0300) >> 7) & 0xFF);
u8_t header = slave | HEADER;
LL_I2C_AcknowledgeNextData(i2c, LL_I2C_ACK);

LL_I2C_TransmitData8(i2c, header);
while (!LL_I2C_IsActiveFlag_ADD10(i2c)) {
if (msg->flags & I2C_MSG_RESTART) {
LL_I2C_GenerateStartCondition(i2c);
while (!LL_I2C_IsActiveFlag_SB(i2c)) {
;
}
slave = saddr & 0xFF;
LL_I2C_TransmitData8(i2c, slave);

if (I2C_ADDR_10_BITS & data->dev_config) {
u8_t slave = (((saddr & 0x0300) >> 7) & 0xFF);
u8_t header = slave | HEADER;

LL_I2C_TransmitData8(i2c, header);
while (!LL_I2C_IsActiveFlag_ADD10(i2c)) {
;
}
slave = saddr & 0xFF;
LL_I2C_TransmitData8(i2c, slave);
while (!LL_I2C_IsActiveFlag_ADDR(i2c)) {
;
}
LL_I2C_ClearFlag_ADDR(i2c);
LL_I2C_GenerateStartCondition(i2c);
while (!LL_I2C_IsActiveFlag_SB(i2c)) {
;
}
header |= I2C_REQUEST_READ;
LL_I2C_TransmitData8(i2c, header);
} else {
u8_t slave = ((saddr) << 1) & 0xFF;

LL_I2C_TransmitData8(i2c, slave | I2C_REQUEST_READ);
}

while (!LL_I2C_IsActiveFlag_ADDR(i2c)) {
;
}
LL_I2C_ClearFlag_ADDR(i2c);
LL_I2C_GenerateStartCondition(i2c);
while (!LL_I2C_IsActiveFlag_SB(i2c)) {
;

if (len == 1) {
/* Single byte reception: enable NACK and set STOP */
LL_I2C_AcknowledgeNextData(i2c, LL_I2C_NACK);
} else if (len == 2) {
/* 2-byte reception: enable NACK and set POS */
LL_I2C_AcknowledgeNextData(i2c, LL_I2C_NACK);
LL_I2C_EnableBitPOS(i2c);
}
header |= I2C_REQUEST_READ;
LL_I2C_TransmitData8(i2c, header);
} else {
u8_t slave = ((saddr) << 1) & 0xFF;

LL_I2C_TransmitData8(i2c, slave | I2C_REQUEST_READ);
LL_I2C_ClearFlag_ADDR(i2c);
}

while (!LL_I2C_IsActiveFlag_ADDR(i2c)) {
;
}
if (len == 1) {
/* Single byte reception: enable NACK and set STOP */
LL_I2C_AcknowledgeNextData(i2c, LL_I2C_NACK);
} else if (len == 2) {
/* 2-byte reception: enable NACK and set POS */
LL_I2C_AcknowledgeNextData(i2c, LL_I2C_NACK);
LL_I2C_EnableBitPOS(i2c);
}
LL_I2C_ClearFlag_ADDR(i2c);
while (len) {
while (!LL_I2C_IsActiveFlag_RXNE(i2c)) {
;
}
switch (len) {
case 1:
if ((flags & I2C_MSG_RESTART) == 0) {
if (msg->flags & I2C_MSG_STOP) {
LL_I2C_GenerateStopCondition(i2c);
}
len--;
Expand All @@ -427,7 +449,7 @@ s32_t stm32_i2c_msg_read(struct device *dev, struct i2c_msg *msg,
* Stop condition must be generated before reading the
* last two bytes.
*/
if ((data->current.flags & I2C_MSG_RESTART) == 0) {
if (msg->flags & I2C_MSG_STOP) {
LL_I2C_GenerateStopCondition(i2c);
}

Expand Down
Loading

0 comments on commit aa5853c

Please sign in to comment.