Skip to content

Commit 02a46e7

Browse files
Daniel Wagenknechtgalak
authored andcommitted
drivers: i2c_ll_stm32_v2: don't use while loops in interrupt mode
Waiting for transfer complete and stop condition uses while loops even when interrupt mode is enabled. Implement use of TC, TCR and STOP interrupt for interrupt mode. msg_done is not needed in interrupt mode anymore, so move it to non-interrupt section Tested with stm32f3_disco board. Signed-off-by: Daniel Wagenknecht <[email protected]>
1 parent 5380bc5 commit 02a46e7

File tree

1 file changed

+65
-35
lines changed

1 file changed

+65
-35
lines changed

drivers/i2c/i2c_ll_stm32_v2.c

Lines changed: 65 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -54,56 +54,68 @@ static inline void msg_init(struct device *dev, struct i2c_msg *msg,
5454
}
5555
}
5656

57-
static inline void msg_done(struct device *dev, unsigned int current_msg_flags)
58-
{
59-
const struct i2c_stm32_config *cfg = DEV_CFG(dev);
60-
I2C_TypeDef *i2c = cfg->i2c;
61-
62-
/* Wait for transfer to complete */
63-
while (!LL_I2C_IsActiveFlag_TC(i2c) && !LL_I2C_IsActiveFlag_TCR(i2c)) {
64-
;
65-
}
66-
/* Issue stop condition if necessary */
67-
if (current_msg_flags & I2C_MSG_STOP) {
68-
LL_I2C_GenerateStopCondition(i2c);
69-
while (!LL_I2C_IsActiveFlag_STOP(i2c)) {
70-
;
71-
}
72-
LL_I2C_ClearFlag_STOP(i2c);
73-
LL_I2C_DisableReloadMode(i2c);
74-
}
75-
}
76-
7757
#ifdef CONFIG_I2C_STM32_INTERRUPT
7858
void stm32_i2c_event_isr(void *arg)
7959
{
8060
const struct i2c_stm32_config *cfg = DEV_CFG((struct device *)arg);
8161
struct i2c_stm32_data *data = DEV_DATA((struct device *)arg);
8262
I2C_TypeDef *i2c = cfg->i2c;
8363

84-
if (data->current.is_write) {
85-
if (data->current.len && LL_I2C_IsActiveFlag_TXIS(i2c)) {
64+
if (data->current.len) {
65+
/* Interrupts for sending/receiving next byte */
66+
67+
if (data->current.is_write && LL_I2C_IsActiveFlag_TXIS(i2c)) {
68+
/* Send next byte */
8669
LL_I2C_TransmitData8(i2c, *data->current.buf);
70+
} else if (!(data->current.is_write) &&
71+
LL_I2C_IsActiveFlag_RXNE(i2c)) {
72+
/* Receive next byte */
73+
*data->current.buf = LL_I2C_ReceiveData8(i2c);
8774
} else {
88-
LL_I2C_DisableIT_TX(i2c);
8975
goto error;
9076
}
77+
78+
data->current.buf++;
79+
data->current.len--;
80+
if (!data->current.len) {
81+
LL_I2C_EnableIT_TC(i2c);
82+
}
83+
9184
} else {
92-
if (data->current.len && LL_I2C_IsActiveFlag_RXNE(i2c)) {
93-
*data->current.buf = LL_I2C_ReceiveData8(i2c);
85+
/* Interrupts to process end of message */
86+
87+
if (LL_I2C_IsActiveFlag_TC(i2c) ||
88+
LL_I2C_IsActiveFlag_TCR(i2c)) {
89+
/* Interrupt after last byte of message
90+
* was transferred
91+
*/
92+
LL_I2C_DisableIT_TC(i2c);
93+
94+
/* Issue stop condition if necessary */
95+
if (data->current.msg->flags & I2C_MSG_STOP) {
96+
LL_I2C_GenerateStopCondition(i2c);
97+
LL_I2C_EnableIT_STOP(i2c);
98+
} else {
99+
k_sem_give(&data->device_sync_sem);
100+
}
101+
102+
} else if (LL_I2C_IsActiveFlag_STOP(i2c)) {
103+
/* Interrupt after stop condition was
104+
* successfully issued
105+
*/
106+
LL_I2C_DisableIT_STOP(i2c);
107+
LL_I2C_ClearFlag_STOP(i2c);
108+
LL_I2C_DisableReloadMode(i2c);
109+
k_sem_give(&data->device_sync_sem);
94110
} else {
95-
LL_I2C_DisableIT_RX(i2c);
96111
goto error;
97112
}
98113
}
99114

100-
data->current.buf++;
101-
data->current.len--;
102-
if (!data->current.len) {
103-
k_sem_give(&data->device_sync_sem);
104-
}
105115
return;
106116
error:
117+
LL_I2C_DisableIT_TX(i2c);
118+
LL_I2C_DisableIT_RX(i2c);
107119
data->current.is_err = 1;
108120
k_sem_give(&data->device_sync_sem);
109121
}
@@ -136,6 +148,7 @@ int stm32_i2c_msg_write(struct device *dev, struct i2c_msg *msg,
136148
data->current.is_write = 1;
137149
data->current.is_nack = 0;
138150
data->current.is_err = 0;
151+
data->current.msg = msg;
139152

140153
msg_init(dev, msg, next_msg_flags, slave, LL_I2C_REQUEST_WRITE);
141154
LL_I2C_EnableIT_TX(i2c);
@@ -149,8 +162,6 @@ int stm32_i2c_msg_write(struct device *dev, struct i2c_msg *msg,
149162
goto error;
150163
}
151164

152-
msg_done(dev, msg->flags);
153-
154165
return 0;
155166
error:
156167
if (data->current.is_nack) {
@@ -178,6 +189,7 @@ int stm32_i2c_msg_read(struct device *dev, struct i2c_msg *msg,
178189
data->current.buf = msg->buf;
179190
data->current.is_write = 0;
180191
data->current.is_err = 0;
192+
data->current.msg = msg;
181193

182194
msg_init(dev, msg, next_msg_flags, slave, LL_I2C_REQUEST_READ);
183195
LL_I2C_EnableIT_RX(i2c);
@@ -189,8 +201,6 @@ int stm32_i2c_msg_read(struct device *dev, struct i2c_msg *msg,
189201
goto error;
190202
}
191203

192-
msg_done(dev, msg->flags);
193-
194204
return 0;
195205
error:
196206
SYS_LOG_DBG("%s: ERR %d", __func__, data->current.is_err);
@@ -200,6 +210,26 @@ int stm32_i2c_msg_read(struct device *dev, struct i2c_msg *msg,
200210
}
201211

202212
#else /* !CONFIG_I2C_STM32_INTERRUPT */
213+
static inline void msg_done(struct device *dev, unsigned int current_msg_flags)
214+
{
215+
const struct i2c_stm32_config *cfg = DEV_CFG(dev);
216+
I2C_TypeDef *i2c = cfg->i2c;
217+
218+
/* Wait for transfer to complete */
219+
while (!LL_I2C_IsActiveFlag_TC(i2c) && !LL_I2C_IsActiveFlag_TCR(i2c)) {
220+
;
221+
}
222+
/* Issue stop condition if necessary */
223+
if (current_msg_flags & I2C_MSG_STOP) {
224+
LL_I2C_GenerateStopCondition(i2c);
225+
while (!LL_I2C_IsActiveFlag_STOP(i2c)) {
226+
;
227+
}
228+
LL_I2C_ClearFlag_STOP(i2c);
229+
LL_I2C_DisableReloadMode(i2c);
230+
}
231+
}
232+
203233
int stm32_i2c_msg_write(struct device *dev, struct i2c_msg *msg,
204234
u8_t *next_msg_flags, uint16_t slave)
205235
{

0 commit comments

Comments
 (0)