i2s: stm32h7: add i2s support for stm32h7 mcu family
This commit modifies the I2S driver to work for STM32H7 family of MCU's. Currently only TX is working. Tested on nucleo_stm32h743zi. Requires dma1 & dmamux1 to be enabled. Signed-off-by: Emil Lindqvist <emil@lindq.gr>
This commit is contained in:
parent
c3e8b731ef
commit
ed6da68f5b
7 changed files with 153 additions and 32 deletions
|
@ -10,7 +10,7 @@ menuconfig I2S_STM32
|
|||
select DMA
|
||||
help
|
||||
Enable I2S support on the STM32 family of processors.
|
||||
(Tested on the STM32F4 series)
|
||||
(Tested on the STM32F4 & STM32H7 series)
|
||||
|
||||
if I2S_STM32
|
||||
|
||||
|
|
|
@ -22,11 +22,7 @@
|
|||
#include <zephyr/irq.h>
|
||||
LOG_MODULE_REGISTER(i2s_ll_stm32);
|
||||
|
||||
/* FIXME change to
|
||||
* #if __DCACHE_PRESENT == 1
|
||||
* when cache support is added
|
||||
*/
|
||||
#if 0
|
||||
#if __DCACHE_PRESENT == 1
|
||||
#define DCACHE_INVALIDATE(addr, size) \
|
||||
SCB_InvalidateDCache_by_Addr((uint32_t *)addr, size)
|
||||
#define DCACHE_CLEAN(addr, size) \
|
||||
|
@ -187,6 +183,9 @@ static int i2s_stm32_configure(const struct device *dev, enum i2s_dir dir,
|
|||
int ret;
|
||||
|
||||
if (dir == I2S_DIR_RX) {
|
||||
#if DT_HAS_COMPAT_STATUS_OKAY(st_stm32h7_i2s)
|
||||
return -ENOSYS;
|
||||
#endif
|
||||
stream = &dev_data->rx;
|
||||
} else if (dir == I2S_DIR_TX) {
|
||||
stream = &dev_data->tx;
|
||||
|
@ -549,7 +548,11 @@ static void dma_rx_callback(const struct device *dma_dev, void *arg,
|
|||
|
||||
ret = reload_dma(stream->dev_dma, stream->dma_channel,
|
||||
&stream->dma_cfg,
|
||||
#if DT_HAS_COMPAT_STATUS_OKAY(st_stm32h7_i2s)
|
||||
(void *)LL_SPI_DMA_GetRxRegAddr(cfg->i2s),
|
||||
#else
|
||||
(void *)LL_SPI_DMA_GetRegAddr(cfg->i2s),
|
||||
#endif
|
||||
stream->mem_block,
|
||||
stream->cfg.block_size);
|
||||
if (ret < 0) {
|
||||
|
@ -634,7 +637,11 @@ static void dma_tx_callback(const struct device *dma_dev, void *arg,
|
|||
ret = reload_dma(stream->dev_dma, stream->dma_channel,
|
||||
&stream->dma_cfg,
|
||||
stream->mem_block,
|
||||
#if DT_HAS_COMPAT_STATUS_OKAY(st_stm32h7_i2s)
|
||||
(void *)LL_SPI_DMA_GetTxRegAddr(cfg->i2s),
|
||||
#else
|
||||
(void *)LL_SPI_DMA_GetRegAddr(cfg->i2s),
|
||||
#endif
|
||||
stream->cfg.block_size);
|
||||
if (ret < 0) {
|
||||
LOG_DBG("Failed to start TX DMA transfer: %d", ret);
|
||||
|
@ -649,6 +656,7 @@ tx_disable:
|
|||
|
||||
static uint32_t i2s_stm32_irq_count;
|
||||
static uint32_t i2s_stm32_irq_ovr_count;
|
||||
static uint32_t i2s_stm32_irq_udr_count;
|
||||
|
||||
static void i2s_stm32_isr(const struct device *dev)
|
||||
{
|
||||
|
@ -665,6 +673,12 @@ static void i2s_stm32_isr(const struct device *dev)
|
|||
LL_I2S_ClearFlag_OVR(cfg->i2s);
|
||||
}
|
||||
|
||||
/* NOTE: UDR error must be explicitly cleared on STM32H7 */
|
||||
if (LL_I2S_IsActiveFlag_UDR(cfg->i2s)) {
|
||||
i2s_stm32_irq_udr_count++;
|
||||
LL_I2S_ClearFlag_UDR(cfg->i2s);
|
||||
}
|
||||
|
||||
i2s_stm32_irq_count++;
|
||||
}
|
||||
|
||||
|
@ -736,7 +750,11 @@ static int rx_stream_start(struct stream *stream, const struct device *dev)
|
|||
|
||||
ret = start_dma(stream->dev_dma, stream->dma_channel,
|
||||
&stream->dma_cfg,
|
||||
#if DT_HAS_COMPAT_STATUS_OKAY(st_stm32h7_i2s)
|
||||
(void *)LL_SPI_DMA_GetRxRegAddr(cfg->i2s),
|
||||
#else
|
||||
(void *)LL_SPI_DMA_GetRegAddr(cfg->i2s),
|
||||
#endif
|
||||
stream->src_addr_increment, stream->mem_block,
|
||||
stream->dst_addr_increment, stream->fifo_threshold,
|
||||
stream->cfg.block_size);
|
||||
|
@ -747,8 +765,17 @@ static int rx_stream_start(struct stream *stream, const struct device *dev)
|
|||
|
||||
LL_I2S_EnableDMAReq_RX(cfg->i2s);
|
||||
|
||||
#if DT_HAS_COMPAT_STATUS_OKAY(st_stm32h7_i2s)
|
||||
LL_I2S_EnableIT_OVR(cfg->i2s);
|
||||
LL_I2S_EnableIT_UDR(cfg->i2s);
|
||||
LL_I2S_EnableIT_FRE(cfg->i2s);
|
||||
LL_I2S_Enable(cfg->i2s);
|
||||
LL_SPI_StartMasterTransfer(cfg->i2s);
|
||||
#else
|
||||
LL_I2S_EnableIT_ERR(cfg->i2s);
|
||||
LL_I2S_Enable(cfg->i2s);
|
||||
#endif
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -781,7 +808,11 @@ static int tx_stream_start(struct stream *stream, const struct device *dev)
|
|||
ret = start_dma(stream->dev_dma, stream->dma_channel,
|
||||
&stream->dma_cfg,
|
||||
stream->mem_block, stream->src_addr_increment,
|
||||
#if DT_HAS_COMPAT_STATUS_OKAY(st_stm32h7_i2s)
|
||||
(void *)LL_SPI_DMA_GetTxRegAddr(cfg->i2s),
|
||||
#else
|
||||
(void *)LL_SPI_DMA_GetRegAddr(cfg->i2s),
|
||||
#endif
|
||||
stream->dst_addr_increment, stream->fifo_threshold,
|
||||
stream->cfg.block_size);
|
||||
if (ret < 0) {
|
||||
|
@ -791,8 +822,17 @@ static int tx_stream_start(struct stream *stream, const struct device *dev)
|
|||
|
||||
LL_I2S_EnableDMAReq_TX(cfg->i2s);
|
||||
|
||||
#if DT_HAS_COMPAT_STATUS_OKAY(st_stm32h7_i2s)
|
||||
LL_I2S_EnableIT_OVR(cfg->i2s);
|
||||
LL_I2S_EnableIT_UDR(cfg->i2s);
|
||||
LL_I2S_EnableIT_FRE(cfg->i2s);
|
||||
|
||||
LL_I2S_Enable(cfg->i2s);
|
||||
LL_SPI_StartMasterTransfer(cfg->i2s);
|
||||
#else
|
||||
LL_I2S_EnableIT_ERR(cfg->i2s);
|
||||
LL_I2S_Enable(cfg->i2s);
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -802,7 +842,13 @@ static void rx_stream_disable(struct stream *stream, const struct device *dev)
|
|||
const struct i2s_stm32_cfg *cfg = dev->config;
|
||||
|
||||
LL_I2S_DisableDMAReq_RX(cfg->i2s);
|
||||
#if DT_HAS_COMPAT_STATUS_OKAY(st_stm32h7_i2s)
|
||||
LL_I2S_DisableIT_OVR(cfg->i2s);
|
||||
LL_I2S_DisableIT_UDR(cfg->i2s);
|
||||
LL_I2S_DisableIT_FRE(cfg->i2s);
|
||||
#else
|
||||
LL_I2S_DisableIT_ERR(cfg->i2s);
|
||||
#endif
|
||||
|
||||
dma_stop(stream->dev_dma, stream->dma_channel);
|
||||
if (stream->mem_block != NULL) {
|
||||
|
@ -820,7 +866,13 @@ static void tx_stream_disable(struct stream *stream, const struct device *dev)
|
|||
const struct i2s_stm32_cfg *cfg = dev->config;
|
||||
|
||||
LL_I2S_DisableDMAReq_TX(cfg->i2s);
|
||||
#if DT_HAS_COMPAT_STATUS_OKAY(st_stm32h7_i2s)
|
||||
LL_I2S_DisableIT_OVR(cfg->i2s);
|
||||
LL_I2S_DisableIT_UDR(cfg->i2s);
|
||||
LL_I2S_DisableIT_FRE(cfg->i2s);
|
||||
#else
|
||||
LL_I2S_DisableIT_ERR(cfg->i2s);
|
||||
#endif
|
||||
|
||||
dma_stop(stream->dev_dma, stream->dma_channel);
|
||||
if (stream->mem_block != NULL) {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue