Skip to content

Commit

Permalink
Added stop DMA fot transmit complete or other master end conditions
Browse files Browse the repository at this point in the history
  • Loading branch information
sgilbert182 committed Nov 23, 2024
1 parent 1556fb0 commit 601d56f
Showing 1 changed file with 104 additions and 0 deletions.
104 changes: 104 additions & 0 deletions drivers/i2c/i2c_ll_stm32_v2.c
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,42 @@ static struct stm32_i2c_timings_t i2c_valid_timing[STM32_I2C_VALID_TIMING_NBR];
static uint32_t i2c_valid_timing_nbr;
#endif /* CONFIG_I2C_STM32_V2_TIMING */

#ifdef CONFIG_I2C_DMA
static int configure_dma(const struct device *dma_dev, uint32_t dma_channel,
struct dma_config *dma_cfg, struct dma_block_config *blk_cfg,
uint32_t source_address, uint32_t dest_address, struct i2c_msg *msg,
struct k_sem *dma_sem, const char *direction)
{
if (!device_is_ready(dma_dev)) {
LOG_ERR("DMA device not ready for %s", direction);
return -ENODEV;
}

k_sem_take(dma_sem, K_FOREVER);

blk_cfg->source_address = source_address;
blk_cfg->dest_address = dest_address;
blk_cfg->block_size = msg->len;

dma_cfg->head_block = blk_cfg;
dma_cfg->block_count = 1;

int ret = dma_config(dma_dev, dma_channel, dma_cfg);
if (ret != 0) {
LOG_ERR("Problem setting up %s DMA: %d", direction, ret);
return ret;
}

ret = dma_start(dma_dev, dma_channel);
if (ret != 0) {
LOG_ERR("Problem starting %s DMA: %d", direction, ret);
return ret;
}

return 0;
}
#endif

static inline void msg_init(const struct device *dev, struct i2c_msg *msg,
uint8_t *next_msg_flags, uint16_t slave,
uint32_t transfer)
Expand Down Expand Up @@ -151,6 +187,48 @@ static inline void msg_init(const struct device *dev, struct i2c_msg *msg,
#if defined(CONFIG_I2C_TARGET)
data->master_active = true;
#endif

#ifdef CONFIG_I2C_DMA
if (msg->len) {
if (msg->flags & I2C_MSG_READ) {
// Configure RX DMA
if (configure_dma(cfg->dev_dma_rx, cfg->dma_rx_channel,
&data->dma_rx_cfg, &data->dma_rx_blk_cfg,
LL_I2C_DMA_GetRegAddr(
cfg->i2c, LL_I2C_DMA_REG_DATA_RECEIVE),
(uint32_t)msg->buf, msg, &data->dma_rx_sem,
"RX") != 0) {
return;
}
data->current.buf += msg->len;
data->current.len -= msg->len;
LL_I2C_EnableDMAReq_RX(i2c);
} else {
// Preload the TX register for the first byte

LL_I2C_TransmitData8(i2c, *data->current.buf);
data->current.buf++;
data->current.len--;

if (msg->len) {
// Configure TX DMA
if (configure_dma(
cfg->dev_dma_tx, cfg->dma_tx_channel,
&data->dma_tx_cfg, &data->dma_tx_blk_cfg,
(uint32_t)msg->buf,
LL_I2C_DMA_GetRegAddr(
cfg->i2c, LL_I2C_DMA_REG_DATA_TRANSMIT),
msg, &data->dma_tx_sem, "TX") != 0) {
return;
}
data->current.buf += msg->len;
data->current.len -= msg->len;
LL_I2C_EnableDMAReq_TX(i2c);
}
}
}
#endif

LL_I2C_Enable(i2c);

LL_I2C_GenerateStartCondition(i2c);
Expand Down Expand Up @@ -209,6 +287,19 @@ static void stm32_i2c_master_mode_end(const struct device *dev)
LL_I2C_Disable(i2c);
}
#endif

#ifdef CONFIG_I2C_DMA
if (data->current.msg->flags & I2C_MSG_READ) {
dma_stop(cfg->dev_dma_rx, cfg->dma_rx_channel);
k_sem_give(&data->dma_rx_sem);
LL_I2C_DisableDMAReq_RX(i2c);
} else {
dma_stop(cfg->dev_dma_tx, cfg->dma_tx_channel);
k_sem_give(&data->dma_tx_sem);
LL_I2C_DisableDMAReq_TX(i2c);
}
#endif

k_sem_give(&data->device_sync_sem);
}

Expand Down Expand Up @@ -508,6 +599,19 @@ static void stm32_i2c_event(const struct device *dev)
LL_I2C_GenerateStopCondition(i2c);
} else {
stm32_i2c_disable_transfer_interrupts(dev);

#ifdef CONFIG_I2C_DMA
if (data->current.msg->flags & I2C_MSG_READ) {
dma_stop(cfg->dev_dma_rx, cfg->dma_rx_channel);
k_sem_give(&data->dma_rx_sem);
LL_I2C_DisableDMAReq_RX(i2c);
} else {
dma_stop(cfg->dev_dma_tx, cfg->dma_tx_channel);
k_sem_give(&data->dma_tx_sem);
LL_I2C_DisableDMAReq_TX(i2c);
}
#endif

k_sem_give(&data->device_sync_sem);
}
}
Expand Down

0 comments on commit 601d56f

Please sign in to comment.