Skip to content

Commit 78d3f2a

Browse files
mimokfabiobaltieri
authored andcommitted
stm32,i2c: Fix large I2C transactions on I2C V1
Previous commit added support of large transactions on I2C v2, this commit implements some changes to also add support of large transactions on I2C v1. Some refactoring is also done to put the code in the right source files. Fixes #58866 Signed-off-by: Michael Grand <[email protected]>
1 parent a8b28f1 commit 78d3f2a

File tree

4 files changed

+75
-65
lines changed

4 files changed

+75
-65
lines changed

drivers/i2c/i2c_ll_stm32.c

Lines changed: 1 addition & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -93,56 +93,6 @@ int i2c_stm32_runtime_configure(const struct device *dev, uint32_t config)
9393
return ret;
9494
}
9595

96-
static inline int
97-
i2c_stm32_transaction(const struct device *dev,
98-
struct i2c_msg msg, uint8_t *next_msg_flags,
99-
uint16_t periph)
100-
{
101-
/*
102-
* Perform a I2C transaction, while taking into account the STM32 I2C
103-
* peripheral has a limited maximum chunk size. Take appropriate action
104-
* if the message to send exceeds that limit.
105-
*
106-
* The last chunk of a transmission uses this function's next_msg_flags
107-
* parameter for its backend calls (_write/_read). Any previous chunks
108-
* use a copy of the current message's flags, with the STOP and RESTART
109-
* bits turned off. This will cause the backend to use reload-mode,
110-
* which will make the combination of all chunks to look like one big
111-
* transaction on the wire.
112-
*/
113-
const uint32_t i2c_stm32_maxchunk = 255U;
114-
const uint8_t saved_flags = msg.flags;
115-
uint8_t combine_flags =
116-
saved_flags & ~(I2C_MSG_STOP | I2C_MSG_RESTART);
117-
uint8_t *flagsp = NULL;
118-
uint32_t rest = msg.len;
119-
int ret = 0;
120-
121-
do { /* do ... while to allow zero-length transactions */
122-
if (msg.len > i2c_stm32_maxchunk) {
123-
msg.len = i2c_stm32_maxchunk;
124-
msg.flags &= ~I2C_MSG_STOP;
125-
flagsp = &combine_flags;
126-
} else {
127-
msg.flags = saved_flags;
128-
flagsp = next_msg_flags;
129-
}
130-
if ((msg.flags & I2C_MSG_RW_MASK) == I2C_MSG_WRITE) {
131-
ret = stm32_i2c_msg_write(dev, &msg, flagsp, periph);
132-
} else {
133-
ret = stm32_i2c_msg_read(dev, &msg, flagsp, periph);
134-
}
135-
if (ret < 0) {
136-
break;
137-
}
138-
rest -= msg.len;
139-
msg.buf += msg.len;
140-
msg.len = rest;
141-
} while (rest > 0U);
142-
143-
return ret;
144-
}
145-
14696
#define OPERATION(msg) (((struct i2c_msg *) msg)->flags & I2C_MSG_RW_MASK)
14797

14898
static int i2c_stm32_transfer(const struct device *dev, struct i2c_msg *msg,
@@ -220,7 +170,7 @@ static int i2c_stm32_transfer(const struct device *dev, struct i2c_msg *msg,
220170
next = current + 1;
221171
next_msg_flags = &(next->flags);
222172
}
223-
ret = i2c_stm32_transaction(dev, *current, next_msg_flags, slave);
173+
ret = stm32_i2c_transaction(dev, *current, next_msg_flags, slave);
224174
if (ret < 0) {
225175
break;
226176
}

drivers/i2c/i2c_ll_stm32.h

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -80,12 +80,9 @@ struct i2c_stm32_data {
8080
#endif
8181
};
8282

83-
int32_t stm32_i2c_msg_write(const struct device *dev, struct i2c_msg *msg,
84-
uint8_t *flg,
85-
uint16_t sadr);
86-
int32_t stm32_i2c_msg_read(const struct device *dev, struct i2c_msg *msg,
87-
uint8_t *flg,
88-
uint16_t sadr);
83+
int32_t stm32_i2c_transaction(const struct device *dev,
84+
struct i2c_msg msg, uint8_t *next_msg_flags,
85+
uint16_t periph);
8986
int32_t stm32_i2c_configure_timing(const struct device *dev, uint32_t clk);
9087
int i2c_stm32_runtime_configure(const struct device *dev, uint32_t config);
9188

drivers/i2c/i2c_ll_stm32_v1.c

Lines changed: 18 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -613,7 +613,7 @@ void stm32_i2c_error_isr(void *arg)
613613
stm32_i2c_master_mode_end(dev);
614614
}
615615

