硬汉嵌入式论坛

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

[UART] 使用串口DMA,初始化DMA中断之后 程序就直接卡死了

[复制链接]

2

主题

3

回帖

9

积分

新手上路

积分
9
发表于 2024-12-29 17:44:15 | 显示全部楼层 |阅读模式
请各位大佬解答一下看看有没有类似的问题
这边调试其他的功能,下载程序之后还是没有问题的 隔一段时间时候程序就起不来了,但是屏蔽了MX_DMA_Init就没有问题了,DMA是用于串口DMA空闲中断的,感觉去掉了也没有影响功能,只是不明白为什么突然不行了,仿真跑到的地方截图如下:
主要的代码贴图以及代码如下:

void MX_DMA_Init(void)
{

  /* DMA controller clock enable */
  __HAL_RCC_DMA1_CLK_ENABLE();

  /* DMA interrupt init */
  /* DMA1_Stream0_IRQn interrupt configuration */
  HAL_NVIC_SetPriority(DMA1_Stream0_IRQn, 6, 0);
  HAL_NVIC_EnableIRQ(DMA1_Stream0_IRQn);
  /* DMA1_Stream1_IRQn interrupt configuration */
  HAL_NVIC_SetPriority(DMA1_Stream1_IRQn, 5, 0);
  HAL_NVIC_EnableIRQ(DMA1_Stream1_IRQn);

}

void MX_USART1_UART_Init(void)
{
  huart1.Instance = USART1;
  huart1.Init.BaudRate = 1500000;
  huart1.Init.WordLength = UART_WORDLENGTH_8B;
  huart1.Init.StopBits = UART_STOPBITS_1;
  huart1.Init.Parity = UART_PARITY_NONE;
  huart1.Init.Mode = UART_MODE_TX_RX;
  huart1.Init.HwFlowCtl = UART_HWCONTROL_NONE;
  huart1.Init.OverSampling = UART_OVERSAMPLING_16;
  huart1.Init.OneBitSampling = UART_ONE_BIT_SAMPLE_DISABLE;
  huart1.Init.ClockPrescaler = UART_PRESCALER_DIV1;
  huart1.AdvancedInit.AdvFeatureInit = UART_ADVFEATURE_NO_INIT;
  if (HAL_UART_Init(&huart1) != HAL_OK)
  {
    Error_Handler();
  }
  if (HAL_UARTEx_SetTxFifoThreshold(&huart1, UART_TXFIFO_THRESHOLD_1_8) != HAL_OK)
  {
    Error_Handler();
  }
  if (HAL_UARTEx_SetRxFifoThreshold(&huart1, UART_RXFIFO_THRESHOLD_1_8) != HAL_OK)
  {
    Error_Handler();
  }
  if (HAL_UARTEx_DisableFifoMode(&huart1) != HAL_OK)
  {
    Error_Handler();
  }
        HAL_UARTEx_ReceiveToIdle_DMA(&huart1, UART_RECV_RXBUF, UART_BUF_SIZE);
}

void HAL_UART_MspInit(UART_HandleTypeDef* uartHandle)
{

  GPIO_InitTypeDef GPIO_InitStruct = {0};
  RCC_PeriphCLKInitTypeDef PeriphClkInitStruct = {0};
  if(uartHandle->Instance==USART1)
  {
    PeriphClkInitStruct.PeriphClockSelection = RCC_PERIPHCLK_USART1;
    PeriphClkInitStruct.Usart16ClockSelection = RCC_USART16CLKSOURCE_D2PCLK2;
    if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInitStruct) != HAL_OK)
    {
      Error_Handler();
    }
    __HAL_RCC_USART1_CLK_ENABLE();

    __HAL_RCC_GPIOA_CLK_ENABLE();
    GPIO_InitStruct.Pin = GPIO_PIN_9|GPIO_PIN_10;
    GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
    GPIO_InitStruct.Pull = GPIO_NOPULL;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
    GPIO_InitStruct.Alternate = GPIO_AF7_USART1;
    HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
    hdma_usart1_tx.Instance = DMA1_Stream0;
    hdma_usart1_tx.Init.Request = DMA_REQUEST_USART1_TX;
    hdma_usart1_tx.Init.Direction = DMA_MEMORY_TO_PERIPH;
    hdma_usart1_tx.Init.PeriphInc = DMA_PINC_DISABLE;
    hdma_usart1_tx.Init.MemInc = DMA_MINC_ENABLE;
    hdma_usart1_tx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;
    hdma_usart1_tx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;
    hdma_usart1_tx.Init.Mode = DMA_NORMAL;
    hdma_usart1_tx.Init.Priority = DMA_PRIORITY_MEDIUM;
    hdma_usart1_tx.Init.FIFOMode = DMA_FIFOMODE_DISABLE;
    if (HAL_DMA_Init(&hdma_usart1_tx) != HAL_OK)
    {
      Error_Handler();
    }
    __HAL_LINKDMA(uartHandle,hdmatx,hdma_usart1_tx);
    hdma_usart1_rx.Instance = DMA1_Stream1;
    hdma_usart1_rx.Init.Request = DMA_REQUEST_USART1_RX;
    hdma_usart1_rx.Init.Direction = DMA_PERIPH_TO_MEMORY;
    hdma_usart1_rx.Init.PeriphInc = DMA_PINC_DISABLE;
    hdma_usart1_rx.Init.MemInc = DMA_MINC_ENABLE;
    hdma_usart1_rx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;
    hdma_usart1_rx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;
    hdma_usart1_rx.Init.Mode = DMA_NORMAL;
    hdma_usart1_rx.Init.Priority = DMA_PRIORITY_MEDIUM;
    hdma_usart1_rx.Init.FIFOMode = DMA_FIFOMODE_DISABLE;
    if (HAL_DMA_Init(&hdma_usart1_rx) != HAL_OK)
    {
      Error_Handler();
    }
    __HAL_LINKDMA(uartHandle,hdmarx,hdma_usart1_rx);
    HAL_NVIC_SetPriority(USART1_IRQn, 5, 0);
    HAL_NVIC_EnableIRQ(USART1_IRQn);

  }
}

