Почему HAL_UART_Transmit_DMA () не работает для последовательных портов на Nucleo F103RB? - PullRequest
0 голосов
/ 10 января 2020

У меня есть следующий код, большая часть которого генерируется STM32CubeMX. (Я исключил огромное количество сгенерированных комментариев, чтобы сделать его читаемым.)

volatile int txDoneFlag = 0;

void HAL_UART_TxCpltCallback(UART_HandleTypeDef *huart){
    txDoneFlag = 1;
}

int main(void)
{
  HAL_Init();
  SystemClock_Config();
  MX_GPIO_Init();
  MX_USART2_UART_Init();
  MX_USART1_UART_Init();
  MX_DMA_Init();
  MX_USART3_UART_Init();

  while (1)
  {
    LD2_GPIO_Port->BSRR = (uint32_t)LD2_Pin;
    HAL_UART_Transmit_DMA(&huart1, (uint8_t*)"1: on          \n", 16);
    while(!txDoneFlag);
    txDoneFlag = 0;
    HAL_UART_Transmit_DMA(&huart2, (uint8_t*)"2: on          \n", 16);
    while(!txDoneFlag);
    txDoneFlag = 0;
    HAL_UART_Transmit_DMA(&huart3, (uint8_t*)"3: on          \n", 16);
    while(!txDoneFlag);
    txDoneFlag = 0;
    HAL_Delay(100);
    LD2_GPIO_Port->BSRR = (uint32_t)LD2_Pin << 16U;
    HAL_UART_Transmit_DMA(&huart1, (uint8_t*)"1: off         \n", 16);
    while(!txDoneFlag);
    txDoneFlag = 0;
    HAL_UART_Transmit_DMA(&huart2, (uint8_t*)"2: off         \n", 16);
    while(!txDoneFlag);
    txDoneFlag = 0;
    HAL_UART_Transmit_DMA(&huart3, (uint8_t*)"3: off         \n", 16);
    while(!txDoneFlag);
    txDoneFlag = 0;
    HAL_Delay(100);
  }
}

DMA был настроен в генераторе STM32CubeMX, поэтому он должен быть правильным.

Когда я запустить этот код, он застревает в бесконечном l oop в первом while(!txDoneFlag);, подразумевая, что HAL_UART_TxCpltCallback() никогда не вызывается.

Это заставляет меня думать, что мне нужно сделать что-то еще, чтобы включить DMA.

Как заставить HAL_UART_Transmit_DMA() работать?

Я уже пытался изменить порядок сгенерированных вызовов MX..., чтобы MX_DMA_Init() вызывался до ...UART_Init() s.

-

Обновление: запрошенный код. Все три функции MX_USARTn_UART_Init() имеют идентичные тела (за исключением номера UART.

/**
  * @brief USART3 Initialization Function
  * @param None
  * @retval None
  */
static void MX_USART3_UART_Init(void)
{

  /* USER CODE BEGIN USART3_Init 0 */

  /* USER CODE END USART3_Init 0 */

  /* USER CODE BEGIN USART3_Init 1 */

  /* USER CODE END USART3_Init 1 */
  huart3.Instance = USART3;
  huart3.Init.BaudRate = 115200;
  huart3.Init.WordLength = UART_WORDLENGTH_8B;
  huart3.Init.StopBits = UART_STOPBITS_1;
  huart3.Init.Parity = UART_PARITY_NONE;
  huart3.Init.Mode = UART_MODE_TX_RX;
  huart3.Init.HwFlowCtl = UART_HWCONTROL_NONE;
  huart3.Init.OverSampling = UART_OVERSAMPLING_16;
  if (HAL_UART_Init(&huart3) != HAL_OK)
  {
    Error_Handler();
  }
  /* USER CODE BEGIN USART3_Init 2 */

  /* USER CODE END USART3_Init 2 */

}

/** 
  * Enable DMA controller clock
  */
static void MX_DMA_Init(void) 
{

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

  /* DMA interrupt init */
  /* DMA1_Channel2_IRQn interrupt configuration */
  HAL_NVIC_SetPriority(DMA1_Channel2_IRQn, 0, 0);
  HAL_NVIC_EnableIRQ(DMA1_Channel2_IRQn);
  /* DMA1_Channel3_IRQn interrupt configuration */
  HAL_NVIC_SetPriority(DMA1_Channel3_IRQn, 0, 0);
  HAL_NVIC_EnableIRQ(DMA1_Channel3_IRQn);
  /* DMA1_Channel4_IRQn interrupt configuration */
  HAL_NVIC_SetPriority(DMA1_Channel4_IRQn, 0, 0);
  HAL_NVIC_EnableIRQ(DMA1_Channel4_IRQn);
  /* DMA1_Channel5_IRQn interrupt configuration */
  HAL_NVIC_SetPriority(DMA1_Channel5_IRQn, 0, 0);
  HAL_NVIC_EnableIRQ(DMA1_Channel5_IRQn);
  /* DMA1_Channel6_IRQn interrupt configuration */
  HAL_NVIC_SetPriority(DMA1_Channel6_IRQn, 0, 0);
  HAL_NVIC_EnableIRQ(DMA1_Channel6_IRQn);
  /* DMA1_Channel7_IRQn interrupt configuration */
  HAL_NVIC_SetPriority(DMA1_Channel7_IRQn, 0, 0);
  HAL_NVIC_EnableIRQ(DMA1_Channel7_IRQn);

}

1 Ответ

1 голос
/ 10 января 2020

Убедитесь, что в файле STM32Cube io c указано, что глобальное прерывание для используемого вами периферийного устройства UART проверено для всех трех, некоторые IRQ объединены в зависимости от микросхемы.

Они расположены в вашем файл stm32F1xx_it. c. При необходимости установите точки останова и убедитесь, что эти прерывания срабатывают. Внутри ISR будет место, где вы можете увидеть, какой обратный вызов вызывается, если он вообще существует (если отсутствует какая-либо конфигурация). Как ваша конфигурация выглядит в вашем MX_DMA_Init () и UART_INIT ()? Вы можете поделиться этим? В противном случае вы можете убедиться, что все подключено самостоятельно. Хотя я могу предостеречь вас от использования этого метода с DMA, весь смысл DMA в том, чтобы иметь возможность выполнять другие инструкции на CPU, в то время как DMA связывается с памятью и обрабатывает операции с памятью.

Со всеми три периферийных устройства UART, отправляющих сообщения, и DMA, вы должны иметь возможность использовать несколько флагов в обратных вызовах и использовать операторы вместо того, чтобы блокировать их в течение некоторого времени l oop.

Обратные вызовы в HAL слабо типизированы, поэтому вам нужно убедиться, что у символа есть путь к правильному определению ie .. extern или четкий путь включения, чтобы правильный адрес памяти был назначен вашему обратному вызову в вашем главном файле здесь. Таким образом, когда обратный вызов выдается из ISR, ваш обратный вызов в вашем основном файле будет тем, к которому он обращается.

...