616-
int32_t stm32_i2c_msg_write(const struct device *dev, struct i2c_msg *msg,
616+
static int32_t stm32_i2c_msg_write(const struct device *dev, struct i2c_msg *msg,
617617
uint8_t *next_msg_flags, uint16_t saddr)
618618
{
619619
struct i2c_stm32_data *data = dev->data;
@@ -632,7 +632,7 @@ int32_t stm32_i2c_msg_write(const struct device *dev, struct i2c_msg *msg,
632632
return msg_end(dev, next_msg_flags, __func__);
633633
}
634634

635-
int32_t stm32_i2c_msg_read(const struct device *dev, struct i2c_msg *msg,
635+
static int32_t stm32_i2c_msg_read(const struct device *dev, struct i2c_msg *msg,
636636
uint8_t *next_msg_flags, uint16_t saddr)
637637
{
638638
const struct i2c_stm32_config *cfg = dev->config;
@@ -706,7 +706,7 @@ static int stm32_i2c_wait_timeout(uint16_t *timeout)
706706
}
707707
}
708708

709-
int32_t stm32_i2c_msg_write(const struct device *dev, struct i2c_msg *msg,
709+
static int32_t stm32_i2c_msg_write(const struct device *dev, struct i2c_msg *msg,
710710
uint8_t *next_msg_flags, uint16_t saddr)
711711
{
712712
const struct i2c_stm32_config *cfg = dev->config;
@@ -804,7 +804,7 @@ int32_t stm32_i2c_msg_write(const struct device *dev, struct i2c_msg *msg,
804804
return res;
805805
}
806806

807-
int32_t stm32_i2c_msg_read(const struct device *dev, struct i2c_msg *msg,
807+
static int32_t stm32_i2c_msg_read(const struct device *dev, struct i2c_msg *msg,
808808
uint8_t *next_msg_flags, uint16_t saddr)
809809
{
810810
const struct i2c_stm32_config *cfg = dev->config;
@@ -986,3 +986,17 @@ int32_t stm32_i2c_configure_timing(const struct device *dev, uint32_t clock)
986986

987987
return 0;
988988
}
989+
990+
int stm32_i2c_transaction(const struct device *dev,
991+
struct i2c_msg msg, uint8_t *next_msg_flags,
992+
uint16_t periph)
993+
{
994+
int ret;
995+
996+
if ((msg.flags & I2C_MSG_RW_MASK) == I2C_MSG_WRITE) {
997+
ret = stm32_i2c_msg_write(dev, &msg, next_msg_flags, periph);
998+
} else {
999+
ret = stm32_i2c_msg_read(dev, &msg, next_msg_flags, periph);
1000+
}
1001+
return ret;
1002+
}

drivers/i2c/i2c_ll_stm32_v2.c

Lines changed: 53 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -427,7 +427,7 @@ void stm32_i2c_error_isr(void *arg)
427427
}
428428
#endif
429429

430-
int stm32_i2c_msg_write(const struct device *dev, struct i2c_msg *msg,
430+
static int stm32_i2c_msg_write(const struct device *dev, struct i2c_msg *msg,
431431
uint8_t *next_msg_flags, uint16_t slave)
432432
{
433433
const struct i2c_stm32_config *cfg = dev->config;
@@ -485,7 +485,7 @@ int stm32_i2c_msg_write(const struct device *dev, struct i2c_msg *msg,
485485
return -EIO;
486486
}
487487

488-
int stm32_i2c_msg_read(const struct device *dev, struct i2c_msg *msg,
488+
static int stm32_i2c_msg_read(const struct device *dev, struct i2c_msg *msg,
489489
uint8_t *next_msg_flags, uint16_t slave)
490490
{
491491
const struct i2c_stm32_config *cfg = dev->config;
@@ -607,7 +607,7 @@ static inline int msg_done(const struct device *dev,
607607
return 0;
608608
}
609609

610-
int stm32_i2c_msg_write(const struct device *dev, struct i2c_msg *msg,
610+
static int stm32_i2c_msg_write(const struct device *dev, struct i2c_msg *msg,
611611
uint8_t *next_msg_flags, uint16_t slave)
612612
{
613613
const struct i2c_stm32_config *cfg = dev->config;
@@ -637,7 +637,7 @@ int stm32_i2c_msg_write(const struct device *dev, struct i2c_msg *msg,
637637
return msg_done(dev, msg->flags);
638638
}
639639

640-
int stm32_i2c_msg_read(const struct device *dev, struct i2c_msg *msg,
640+
static int stm32_i2c_msg_read(const struct device *dev, struct i2c_msg *msg,
641641
uint8_t *next_msg_flags, uint16_t slave)
642642
{
643643
const struct i2c_stm32_config *cfg = dev->config;
@@ -738,3 +738,52 @@ int stm32_i2c_configure_timing(const struct device *dev, uint32_t clock)
738738

739739
return 0;
740740
}
741+
742+
int stm32_i2c_transaction(const struct device *dev,
743+
struct i2c_msg msg, uint8_t *next_msg_flags,
744+
uint16_t periph)
745+
{
746+
/*
747+
* Perform a I2C transaction, while taking into account the STM32 I2C V2
748+
* peripheral has a limited maximum chunk size. Take appropriate action
749+
* if the message to send exceeds that limit.
750+
*
751+
* The last chunk of a transmission uses this function's next_msg_flags
752+
* parameter for its backend calls (_write/_read). Any previous chunks
753+
* use a copy of the current message's flags, with the STOP and RESTART
754+
* bits turned off. This will cause the backend to use reload-mode,
755+
* which will make the combination of all chunks to look like one big
756+
* transaction on the wire.
757+
*/
758+
const uint32_t i2c_stm32_maxchunk = 255U;
759+
const uint8_t saved_flags = msg.flags;
760+
uint8_t combine_flags =
761+
saved_flags & ~(I2C_MSG_STOP | I2C_MSG_RESTART);
762+
uint8_t *flagsp = NULL;
763+
uint32_t rest = msg.len;
764+
int ret = 0;
765+
766+
do { /* do ... while to allow zero-length transactions */
767+
if (msg.len > i2c_stm32_maxchunk) {
768+
msg.len = i2c_stm32_maxchunk;
769+
msg.flags &= ~I2C_MSG_STOP;
770+
flagsp = &combine_flags;
771+
} else {
772+
msg.flags = saved_flags;
773+
flagsp = next_msg_flags;
774+
}
775+
if ((msg.flags & I2C_MSG_RW_MASK) == I2C_MSG_WRITE) {
776+
ret = stm32_i2c_msg_write(dev, &msg, flagsp, periph);
777+
} else {
778+
ret = stm32_i2c_msg_read(dev, &msg, flagsp, periph);
779+
}
780+
if (ret < 0) {
781+
break;
782+
}
783+
rest -= msg.len;
784+
msg.buf += msg.len;
785+
msg.len = rest;
786+
} while (rest > 0U);
787+
788+
return ret;
789+
}

0 commit comments

Comments
 (0)