硬汉嵌入式论坛

 找回密码
 立即注册
查看: 222|回复: 8
收起左侧

[DMA] H743 I2S DMA传输报错FEIF问题

[复制链接]

2

主题

4

回帖

10

积分

新手上路

积分
10
发表于 2025-11-23 10:23:15 | 显示全部楼层 |阅读模式
H743 I2S DMA传输报错FEIF问题

使用DMA给I2S传输数据,第一次能够正常传输完成进中断,但是会有FEIF标志置位。开启第二次传输后传了几个数就停下了,同样会有FEIF,且清除该位后不能继续传。


已经排除了内存布局问题。因为缓冲区还需要给SDMMC1使用,所以放在了AXI上。也试过放入SDRAM中问题依旧。缓冲区起始地址也已经32字节对齐。


DMA的FIFO也没有开启,但还是会报这个错,感觉能查的都查差不多了。万望大佬们提供个思路!

回复

使用道具 举报

2

主题

4

回帖

10

积分

新手上路

积分
10
 楼主| 发表于 2025-11-23 11:12:15 | 显示全部楼层
为什么帖子内容一点都不显示呢
回复

使用道具 举报

1万

主题

7万

回帖

12万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
120448
QQ
发表于 2025-11-23 11:13:14 | 显示全部楼层
广寒七号 发表于 2025-11-23 11:12
为什么帖子内容一点都不显示呢

图片要单独上传

论坛bug不支持图片复制粘贴
https://forum.anfulai.cn/forum.p ... 6432&fromuid=58
(出处: 硬汉嵌入式论坛)
回复

使用道具 举报

2

主题

4

回帖

10

积分

新手上路

积分
10
 楼主| 发表于 2025-11-23 11:25:46 | 显示全部楼层
eric2013 发表于 2025-11-23 11:13
图片要单独上传

论坛bug不支持图片复制粘贴

哦哦难怪,新入论坛的不知道。这么说这个帖子可以删除了,我重新传吧(没找到在哪里删除)
回复

使用道具 举报

2

主题

4

回帖

10

积分

新手上路

积分
10
 楼主| 发表于 2025-11-23 11:52:40 | 显示全部楼层

H743 I2S DMA传输报错FEIF问题

使用DMA给I2S传输数据,第一次能够正常传输完成进中断,但是会有FEIF标志置位。开启第二次传输后传了几个数就停下了,同样会有FEIF,且清除该位后不能继续传。

FEIF标志

FEIF标志

开始传输

开始传输

已经排除了内存布局问题。因为缓冲区还需要给SDMMC1使用,所以放在了AXI上。也试过放入SDRAM中问题依旧。缓冲区起始地址也已经32字节对齐。

内存位置

内存位置

DMA的FIFO也没有开启,但还是会报这个错,感觉能查的都查差不多了。万望大佬们提供个思路!

初始化代码

初始化代码



回复

使用道具 举报

1万

主题

7万

回帖

12万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
120448
QQ
发表于 2025-11-24 09:14:57 | 显示全部楼层
广寒七号 发表于 2025-11-23 11:52
使用DMA给I2S传输数据,第一次能够正常传输完成进中断,但是会有FEIF标志置位。开启第二次传输后传了几个数 ...

方便的话,完整的I2S配置代码看下。
回复

使用道具 举报

2

主题

4

回帖

10

积分

新手上路

积分
10
 楼主| 发表于 2025-11-26 10:36:36 | 显示全部楼层
eric2013 发表于 2025-11-24 09:14
方便的话,完整的I2S配置代码看下。

DMA问题应该是已经解决了,不使用FIFO时可以不关注这个标志位,但是HAL默认开启了所有标志位的中断,可能造成性能问题。
不传输是因为I2S的UDR因为未知原因被置位,导致不再触发DMA传输,造成的死机。实测在debug模式中手动去掉这个标志就可以继续传下一包,但又会继续UDR。

