Skip to content

Commit 26a8b36

Browse files
sgilbert182carlescufi
authored andcommitted
i2c: stm32: Added DMA stop for various i2c comms conditions
Added stop DMA fot transmit complete or other master end conditions Signed-off-by: Simon Gilbert <[email protected]>
1 parent 446a5ec commit 26a8b36

File tree

1 file changed

+91
-0
lines changed

1 file changed

+91
-0
lines changed

drivers/i2c/i2c_ll_stm32_v2.c

Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,36 @@ static struct stm32_i2c_timings_t i2c_valid_timing[STM32_I2C_VALID_TIMING_NBR];
117117
static uint32_t i2c_valid_timing_nbr;
118118
#endif /* CONFIG_I2C_STM32_V2_TIMING */
119119

120+
#ifdef CONFIG_I2C_STM32_V2_DMA
121+
static int configure_dma(struct stream const *dma, struct dma_config *dma_cfg,
122+
struct dma_block_config *blk_cfg)
123+
{
124+
if (!device_is_ready(dma->dev_dma)) {
125+
LOG_ERR("DMA device not ready");
126+
return -ENODEV;
127+
}
128+
129+
dma_cfg->head_block = blk_cfg;
130+
dma_cfg->block_count = 1;
131+
132+
int ret = dma_config(dma->dev_dma, dma->dma_channel, dma_cfg);
133+
134+
if (ret != 0) {
135+
LOG_ERR("Problem setting up DMA: %d", ret);
136+
return ret;
137+
}
138+
139+
ret = dma_start(dma->dev_dma, dma->dma_channel);
140+
141+
if (ret != 0) {
142+
LOG_ERR("Problem starting DMA: %d", ret);
143+
return ret;
144+
}
145+
146+
return 0;
147+
}
148+
#endif /* CONFIG_I2C_STM32_V2_DMA */
149+
120150
static inline void msg_init(const struct device *dev, struct i2c_msg *msg,
121151
uint8_t *next_msg_flags, uint16_t slave,
122152
uint32_t transfer)
@@ -151,6 +181,45 @@ static inline void msg_init(const struct device *dev, struct i2c_msg *msg,
151181
#if defined(CONFIG_I2C_TARGET)
152182
data->master_active = true;
153183
#endif
184+
185+
#ifdef CONFIG_I2C_STM32_V2_DMA
186+
if (msg->len) {
187+
if (msg->flags & I2C_MSG_READ) {
188+
/* Configure RX DMA */
189+
data->dma_blk_cfg.source_address = LL_I2C_DMA_GetRegAddr(
190+
cfg->i2c, LL_I2C_DMA_REG_DATA_RECEIVE);
191+
data->dma_blk_cfg.dest_address = (uint32_t)msg->buf;
192+
data->dma_blk_cfg.block_size = msg->len;
193+
194+
if (configure_dma(&cfg->rx_dma, &data->dma_cfg,
195+
&data->dma_blk_cfg) != 0) {
196+
LOG_ERR("Problem setting up RX DMA");
197+
return;
198+
}
199+
data->current.buf += msg->len;
200+
data->current.len -= msg->len;
201+
LL_I2C_EnableDMAReq_RX(i2c);
202+
} else {
203+
if (data->current.len) {
204+
/* Configure TX DMA */
205+
data->dma_blk_cfg.source_address =
206+
(uint32_t)data->current.buf;
207+
data->dma_blk_cfg.dest_address = LL_I2C_DMA_GetRegAddr(
208+
cfg->i2c, LL_I2C_DMA_REG_DATA_TRANSMIT);
209+
data->dma_blk_cfg.block_size = msg->len;
210+
if (configure_dma(&cfg->tx_dma, &data->dma_cfg,
211+
&data->dma_blk_cfg) != 0) {
212+
LOG_ERR("Problem setting up TX DMA");
213+
return;
214+
}
215+
data->current.buf += data->current.len;
216+
data->current.len -= data->current.len;
217+
LL_I2C_EnableDMAReq_TX(i2c);
218+
}
219+
}
220+
}
221+
#endif /* CONFIG_I2C_STM32_V2_DMA */
222+
154223
LL_I2C_Enable(i2c);
155224

156225
LL_I2C_GenerateStartCondition(i2c);
@@ -209,6 +278,17 @@ static void stm32_i2c_master_mode_end(const struct device *dev)
209278
LL_I2C_Disable(i2c);
210279
}
211280
#endif
281+
282+
#ifdef CONFIG_I2C_STM32_V2_DMA
283+
if (data->current.msg->flags & I2C_MSG_READ) {
284+
dma_stop(cfg->rx_dma.dev_dma, cfg->rx_dma.dma_channel);
285+
LL_I2C_DisableDMAReq_RX(i2c);
286+
} else {
287+
dma_stop(cfg->tx_dma.dev_dma, cfg->tx_dma.dma_channel);
288+
LL_I2C_DisableDMAReq_TX(i2c);
289+
}
290+
#endif /* CONFIG_I2C_STM32_V2_DMA */
291+
212292
k_sem_give(&data->device_sync_sem);
213293
}
214294

@@ -508,6 +588,17 @@ static void stm32_i2c_event(const struct device *dev)
508588
LL_I2C_GenerateStopCondition(i2c);
509589
} else {
510590
stm32_i2c_disable_transfer_interrupts(dev);
591+
592+
#ifdef CONFIG_I2C_STM32_V2_DMA
593+
if (data->current.msg->flags & I2C_MSG_READ) {
594+
dma_stop(cfg->rx_dma.dev_dma, cfg->rx_dma.dma_channel);
595+
LL_I2C_DisableDMAReq_RX(i2c);
596+
} else {
597+
dma_stop(cfg->tx_dma.dev_dma, cfg->tx_dma.dma_channel);
598+
LL_I2C_DisableDMAReq_TX(i2c);
599+
}
600+
#endif /* CONFIG_I2C_STM32_V2_DMA */
601+
511602
k_sem_give(&data->device_sync_sem);
512603
}
513604
}

0 commit comments

Comments
 (0)