void HAL_UART_MspDeInit(UART_HandleTypeDef* uartHandle)
{

  if(uartHandle->Instance==USART1)
  {
    __HAL_RCC_USART1_CLK_DISABLE();
    HAL_GPIO_DeInit(GPIOA, GPIO_PIN_9|GPIO_PIN_10);
               
    HAL_DMA_DeInit(uartHandle->hdmatx);
    HAL_DMA_DeInit(uartHandle->hdmarx);

    HAL_NVIC_DisableIRQ(USART1_IRQn);
  }
}

void HAL_UART_TxCpltCallback(UART_HandleTypeDef *huart)
{

}
//串口接收完成回调函数
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{

}
//串口发生错误回调函数
void HAL_UART_ErrorCallback(UART_HandleTypeDef *huart)
{

}
//串口接收事件回调函数 如果是空闲中断触发ReceptionType = HAL_UART_RECEPTION_STANDARD
void HAL_UARTEx_RxEventCallback(UART_HandleTypeDef *huart, uint16_t Size)
{
    //HAL_UART_RECEPTION_TOIDLE 说明是DMA接收完成,或者半传输完成
    if (huart->ReceptionType == HAL_UART_RECEPTION_TOIDLE)
    {
        
    }
   
    //HAL_UART_RECEPTION_STANDARD 说明是空闲中断触发的接收事件
    if (huart->ReceptionType == HAL_UART_RECEPTION_STANDARD)
    {
        SCB_InvalidateDCache_by_Addr((uint32_t *)UART_RECV_RXBUF, uart1rx_data.rx_datalen);
        memcpy(UART_RECV_ShellBUF, UART_RECV_RXBUF, uart1rx_data.rx_datalen);
        SCB_CleanDCache_by_Addr((uint32_t *)UART_RECV_ShellBUF, uart1rx_data.rx_datalen); // 打开cache使用的方式 特别是Dcache
                                shellHandler(&shell, (char)UART_RECV_ShellBUF[0]);
                                uart1rx_data.rx_dataflag = 1;
                                uart1rx_data.rx_datalen = Size;

    }
}

void DMA1_Stream0_IRQHandler(void)
{
  HAL_DMA_IRQHandler(&hdma_usart1_tx);
}

/**
  * @brief This function handles DMA1 stream1 global interrupt.
  */
void DMA1_Stream1_IRQHandler(void)
{
  HAL_DMA_IRQHandler(&hdma_usart1_rx);
}

/**
  * @brief This function handles USART1 global interrupt.
  */
void USART1_IRQHandler(void)
{
  /* USER CODE BEGIN USART1_IRQn 0 */

  /* USER CODE END USART1_IRQn 0 */
  HAL_UART_IRQHandler(&huart1);
        HAL_UARTEx_ReceiveToIdle_DMA(&huart1,UART_RECV_RXBUF,UART_BUF_SIZE);        //重新开启串口空闲中断和DMA接收,一定要放在这里
  /* USER CODE BEGIN USART1_IRQn 1 */

  /* USER CODE END USART1_IRQn 1 */
}

去掉MX_DMA_Init是没有问题的 功能也不不影响 但是不知道为什么不行呢  这个有一个boot程序的 在boot下是没有问题的,有遇到类似的问题可以分析一下呢


1.jpg
2.jpg
回复

使用道具 举报

1万

主题

7万

回帖

11万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
115488
QQ
发表于 2024-12-30 06:40:38 | 显示全部楼层
这个中断
void USART1_IRQHandler(void)
{
  /* USER CODE BEGIN USART1_IRQn 0 */

  /* USER CODE END USART1_IRQn 0 */
  HAL_UART_IRQHandler(&huart1);
        HAL_UARTEx_ReceiveToIdle_DMA(&huart1,UART_RECV_RXBUF,UART_BUF_SIZE);        //重新开启串口空闲中断和DMA接收,一定要放在这里
  /* USER CODE BEGIN USART1_IRQn 1 */

  /* USER CODE END USART1_IRQn 1 */
}

这个中断处理有问题,这种情况成了各种发送,发送空,接收,错误等中断不都重新启动DMA了。

应该通过回调消息处理,使用函数HAL_UARTEx_ReceiveToIdle_DMA做超时接收整理:
1、半DMA传输完成中断UART_DMARxHalfCplt     调用  HAL_UARTEx_RxEventCallback,标识继续为HAL_UART_RECEPTION_TOIDLE
2、DMA传输完成中断UART_DMAReceiveCplt       调用   HAL_UARTEx_RxEventCallback,标识继续为HAL_UART_RECEPTION_TOIDLE
3、如果传输期间触发了空闲,DMA又没有传输完成,调用串口中断HAL_UART_IRQHandler,空闲标识处理的HAL_UARTEx_RxEventCallback,并设置HAL_UART_RECEPTION_STANDARD
回复

使用道具 举报

2

主题

3

回帖

9

积分

新手上路

积分
9
 楼主| 发表于 2024-12-31 02:09:18 | 显示全部楼层
好的 感谢感谢  我这边修改看看
回复

使用道具 举报

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

本版积分规则

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

GMT+8, 2025-4-28 16:33 , Processed in 0.219200 second(s), 28 queries .

Powered by Discuz! X3.4 Licensed

Copyright © 2001-2023, Tencent Cloud.

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