再次改进后使用DMA的32位传输能力,直接将数据以32位传入SPI->TXDR,但需要重新设置FIFO阈值(HAL的I2S并未提供这种函数,只能手动操作寄存器,即以下代码的最后一句),默认的阈值会导致丢数据造成音乐播放速度快一倍。

  /* USER CODE END I2S3_Init 1 */
  hi2s3.Instance = SPI3;
  hi2s3.Init.Mode = I2S_MODE_MASTER_TX;
  hi2s3.Init.Standard = I2S_STANDARD_PHILIPS;
  hi2s3.Init.DataFormat = I2S_DATAFORMAT_16B;
  hi2s3.Init.MCLKOutput = I2S_MCLKOUTPUT_ENABLE;
  hi2s3.Init.AudioFreq = I2S_AUDIOFREQ_96K;
  hi2s3.Init.CPOL = I2S_CPOL_LOW;
  hi2s3.Init.FirstBit = I2S_FIRSTBIT_MSB;
  hi2s3.Init.WSInversion = I2S_WS_INVERSION_DISABLE;
  hi2s3.Init.Data24BitAlignment = I2S_DATA_24BIT_ALIGNMENT_RIGHT;
  hi2s3.Init.MasterKeepIOState = I2S_MASTER_KEEP_IO_STATE_ENABLE;
  if (HAL_I2S_Init(&hi2s3) != HAL_OK)
  {
    Error_Handler();
  }
  /* USER CODE BEGIN I2S3_Init 2 */
        SPI3->CFG1|=1<<5;
  /* USER CODE END I2S3_Init 2 */
回复

使用道具 举报

2

主题

4

回帖

10

积分

新手上路

积分
10
 楼主| 发表于 2025-11-26 10:40:25 | 显示全部楼层
另外HAL的外设DMA默认不支持双缓冲,感觉挺坑人的,手动调用DMA的双缓冲设计函数又跟外设函数的DMA冲突,只能手动操作寄存器实现(WM8978.c中发送函数下的部分注释代码)

不过目前读取wav直接扔给I2S播放还是会存在缓冲区边界破音问题,目前还没找到原因究竟在哪


int fatfs_readbuffer(FIL *file,void * buffer,unsigned int size)
{
        FRESULT res;
        int cnt=0;
        int bw=0;
        while (1) {
                res = f_read(file, buffer+cnt,size-cnt,&bw);
                if(res!=FR_OK)
                {
                        return -1;
                }
                cnt += bw;
                if(bw==0)
                {
                        return -2;
                }
                if (size != cnt) {
                        //DBGOUT("ReadError@%s: %d\n", __func__, __LINE__);
                        //UART_DUMP(&g_frame_rx);
                        continue;
                }
                //count = nbytes = 0;
                break;
        }
        return 0;
}

// DMA 回调函数
void HAL_I2S_TxCpltCallback(I2S_HandleTypeDef *hspi) {
// 处理缓冲区切换后的操作
// 更新 buffer0 或 buffer1 的数据
        //printf("b\n");
        //LL_DMA_ClearFlag_FE0(DMA1_Stream0);
        __HAL_I2S_CLEAR_UDRFLAG(&hi2s3);
        xSemaphoreGiveFromISR(wav_semap,pdTRUE);
       
       
}

