Skip to content

Commit f9cfcfc

Browse files
committed
drivers: i2c_stm32_v2: DMA fixup
Adapt DMA implementation to match changes introduced by new interrupt handler Signed-off-by: Erik Andersson <erian747@gmail.com>
1 parent a3df1a6 commit f9cfcfc

File tree

1 file changed

+105
-90
lines changed

1 file changed

+105
-90
lines changed

drivers/i2c/i2c_ll_stm32_v2.c

Lines changed: 105 additions & 90 deletions
Original file line numberDiff line numberDiff line change
@@ -150,92 +150,80 @@ static int configure_dma(struct stream const *dma, struct dma_config *dma_cfg,
150150

151151
return 0;
152152
}
153-
#endif /* CONFIG_I2C_STM32_V2_DMA */
154153

155-
static inline void msg_init(const struct device *dev, struct i2c_msg *msg,
156-
uint8_t *next_msg_flags, uint16_t slave,
157-
uint32_t transfer)
154+
static inline void dma_xfer_start(const struct device *dev, struct i2c_msg *msg)
158155
{
159156
const struct i2c_stm32_config *cfg = dev->config;
160157
struct i2c_stm32_data *data = dev->data;
161158
I2C_TypeDef *i2c = cfg->i2c;
162159

163-
if (LL_I2C_IsEnabledReloadMode(i2c)) {
164-
LL_I2C_SetTransferSize(i2c, msg->len);
160+
if (msg->flags & I2C_MSG_READ) {
161+
/* Configure RX DMA */
162+
data->dma_blk_cfg.source_address = LL_I2C_DMA_GetRegAddr(
163+
cfg->i2c, LL_I2C_DMA_REG_DATA_RECEIVE);
164+
data->dma_blk_cfg.source_addr_adj = DMA_ADDR_ADJ_NO_CHANGE;
165+
data->dma_blk_cfg.dest_address = (uint32_t)msg->buf;
166+
data->dma_blk_cfg.dest_addr_adj = DMA_ADDR_ADJ_INCREMENT;
167+
data->dma_blk_cfg.block_size = msg->len;
168+
169+
if (configure_dma(&cfg->rx_dma, &data->dma_rx_cfg,
170+
&data->dma_blk_cfg) != 0) {
171+
LOG_ERR("Problem setting up RX DMA");
172+
return;
173+
}
174+
data->current.buf += msg->len;
175+
data->current.len -= msg->len;
176+
LL_I2C_EnableDMAReq_RX(i2c);
165177
} else {
166-
if (I2C_ADDR_10_BITS & data->dev_config) {
167-
LL_I2C_SetMasterAddressingMode(i2c,
168-
LL_I2C_ADDRESSING_MODE_10BIT);
169-
LL_I2C_SetSlaveAddr(i2c, (uint32_t) slave);
170-
} else {
171-
LL_I2C_SetMasterAddressingMode(i2c,
172-
LL_I2C_ADDRESSING_MODE_7BIT);
173-
LL_I2C_SetSlaveAddr(i2c, (uint32_t) slave << 1);
178+
if (data->current.len) {
179+
/* Configure TX DMA */
180+
data->dma_blk_cfg.source_address =
181+
(uint32_t)data->current.buf;
182+
data->dma_blk_cfg.source_addr_adj = DMA_ADDR_ADJ_INCREMENT;
183+
data->dma_blk_cfg.dest_address = LL_I2C_DMA_GetRegAddr(
184+
cfg->i2c, LL_I2C_DMA_REG_DATA_TRANSMIT);
185+
data->dma_blk_cfg.dest_addr_adj = DMA_ADDR_ADJ_NO_CHANGE;
186+
data->dma_blk_cfg.block_size = msg->len;
187+
188+
if (configure_dma(&cfg->tx_dma, &data->dma_tx_cfg,
189+
&data->dma_blk_cfg) != 0) {
190+
LOG_ERR("Problem setting up TX DMA");
191+
return;
192+
}
193+
data->current.buf += data->current.len;
194+
data->current.len -= data->current.len;
195+
LL_I2C_EnableDMAReq_TX(i2c);
174196
}
197+
}
175198

176-
if (!(msg->flags & I2C_MSG_STOP) && next_msg_flags &&
177-
!(*next_msg_flags & I2C_MSG_RESTART)) {
178-
LL_I2C_EnableReloadMode(i2c);
179-
} else {
180-
LL_I2C_DisableReloadMode(i2c);
181-
}
182-
LL_I2C_DisableAutoEndMode(i2c);
183-
LL_I2C_SetTransferRequest(i2c, transfer);
184-
LL_I2C_SetTransferSize(i2c, msg->len);
199+
}
185200

186-
#if defined(CONFIG_I2C_TARGET)
187-
data->master_active = true;
188-
#endif
201+
static inline void dma_finish(const struct device *dev, struct i2c_msg *msg)
202+
{
203+
const struct i2c_stm32_config *cfg = dev->config;
204+
struct i2c_stm32_data *data = dev->data;
205+
I2C_TypeDef *i2c = cfg->i2c;
189206

190-
#ifdef CONFIG_I2C_STM32_V2_DMA
191-
if (msg->len) {
192-
if (msg->flags & I2C_MSG_READ) {
193-
/* Configure RX DMA */
194-
data->dma_blk_cfg.source_address = LL_I2C_DMA_GetRegAddr(
195-
cfg->i2c, LL_I2C_DMA_REG_DATA_RECEIVE);
196-
data->dma_blk_cfg.source_addr_adj = DMA_ADDR_ADJ_NO_CHANGE;
197-
data->dma_blk_cfg.dest_address = (uint32_t)msg->buf;
198-
data->dma_blk_cfg.dest_addr_adj = DMA_ADDR_ADJ_INCREMENT;
199-
data->dma_blk_cfg.block_size = msg->len;
200-
201-
if (configure_dma(&cfg->rx_dma, &data->dma_rx_cfg,
202-
&data->dma_blk_cfg) != 0) {
203-
LOG_ERR("Problem setting up RX DMA");
204-
return;
205-
}
206-
data->current.buf += msg->len;
207-
data->current.len -= msg->len;
208-
LL_I2C_EnableDMAReq_RX(i2c);
209-
} else {
210-
if (data->current.len) {
211-
/* Configure TX DMA */
212-
data->dma_blk_cfg.source_address =
213-
(uint32_t)data->current.buf;
214-
data->dma_blk_cfg.source_addr_adj = DMA_ADDR_ADJ_INCREMENT;
215-
data->dma_blk_cfg.dest_address = LL_I2C_DMA_GetRegAddr(
216-
cfg->i2c, LL_I2C_DMA_REG_DATA_TRANSMIT);
217-
data->dma_blk_cfg.dest_addr_adj = DMA_ADDR_ADJ_NO_CHANGE;
218-
data->dma_blk_cfg.block_size = msg->len;
219-
220-
if (configure_dma(&cfg->tx_dma, &data->dma_tx_cfg,
221-
&data->dma_blk_cfg) != 0) {
222-
LOG_ERR("Problem setting up TX DMA");
223-
return;
224-
}
225-
data->current.buf += data->current.len;
226-
data->current.len -= data->current.len;
227-
LL_I2C_EnableDMAReq_TX(i2c);
228-
}
229-
}
207+
/* Stop the DMA */
208+
if (data->current.msg->flags & I2C_MSG_READ) {
209+
dma_stop(cfg->rx_dma.dev_dma, cfg->rx_dma.dma_channel);
210+
LL_I2C_DisableDMAReq_RX(i2c);
211+
#if defined(CONFIG_DCACHE) && defined(CONFIG_I2C_STM32_V2_DMA)
212+
if (!buf_in_nocache((uintptr_t)msg->buf, msg->len) &&
213+
((msg->flags & I2C_MSG_RW_MASK) == I2C_MSG_READ)) {
214+
LOG_DBG("Rx buffer at %p (len %zu) is in cached memory; invalidating cache",
215+
msg->buf, msg->len);
216+
sys_cache_data_invd_range((void *)msg->buf, msg->len);
230217
}
231-
#endif /* CONFIG_I2C_STM32_V2_DMA */
232-
233-
LL_I2C_Enable(i2c);
234-
235-
LL_I2C_GenerateStartCondition(i2c);
218+
#endif /* CONFIG_DCACHE && CONFIG_I2C_STM32_V2_DMA */
219+
} else {
220+
dma_stop(cfg->tx_dma.dev_dma, cfg->tx_dma.dma_channel);
221+
LL_I2C_DisableDMAReq_TX(i2c);
236222
}
237223
}
238224

225+
#endif /* CONFIG_I2C_STM32_V2_DMA */
226+
239227
#ifdef CONFIG_I2C_STM32_INTERRUPT
240228

241229
static void i2c_stm32_disable_transfer_interrupts(const struct device *dev)
@@ -277,17 +265,6 @@ static void i2c_stm32_master_mode_end(const struct device *dev)
277265
LL_I2C_Disable(i2c);
278266
}
279267
#endif
280-
281-
#ifdef CONFIG_I2C_STM32_V2_DMA
282-
if (data->current.msg->flags & I2C_MSG_READ) {
283-
dma_stop(cfg->rx_dma.dev_dma, cfg->rx_dma.dma_channel);
284-
LL_I2C_DisableDMAReq_RX(i2c);
285-
} else {
286-
dma_stop(cfg->tx_dma.dev_dma, cfg->tx_dma.dma_channel);
287-
LL_I2C_DisableDMAReq_TX(i2c);
288-
}
289-
#endif /* CONFIG_I2C_STM32_V2_DMA */
290-
291268
k_sem_give(&data->device_sync_sem);
292269
}
293270

@@ -826,6 +803,7 @@ static int stm32_i2c_irq_xfer(const struct device *dev, struct i2c_msg *msg,
826803
LL_I2C_WriteReg(regs, CR2, cr2);
827804

828805
uint32_t cr1 = LL_I2C_ReadReg(regs, CR1);
806+
829807
/* Set common interrupt enable bits */
830808
cr1 |= I2C_CR1_ERRIE | I2C_CR1_STOPIE | I2C_CR1_TCIE | I2C_CR1_NACKIE;
831809

@@ -845,6 +823,11 @@ static int stm32_i2c_irq_xfer(const struct device *dev, struct i2c_msg *msg,
845823
if (k_sem_take(&data->device_sync_sem, K_MSEC(msg->len + 10)) != 0) {
846824
is_timeout = true;
847825
}
826+
827+
#ifdef CONFIG_I2C_STM32_V2_DMA
828+
/* Stop DMA and invalidate cache if needed */
829+
dma_finish(dev, msg);
830+
#endif
848831
/* Check for transfer errors or timeout */
849832
if (data->current.is_nack || data->current.is_arlo || is_timeout) {
850833
LL_I2C_Disable(regs);
@@ -864,14 +847,6 @@ static int stm32_i2c_irq_xfer(const struct device *dev, struct i2c_msg *msg,
864847
}
865848
#endif
866849
}
867-
#if defined(CONFIG_DCACHE) && defined(CONFIG_I2C_STM32_V2_DMA)
868-
if (!buf_in_nocache((uintptr_t)msg->buf, msg->len) &&
869-
((msg->flags & I2C_MSG_RW_MASK) == I2C_MSG_READ)) {
870-
LOG_DBG("Rx buffer at %p (len %zu) is in cached memory; invalidating cache",
871-
msg->buf, msg->len);
872-
sys_cache_data_invd_range((void *)msg->buf, msg->len);
873-
}
874-
#endif /* CONFIG_DCACHE && CONFIG_I2C_STM32_V2_DMA */
875850
return 0;
876851
error:
877852
if (data->current.is_arlo) {
@@ -934,6 +909,46 @@ static inline int check_errors(const struct device *dev, const char *funcname)
934909
return -EIO;
935910
}
936911

912+
static inline void msg_init(const struct device *dev, struct i2c_msg *msg,
913+
uint8_t *next_msg_flags, uint16_t slave,
914+
uint32_t transfer)
915+
{
916+
const struct i2c_stm32_config *cfg = dev->config;
917+
struct i2c_stm32_data *data = dev->data;
918+
I2C_TypeDef *i2c = cfg->i2c;
919+
920+
if (LL_I2C_IsEnabledReloadMode(i2c)) {
921+
LL_I2C_SetTransferSize(i2c, msg->len);
922+
} else {
923+
if (I2C_ADDR_10_BITS & data->dev_config) {
924+
LL_I2C_SetMasterAddressingMode(i2c,
925+
LL_I2C_ADDRESSING_MODE_10BIT);
926+
LL_I2C_SetSlaveAddr(i2c, (uint32_t) slave);
927+
} else {
928+
LL_I2C_SetMasterAddressingMode(i2c,
929+
LL_I2C_ADDRESSING_MODE_7BIT);
930+
LL_I2C_SetSlaveAddr(i2c, (uint32_t) slave << 1);
931+
}
932+
933+
if (!(msg->flags & I2C_MSG_STOP) && next_msg_flags &&
934+
!(*next_msg_flags & I2C_MSG_RESTART)) {
935+
LL_I2C_EnableReloadMode(i2c);
936+
} else {
937+
LL_I2C_DisableReloadMode(i2c);
938+
}
939+
LL_I2C_DisableAutoEndMode(i2c);
940+
LL_I2C_SetTransferRequest(i2c, transfer);
941+
LL_I2C_SetTransferSize(i2c, msg->len);
942+
943+
#if defined(CONFIG_I2C_TARGET)
944+
data->master_active = true;
945+
#endif
946+
LL_I2C_Enable(i2c);
947+
948+
LL_I2C_GenerateStartCondition(i2c);
949+
}
950+
}
951+
937952
static inline int msg_done(const struct device *dev,
938953
unsigned int current_msg_flags)
939954
{

0 commit comments

Comments
 (0)