硬汉嵌入式论坛

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

[SAI/I2S] 请教stm32h7B0 SAI+DMA无法进DMA中断的问题。

[复制链接]

1

主题

2

回帖

5

积分

新手上路

积分
5
发表于 2025-2-10 15:45:15 | 显示全部楼层 |阅读模式
void MX_SAI2_Init(void)
{
  HAL_SAI_DeInit(&SAI2B_RX_Handler);    //清除以前的配置  

  SAI2B_RX_Handler.Instance = SAI2_Block_B;
  SAI2B_RX_Handler.Init.Protocol = SAI_FREE_PROTOCOL;   //自由协议(支持I2S/LSB/MSB/TDM/PCM/DSP等协议)  
  SAI2B_RX_Handler.Init.AudioMode = SAI_MODEMASTER_RX;
  SAI2B_RX_Handler.Init.Synchro = SAI_ASYNCHRONOUS;
  SAI2B_RX_Handler.Init.OutputDrive = SAI_OUTPUTDRIVE_DISABLE;   //SAI_OUTPUTDRIVE_ENABLE;    //立即驱动音频模块输出;
  SAI2B_RX_Handler.Init.NoDivider = SAI_MASTERDIVIDER_ENABLE;    //使能主时钟分频器(MCKDIV)
  SAI2B_RX_Handler.Init.FIFOThreshold = SAI_FIFOTHRESHOLD_EMPTY;    //SAI_FIFOTHRESHOLD_EMPTY;  //SAI_FIFOTHRESHOLD_FULL
  SAI2B_RX_Handler.Init.AudioFrequency = SAI_AUDIO_FREQUENCY_48K;
  SAI2B_RX_Handler.Init.SynchroExt = SAI_SYNCEXT_DISABLE;
  SAI2B_RX_Handler.Init.MonoStereoMode = SAI_STEREOMODE;         //立体声模式
  SAI2B_RX_Handler.Init.CompandingMode = SAI_NOCOMPANDING;
  SAI2B_RX_Handler.Init.TriState = SAI_OUTPUT_NOTRELEASED;

  //帧设置
  SAI2B_RX_Handler.FrameInit.FrameLength=128;                 //设置帧长度为32,左通道16个SCK,右通道16个SCK.
  SAI2B_RX_Handler.FrameInit.ActiveFrameLength=16;            //设置帧同步有效电平长度,在I2S模式下=1/2帧长.
  SAI2B_RX_Handler.FrameInit.FSDefinition=SAI_FS_STARTFRAME;  //SAI_FS_CHANNEL_IDENTIFICATION;//FS信号为SOF信号+通道识别信号
  SAI2B_RX_Handler.FrameInit.FSPolarity=SAI_FS_ACTIVE_LOW;    //FS低电平有效(下降沿)
  SAI2B_RX_Handler.FrameInit.FSOffset=SAI_FS_FIRSTBIT;  //SAI_FS_BEFOREFIRSTBIT; //在slot0的第一位的前一位使能FS,以匹配飞利浦标准      

  //SLOT设置
  SAI2B_RX_Handler.SlotInit.FirstBitOffset=0;                //slot偏移(FBOFF)为0
  SAI2B_RX_Handler.SlotInit.SlotSize=SAI_SLOTSIZE_16B;       //slot大小为16位
  SAI2B_RX_Handler.SlotInit.SlotNumber=8;                    //slot数为8个   
  SAI2B_RX_Handler.SlotInit.SlotActive=SAI_SLOTACTIVE_0|SAI_SLOTACTIVE_1|SAI_SLOTACTIVE_2|SAI_SLOTACTIVE_3|SAI_SLOTACTIVE_4|SAI_SLOTACTIVE_5|SAI_SLOTACTIVE_6|SAI_SLOTACTIVE_7;   

  if (HAL_SAI_InitProtocol(&SAI2B_RX_Handler, SAI_I2S_STANDARD, SAI_PROTOCOL_DATASIZE_16BIT, 8) != HAL_OK)
  {
      Error_Handler();
  }
}


static uint32_t SAI2_client =0;
static uint32_t FMC_Initialized = 0;