int wav_thread(char* filename)
{
        FIL file;
        FRESULT res;
        int bw;
        char bufferflag=0;
       
        wav_semap=xSemaphoreCreateBinary();
       
        res=f_open(&file,filename,FA_OPEN_EXISTING | FA_READ);
        if(res!=FR_OK)
        {
                printf("fatfs open error:%d\n",res);
                //vTaskDelete(NULL);
        }
        printf("open file success\n");
       
        res=f_read(&file,&wavheader,sizeof(wavheader),&bw);
        if(res!=FR_OK)
        {
                printf("fatfs read error:%d\n",res);
        }
        printf("rid:%x\n",wavheader.rId);
        printf("rLen:%x\n",wavheader.rLen);
        printf("fLen:%x\n",wavheader.fLen);
        printf("Format:%x\n",wavheader.wFormatTag);
        printf("nChannels:%x\n",wavheader.nChannels);
        printf("Samplerate:%x\n",wavheader.nSamplesPerSec);
        printf("BitsPerSample:%x\n",wavheader.wBitsPerSample);
       
       
        fatfs_readbuffer(&file,wav_buffer1,65535*4);
       
        fatfs_readbuffer(&file,wav_buffer2,65535*4);
       
//        res=f_read(&file,wav_buffer2,65535,&bw);
//        if(res!=FR_OK)
//        {
//                printf("fatfs read wav error:%d\n",res);
//        }
        LL_DMA_DisableFifoMode(DMA1,LL_DMA_STREAM_0);
        LL_DMA_DisableIT_FE(DMA1,LL_DMA_STREAM_0);
                HAL_DMAEx_MultiBufferStart_IT((hi2s3.hdmatx),
        (uint32_t)wav_buffer1,
        (uint32_t)&(SPI3->TXDR),
        (uint32_t)wav_buffer2,
        65535);       
        LL_DMA_DisableStream(DMA1,LL_DMA_STREAM_0);
        LL_DMA_DisableIT_FE(DMA1,LL_DMA_STREAM_0);
        LL_DMA_DisableIT_HT(DMA1,LL_DMA_STREAM_0);
        LL_DMA_DisableIT_TE(DMA1,LL_DMA_STREAM_0);
        LL_DMA_DisableIT_DME(DMA1,LL_DMA_STREAM_0);
        LL_DMA_EnableStream(DMA1,LL_DMA_STREAM_0);
       
//        HAL_I2S_Transmit_DMA(&hi2s3,wav_buffer1,65535);
//        hi2s3.hdmatx->XferCpltCallback = HAL_I2S_TxCpltCallback;
//        hi2s3.State       = HAL_I2S_STATE_BUSY_TX;
//  hi2s3.ErrorCode   = HAL_I2S_ERROR_NONE;
//       
//        LL_DMA_EnableIT_TC(DMA1,LL_DMA_STREAM_0);
//        LL_DMA_EnableStream(DMA1,LL_DMA_STREAM_0);
        SET_BIT(hi2s3.Instance->CFG1, SPI_CFG1_TXDMAEN);
       
        SET_BIT(hi2s3.Instance->CR1, SPI_CR1_SPE);
        SET_BIT(hi2s3.Instance->CR1, SPI_CR1_CSTART);
       
        while(1)
        {
                if(xSemaphoreTake(wav_semap, 1000)!=pdTRUE)
                {
                        printf("semp error\n");
                }
               
                if(bufferflag==0)
                {
                       
//                        HAL_I2S_Transmit_DMA(&hi2s3,wav_buffer2,65535);
                        fatfs_readbuffer(&file,wav_buffer1,65535*4);
//                        res=f_read(&file,wav_buffer1,65535,&bw);
//                        if(res!=FR_OK)
//                        {
//                                printf("fatfs read wav error:%d\n",res);
//                        }
                       
                        bufferflag=1;
                }
                else
                {
//                        __HAL_I2S_CLEAR_UDRFLAG(&hi2s3);
//                        HAL_I2S_Transmit_DMA(&hi2s3,wav_buffer1,65535);
                        fatfs_readbuffer(&file,wav_buffer2,65535*4);
//                        res=f_read(&file,wav_buffer2,65535,&bw);
//                        if(res!=FR_OK)
//                        {
//                                printf("fatfs read wav error:%d\n",res);
//                        }
                        bufferflag=0;
                }
                //printf("a\n");
               
               
        }
       
}
回复

使用道具 举报

1万

主题

7万

回帖

12万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
120448
QQ
发表于 2025-11-27 11:07:13 | 显示全部楼层
广寒七号 发表于 2025-11-26 10:36
DMA问题应该是已经解决了,不使用FIFO时可以不关注这个标志位,但是HAL默认开启了所有标志位的中断,可能 ...

谢谢告知原因。
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|小黑屋|Archiver|手机版|硬汉嵌入式论坛

GMT+8, 2026-1-10 17:23 , Processed in 0.083753 second(s), 28 queries .

Powered by Discuz! X3.4 Licensed

Copyright © 2001-2023, Tencent Cloud.

快速回复 返回顶部 返回列表