硬件平台:H750-ART-Pi
软件平台:CubeMX+HAL库 V1.12.1版本
问题背景:需要使用定时器触发DMA-SPI向外部DAC发送数据,由于需要向外部发送的数据量较大且配置SPI总线的多通道,当前需要使用DMA双缓冲配置(从SD卡中读取BIN文件依次填充PingPong-FIFO,使用外扩SDRAM作为DMA-BUF)
遇到的问题:当前已经能够使用单缓冲+定时器触发的方式来向外发送数据,使用双缓冲时,无反应(定时器在工作,当前网络上的一些例程都是基于标准库的,参考作用有限),想求助下HAL库DMA双缓冲案例或者函数调用顺序。
详情参考gitee链接:GIt-CubeMX配置
启动定时器部分代码:HAL_DMAEx_MultiBufferStart_IT这个函数应该是DMA双缓冲的关键 但是开启后无效,即使单缓冲正常工作下也无法看到SPI_TXDR更新,很奇怪- void BSP_DAC_SPI_DMA_Start()
- {
- LookUP_BUF_INIT();
- // HAL_DMAEx_MultiBufferStart(&hspi2.hdmatx, LookUP_PingPongBufer.activeBuffer, &hspi2.Instance->TXDR,LookUP_PingPongBufer.readyBuffer,BUFFER_SIZE/4);
- HAL_DMAEx_MultiBufferStart_IT(&hdma_spi2_tx, LookUP_PingPongBufer.activeBuffer, &hspi2.Instance->TXDR, LookUP_PingPongBufer.readyBuffer,BUFFER_SIZE/4);
- // if(HAL_SPI_Transmit_DMA(&hspi2, (uint8_t*)LookUP_PingPongBufer.activeBuffer, BUFFER_SIZE/4)!= HAL_OK)
- // {
- // printf("BSP_DAC_SPI_DMA_Start HAL_SPI_Transmit_DMA ERROR !!! \r\n");
- // }
- if(HAL_TIM_OC_Start(&htim12, TIM_CHANNEL_1) != HAL_OK)
- {
- printf("BSP_DAC_SPI_DMA_Start HAL_TIM_OC_Start ERROR !!! \r\n");
- }
- }
- void LookUP_BUF_INIT(void)
- {
- FRESULT result;
- uint32_t bw;
- char path[64];
-
- PingPong_Init(&LookUP_PingPongBufer,LOOKUP_BUF1_ADDR,LOOKUP_BUF2_ADDR);
-
- result = f_mount(&fs, DiskPath, 0); /* Mount a logical drive */
- if (result != FR_OK)
- {
- printf("mount fs failed !!\r\n", FR_Table[result]);
- }
- sprintf(path, "%sTable_hex.bin", DiskPath);
- result = f_open(&file, path, FA_OPEN_EXISTING | FA_READ);
- if (result != FR_OK)
- {
- printf("Don't Find File : Table_hex\r\n");
- return;
- }
- result = f_read(&file, LookUP_PingPongBufer.activeBuffer , BUFFER_SIZE, &bw);
- if (bw > 0)
- {
- FsReadBuf[bw] = 0;
- }
-
- result = f_read(&file, LookUP_PingPongBufer.readyBuffer , BUFFER_SIZE, &bw);
- if (bw > 0)
- {
- FsReadBuf[bw] = 0;
- }
- // f_close(&file);
- // f_mount(NULL, DiskPath, 0);
- }
复制代码 定时器初始化部分代码:
- void MX_SPI2_Init(void)
- {
- /* USER CODE BEGIN SPI2_Init 0 */
- /* USER CODE END SPI2_Init 0 */
- /* USER CODE BEGIN SPI2_Init 1 */
- /* USER CODE END SPI2_Init 1 */
- hspi2.Instance = SPI2;
- hspi2.Init.Mode = SPI_MODE_MASTER;
- hspi2.Init.Direction = SPI_DIRECTION_2LINES;
- hspi2.Init.DataSize = SPI_DATASIZE_32BIT;
- hspi2.Init.CLKPolarity = SPI_POLARITY_LOW;
- hspi2.Init.CLKPhase = SPI_PHASE_1EDGE;
- hspi2.Init.NSS = SPI_NSS_SOFT;
- hspi2.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_4;
- hspi2.Init.FirstBit = SPI_FIRSTBIT_MSB;
- hspi2.Init.TIMode = SPI_TIMODE_DISABLE;
- hspi2.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE;
- hspi2.Init.CRCPolynomial = 0x0;
- hspi2.Init.NSSPMode = SPI_NSS_PULSE_ENABLE;
- hspi2.Init.NSSPolarity = SPI_NSS_POLARITY_LOW;
- hspi2.Init.FifoThreshold = SPI_FIFO_THRESHOLD_01DATA;
- hspi2.Init.TxCRCInitializationPattern = SPI_CRC_INITIALIZATION_ALL_ZERO_PATTERN;
- hspi2.Init.RxCRCInitializationPattern = SPI_CRC_INITIALIZATION_ALL_ZERO_PATTERN;
- hspi2.Init.MasterSSIdleness = SPI_MASTER_SS_IDLENESS_00CYCLE;
- hspi2.Init.MasterInterDataIdleness = SPI_MASTER_INTERDATA_IDLENESS_00CYCLE;
- hspi2.Init.MasterReceiverAutoSusp = SPI_MASTER_RX_AUTOSUSP_DISABLE;
- hspi2.Init.MasterKeepIOState = SPI_MASTER_KEEP_IO_STATE_DISABLE;
- hspi2.Init.IOSwap = SPI_IO_SWAP_DISABLE;
- if (HAL_SPI_Init(&hspi2) != HAL_OK)
- {
- Error_Handler();
- }
- /* USER CODE BEGIN SPI2_Init 2 */
- /* USER CODE END SPI2_Init 2 */
- }
- void HAL_SPI_MspInit(SPI_HandleTypeDef* spiHandle)
- {
- GPIO_InitTypeDef GPIO_InitStruct = {0};
- HAL_DMA_MuxSyncConfigTypeDef pSyncConfig= {0};
- RCC_PeriphCLKInitTypeDef PeriphClkInitStruct = {0};
- if(spiHandle->Instance==SPI2)
- {
- /* USER CODE BEGIN SPI2_MspInit 0 */
- /* USER CODE END SPI2_MspInit 0 */
- /** Initializes the peripherals clock
- */
- PeriphClkInitStruct.PeriphClockSelection = RCC_PERIPHCLK_SPI2;
- PeriphClkInitStruct.Spi123ClockSelection = RCC_SPI123CLKSOURCE_CLKP;
- if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInitStruct) != HAL_OK)
- {
- Error_Handler();
- }
- /* SPI2 clock enable */
- __HAL_RCC_SPI2_CLK_ENABLE();
- __HAL_RCC_GPIOI_CLK_ENABLE();
- /**SPI2 GPIO Configuration
- PI1 ------> SPI2_SCK
- PI2 ------> SPI2_MISO
- PI3 ------> SPI2_MOSI
- */
- GPIO_InitStruct.Pin = GPIO_PIN_1|GPIO_PIN_2|GPIO_PIN_3;
- GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
- GPIO_InitStruct.Pull = GPIO_NOPULL;
- GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
- GPIO_InitStruct.Alternate = GPIO_AF5_SPI2;
- HAL_GPIO_Init(GPIOI, &GPIO_InitStruct);
- /* SPI2 DMA Init */
- /* SPI2_TX Init */
- hdma_spi2_tx.Instance = DMA1_Stream0;
- hdma_spi2_tx.Init.Request = DMA_REQUEST_SPI2_TX;
- hdma_spi2_tx.Init.Direction = DMA_MEMORY_TO_PERIPH;
- hdma_spi2_tx.Init.PeriphInc = DMA_PINC_DISABLE;
- hdma_spi2_tx.Init.MemInc = DMA_MINC_ENABLE;
- hdma_spi2_tx.Init.PeriphDataAlignment = DMA_PDATAALIGN_WORD;
- hdma_spi2_tx.Init.MemDataAlignment = DMA_MDATAALIGN_WORD;
- hdma_spi2_tx.Init.Mode = DMA_CIRCULAR;
- hdma_spi2_tx.Init.Priority = DMA_PRIORITY_LOW;
- hdma_spi2_tx.Init.FIFOMode = DMA_FIFOMODE_ENABLE;
- hdma_spi2_tx.Init.FIFOThreshold = DMA_FIFO_THRESHOLD_FULL;
- hdma_spi2_tx.Init.MemBurst = DMA_MBURST_SINGLE;
- hdma_spi2_tx.Init.PeriphBurst = DMA_PBURST_SINGLE;
- if (HAL_DMA_Init(&hdma_spi2_tx) != HAL_OK)
- {
- Error_Handler();
- }
- pSyncConfig.SyncSignalID = HAL_DMAMUX1_SYNC_TIM12_TRGO;
- pSyncConfig.SyncPolarity = HAL_DMAMUX_SYNC_RISING;
- pSyncConfig.SyncEnable = ENABLE;
- pSyncConfig.EventEnable = ENABLE;
- pSyncConfig.RequestNumber = 1;
- if (HAL_DMAEx_ConfigMuxSync(&hdma_spi2_tx, &pSyncConfig) != HAL_OK)
- {
- Error_Handler();
- }
- __HAL_LINKDMA(spiHandle,hdmatx,hdma_spi2_tx);
- /* SPI2 interrupt Init */
- HAL_NVIC_SetPriority(SPI2_IRQn, 0, 0);
- HAL_NVIC_EnableIRQ(SPI2_IRQn);
- /* USER CODE BEGIN SPI2_MspInit 1 */
- // HAL_DMAEx_MultiBufferStart_IT(&hdma_spi2_tx, (uint8_t*)LookUP_PingPongBufer.activeBuffer, (uint32_t)hspi2.Instance->TXDR, (uint8_t*)LookUP_PingPongBufer.readyBuffer,1000);
-
- /* USER CODE END SPI2_MspInit 1 */
- }
- }
复制代码
SPI初始化部分代码:
- /* TIM12 init function */
- void MX_TIM12_Init(void)
- {
- /* USER CODE BEGIN TIM12_Init 0 */
- /* USER CODE END TIM12_Init 0 */
- TIM_ClockConfigTypeDef sClockSourceConfig = {0};
- TIM_MasterConfigTypeDef sMasterConfig = {0};
- TIM_OC_InitTypeDef sConfigOC = {0};
- /* USER CODE BEGIN TIM12_Init 1 */
- /* USER CODE END TIM12_Init 1 */
- htim12.Instance = TIM12;
- htim12.Init.Prescaler = 240-1;
- htim12.Init.CounterMode = TIM_COUNTERMODE_UP;
- htim12.Init.Period = 1000-1;
- htim12.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
- htim12.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_ENABLE;
- if (HAL_TIM_Base_Init(&htim12) != HAL_OK)
- {
- Error_Handler();
- }
- sClockSourceConfig.ClockSource = TIM_CLOCKSOURCE_INTERNAL;
- if (HAL_TIM_ConfigClockSource(&htim12, &sClockSourceConfig) != HAL_OK)
- {
- Error_Handler();
- }
- if (HAL_TIM_PWM_Init(&htim12) != HAL_OK)
- {
- Error_Handler();
- }
- sMasterConfig.MasterOutputTrigger = TIM_TRGO_OC1REF;
- sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
- if (HAL_TIMEx_MasterConfigSynchronization(&htim12, &sMasterConfig) != HAL_OK)
- {
- Error_Handler();
- }
- sConfigOC.OCMode = TIM_OCMODE_PWM1;
- sConfigOC.Pulse = (1000)/2-1;
- sConfigOC.OCPolarity = TIM_OCPOLARITY_LOW;
- sConfigOC.OCFastMode = TIM_OCFAST_DISABLE;
- if (HAL_TIM_PWM_ConfigChannel(&htim12, &sConfigOC, TIM_CHANNEL_1) != HAL_OK)
- {
- Error_Handler();
- }
- /* USER CODE BEGIN TIM12_Init 2 */
- /* USER CODE END TIM12_Init 2 */
- }
- void HAL_TIM_Base_MspInit(TIM_HandleTypeDef* tim_baseHandle)
- {
- if(tim_baseHandle->Instance==TIM12)
- {
- /* USER CODE BEGIN TIM12_MspInit 0 */
- /* USER CODE END TIM12_MspInit 0 */
- /* TIM12 clock enable */
- __HAL_RCC_TIM12_CLK_ENABLE();
- /* TIM12 interrupt Init */
- HAL_NVIC_SetPriority(TIM8_BRK_TIM12_IRQn, 0, 0);
- HAL_NVIC_EnableIRQ(TIM8_BRK_TIM12_IRQn);
- /* USER CODE BEGIN TIM12_MspInit 1 */
- /* USER CODE END TIM12_MspInit 1 */
- }
- }
复制代码
图为使用逻辑分析仪抓取单缓冲数据时刻,SPI总线数据
|