void HAL_SAI_MspInit(SAI_HandleTypeDef* saiHandle)
{

  GPIO_InitTypeDef GPIO_InitStruct;
  RCC_PeriphCLKInitTypeDef PeriphClkInitStruct = {0};

  if (FMC_Initialized)
  {
    return;
  }
  FMC_Initialized = 1;  

  /* SAI2 */
  if(saiHandle->Instance==SAI2_Block_B)
  {
    /* SAI2 clock enable */

    // Initializes the peripherals clock
    PeriphClkInitStruct.PeriphClockSelection = RCC_PERIPHCLK_SAI2B;
    PeriphClkInitStruct.Sai2BClockSelection = RCC_SAI2BCLKSOURCE_PLL;
    if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInitStruct) != HAL_OK)
    {
      Error_Handler();
    }

    if (SAI2_client == 0)
    {
       __HAL_RCC_SAI2_CLK_ENABLE();
    }
    SAI2_client ++;

    /**SAI2_B_Block_B GPIO Configuration
    PC0     ------> SAI2_FS_B
    PA0     ------> SAI2_SD_B
    PA2     ------> SAI2_SCK_B
    */
    GPIO_InitStruct.Pin = GPIO_PIN_0;
    GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
    GPIO_InitStruct.Pull = GPIO_NOPULL;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
    GPIO_InitStruct.Alternate = GPIO_AF8_SAI2;
    HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);

    GPIO_InitStruct.Pin = GPIO_PIN_0;
    GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
    GPIO_InitStruct.Pull = GPIO_PULLUP;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
    GPIO_InitStruct.Alternate = GPIO_AF10_SAI2;
    HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);

    GPIO_InitStruct.Pin = GPIO_PIN_2;
    GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
    GPIO_InitStruct.Pull = GPIO_NOPULL;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
    GPIO_InitStruct.Alternate = GPIO_AF8_SAI2;
    HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);

    /* Peripheral DMA init*/
    SAI2B_RXhdma_Handler.Instance = DMA1_Stream0;
    SAI2B_RXhdma_Handler.Init.Request = DMA_REQUEST_SAI2_B;
    SAI2B_RXhdma_Handler.Init.Direction = DMA_PERIPH_TO_MEMORY;
    SAI2B_RXhdma_Handler.Init.PeriphInc = DMA_PINC_DISABLE;
    SAI2B_RXhdma_Handler.Init.MemInc = DMA_MINC_ENABLE;
    SAI2B_RXhdma_Handler.Init.PeriphDataAlignment = DMA_PDATAALIGN_HALFWORD;
    SAI2B_RXhdma_Handler.Init.MemDataAlignment = DMA_MDATAALIGN_HALFWORD;
    SAI2B_RXhdma_Handler.Init.Mode = DMA_CIRCULAR;        
    SAI2B_RXhdma_Handler.Init.Priority = DMA_PRIORITY_LOW;
    SAI2B_RXhdma_Handler.Init.FIFOMode = DMA_FIFOMODE_ENABLE;  //DMA_FIFOMODE_DISABLE;  //DMA_FIFOMODE_ENABLE;
    SAI2B_RXhdma_Handler.Init.FIFOThreshold = DMA_FIFO_THRESHOLD_1QUARTERFULL;   
    SAI2B_RXhdma_Handler.Init.MemBurst = DMA_MBURST_SINGLE;
    SAI2B_RXhdma_Handler.Init.PeriphBurst = DMA_PBURST_SINGLE;

    HAL_DMA_DeInit(&SAI2B_RXhdma_Handler);   
    if (HAL_DMA_Init(&SAI2B_RXhdma_Handler) != HAL_OK)
    {
      Error_Handler();
    }   

    __HAL_LINKDMA(&SAI2B_RX_Handler,hdmarx,SAI2B_RXhdma_Handler);
    __HAL_LINKDMA(&SAI2B_RX_Handler,hdmatx,SAI2B_RXhdma_Handler);

    HAL_DMA_RegisterCallback(&SAI2B_RXhdma_Handler, HAL_DMA_XFER_CPLT_CB_ID, BSP_SAI_REC_M0_RX_Callback);
    HAL_DMA_RegisterCallback(&SAI2B_RXhdma_Handler, HAL_DMA_XFER_M1CPLT_CB_ID, BSP_SAI_REC_M1_RX_Callback);   

    //用不到的中断可以直接关闭
    //DMA1_Stream1->CR &= ~DMA_IT_DME;
    //DMA1_Stream1->CR &= ~DMA_IT_TE;
   }
}  

static uint32_t FMC_DeInitialized = 0;

void HAL_SAI_MspDeInit(SAI_HandleTypeDef* saiHandle)
{

  /* USER CODE END FMC_MspDeInit 0 */
  if (FMC_DeInitialized) {
    return;
  }
  FMC_DeInitialized = 1;   

/* SAI2 */
    if(saiHandle->Instance==SAI2_Block_B)
    {
      SAI2_client --;
      if (SAI2_client == 0)
      {
        /* Peripheral clock disable */
        __HAL_RCC_SAI2_CLK_DISABLE();
        HAL_NVIC_DisableIRQ(SAI2_IRQn);   
      }

    /**SAI2_B_Block_B GPIO Configuration
    PC0     ------> SAI2_FS_B
    PA0     ------> SAI2_SD_B
    PA2     ------> SAI2_SCK_B
    */
    HAL_GPIO_DeInit(GPIOC, GPIO_PIN_0);
    HAL_GPIO_DeInit(GPIOA, GPIO_PIN_0|GPIO_PIN_2);

    HAL_DMA_DeInit(saiHandle->hdmarx);
    HAL_DMA_DeInit(saiHandle->hdmatx);
    }
}

//SAI开始播放
void SAI_REC_Start(void)
{   
    HAL_DMA_DeInit(SAI2B_RX_Handler.hdmarx);
    __HAL_DMA_DISABLE(&SAI2B_RXhdma_Handler);                       //先关闭接收DMA
    HAL_Delay(1);                                                   //10us延时,防止-O2优化出问题

    /* Change the DMA state */
    SAI2B_RXhdma_Handler.State = HAL_DMA_STATE_READY;

    //开启双缓冲,及缓冲区的大小
    HAL_DMAEx_MultiBufferStart_IT(&SAI2B_RXhdma_Handler, (uint32_t)&SAI2B_RX_Handler.Instance->DR, (uint32_t)sai_rec_buf1, (uint32_t)sai_rec_buf2, 8); //SAI_RX_DMA_BUF_SIZE/2);   


    /* Several peripheral DMA handle pointers point to the same DMA handle.
     Be aware that there is only one channel to perform all the requested DMAs. */
    __HAL_LINKDMA(&SAI2B_RX_Handler,hdmarx,SAI2B_RXhdma_Handler);   
    __HAL_LINKDMA(&SAI2B_RX_Handler,hdmatx,SAI2B_RXhdma_Handler);

    __HAL_DMA_ENABLE_IT(&SAI2B_RXhdma_Handler, DMA_IT_TC);
    __HAL_DMA_ENABLE_IT(&SAI2B_RXhdma_Handler, DMA_IT_HT);

    //开启 DMA1 Stream1 的中断
    HAL_NVIC_SetPriority(DMA1_Stream0_IRQn, 0x02, 0);
    HAL_NVIC_EnableIRQ(DMA1_Stream0_IRQn);

    __HAL_SAI_ENABLE(&SAI2B_RX_Handler);      //使能SAI   
    HAL_Delay(1);
    __HAL_DMA_ENABLE(&SAI2B_RXhdma_Handler);  //开启DMA RX传输
}

回复

使用道具 举报

1

主题

2

回帖

5

积分

新手上路

积分
5
 楼主| 发表于 2025-2-10 15:46:43 | 显示全部楼层
SAI_BDR可以看到数据,但DMA不进中断,麻烦高手帮忙看看是什么原因。
回复

使用道具 举报

1

主题

35

回帖

38

积分

新手上路

积分
38
发表于 2025-2-10 16:42:53 | 显示全部楼层
ram的地址 有关系  有些ram地址 不支持dma
回复

使用道具 举报

1

主题

2

回帖

5

积分

新手上路

积分
5
 楼主| 发表于 2025-2-10 17:57:11 | 显示全部楼层
sy2009 发表于 2025-2-10 16:42
ram的地址 有关系  有些ram地址 不支持dma

__attribute__((section (".RAM_D1")))  uint16_t sai_rec_buf1[0x800];  /* 数据缓存区0 */
__attribute__((section (".RAM_D1")))  uint16_t sai_rec_buf2[0x800];  /* 数据缓存区1 */

AXI RAM可以吗?需要什么特别的配置吗?
回复

使用道具 举报

1

主题

2

回帖

5

积分

新手上路

积分
5
 楼主| 发表于 2025-2-10 18:21:44 | 显示全部楼层
static void MPU_Config(void)
{
        MPU_Region_InitTypeDef MPU_InitStruct;

        /* 禁止 MPU */
        HAL_MPU_Disable();

        /* 配置AXI SRAM的MPU属性为Write back, Read allocate,Write allocate */
        MPU_InitStruct.Enable           = MPU_REGION_ENABLE;
        MPU_InitStruct.BaseAddress      = 0x24000000;
        MPU_InitStruct.Size             = MPU_REGION_SIZE_512KB;
        MPU_InitStruct.AccessPermission = MPU_REGION_FULL_ACCESS;
        MPU_InitStruct.IsBufferable     = MPU_ACCESS_BUFFERABLE;
        MPU_InitStruct.IsCacheable      = MPU_ACCESS_CACHEABLE;
        MPU_InitStruct.IsShareable      = MPU_ACCESS_SHAREABLE;  //MPU_ACCESS_NOT_SHAREABLE;
        MPU_InitStruct.Number           = MPU_REGION_NUMBER0;
        MPU_InitStruct.TypeExtField     = MPU_TEX_LEVEL1;
        MPU_InitStruct.SubRegionDisable = 0x00;
        MPU_InitStruct.DisableExec      = MPU_INSTRUCTION_ACCESS_ENABLE;

        HAL_MPU_ConfigRegion(&MPU_InitStruct);       
       
        /* 配置SRAM1的属性为Write through, read allocate,no write allocate */
    MPU_InitStruct.Enable           = MPU_REGION_ENABLE;
    MPU_InitStruct.BaseAddress      = 0x30000000;
    MPU_InitStruct.Size             = ARM_MPU_REGION_SIZE_128KB;       
    MPU_InitStruct.AccessPermission = MPU_REGION_FULL_ACCESS;
    MPU_InitStruct.IsBufferable     = MPU_ACCESS_NOT_BUFFERABLE;
    MPU_InitStruct.IsCacheable      = MPU_ACCESS_CACHEABLE;
    MPU_InitStruct.IsShareable      = MPU_ACCESS_NOT_SHAREABLE;
    MPU_InitStruct.Number           = MPU_REGION_NUMBER2;
    MPU_InitStruct.TypeExtField     = MPU_TEX_LEVEL0;
    MPU_InitStruct.SubRegionDisable = 0x00;
    MPU_InitStruct.DisableExec      = MPU_INSTRUCTION_ACCESS_ENABLE;

    HAL_MPU_ConfigRegion(&MPU_InitStruct);

        /*使能 MPU */
        HAL_MPU_Enable(MPU_PRIVILEGED_DEFAULT);
}

没有开CACHE。
回复

使用道具 举报

1万

主题

7万

回帖

11万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
115653
QQ
发表于 2025-2-11 06:27:07 | 显示全部楼层
sy2009 发表于 2025-2-10 16:42
ram的地址 有关系  有些ram地址 不支持dma

这种设置是可以的,注意看MAP文件,确定没有被分配到TCM RAM,这个不支持通用DMA
回复

使用道具 举报

0

主题

13

回帖

13

积分

新手上路

积分
13
发表于 前天 17:13 | 显示全部楼层
可以去调试里看一下申请的内存区域有没有成功
建议检查一下参考手册(RM0455),看看这块总线能不能访问到
回复

使用道具 举报

0

主题

13

回帖

13

积分

新手上路

积分
13
发表于 前天 17:15 | 显示全部楼层
这是rm0455里h7b0的示意图
matrix.png
回复

使用道具 举报

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

本版积分规则

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

GMT+8, 2025-5-10 03:46 , Processed in 0.506966 second(s), 28 queries .

Powered by Discuz! X3.4 Licensed

Copyright © 2001-2023, Tencent Cloud.

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