Перейти к содержанию
    

HAL+UART+DMA

Доброго всем времени суток!

Контроллер stm32f107, проект собран в Cube, пытаюсь сделать отправку по USART с DMA.

Инициализация:

void MX_UART4_Init(void)
{

  huart4.Instance = UART4;
  huart4.Init.BaudRate = 9600;
  huart4.Init.WordLength = UART_WORDLENGTH_8B;
  huart4.Init.StopBits = UART_STOPBITS_1;
  huart4.Init.Parity = UART_PARITY_NONE;
  huart4.Init.Mode = UART_MODE_TX;
  huart4.Init.HwFlowCtl = UART_HWCONTROL_NONE;
  huart4.Init.OverSampling = UART_OVERSAMPLING_16;
  HAL_UART_Init(&huart4);

}

void MX_DMA_Init(void) 
{
  /* DMA controller clock enable */
  __HAL_RCC_DMA2_CLK_ENABLE();

  /* DMA interrupt init */
  HAL_NVIC_SetPriority(DMA2_Channel5_IRQn, 0, 0);
  HAL_NVIC_EnableIRQ(DMA2_Channel5_IRQn);

}

Связка USART<->DMA:

void HAL_UART_MspInit(UART_HandleTypeDef* huart)
{

  GPIO_InitTypeDef GPIO_InitStruct;
  if(huart->Instance==UART4)
  {
  /* USER CODE BEGIN UART4_MspInit 0 */

  /* USER CODE END UART4_MspInit 0 */
    /* Peripheral clock enable */
    __UART4_CLK_ENABLE();
  
    /**UART4 GPIO Configuration    
    PC10     ------> UART4_TX
    PC11     ------> UART4_RX 
    */
    GPIO_InitStruct.Pin = GPIO_PIN_10;
    GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
    GPIO_InitStruct.Speed = GPIO_SPEED_LOW;
    HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);

    GPIO_InitStruct.Pin = GPIO_PIN_11;
    GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
    GPIO_InitStruct.Pull = GPIO_NOPULL;
    HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);

    /* Peripheral DMA init*/
  
    hdma_uart4_tx.Instance = DMA2_Channel5;
    hdma_uart4_tx.Init.Direction = DMA_MEMORY_TO_PERIPH;
    hdma_uart4_tx.Init.PeriphInc = DMA_PINC_DISABLE;
    hdma_uart4_tx.Init.MemInc = DMA_MINC_ENABLE;
    hdma_uart4_tx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;
    hdma_uart4_tx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;
    hdma_uart4_tx.Init.Mode = DMA_NORMAL;
    hdma_uart4_tx.Init.Priority = DMA_PRIORITY_LOW;
    HAL_DMA_Init(&hdma_uart4_tx);

    __HAL_LINKDMA(huart,hdmatx,hdma_uart4_tx);

  /* USER CODE BEGIN UART4_MspInit 1 */

  /* USER CODE END UART4_MspInit 1 */
  }

}

Посылка данных:

  uint8_t data[8] = {0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08};
  
  while (1)
  {
      HAL_UART_Transmit_DMA(&huart4, data, 8);
      HAL_Delay(500);
  }

Но отправляется только первая посылка. Далее huart4.State переходит в состояние HAL_UART_STATE_BUSY_TX.

Пробовал делать отправку без HAL (регистрами) - все работает. Хочется разобраться с hal и понять что делаю не так.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Но отправляется только первая посылка. Далее huart4.State переходит в состояние HAL_UART_STATE_BUSY_TX.

Пробовал делать отправку без HAL (регистрами) - все работает. Хочется разобраться с hal и понять что делаю не так.

Первая посылка - это сколько байт?

А что у Вас делает обработчик прерываний? И зачем тут прерывания?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Первая посылка - это сколько байт?

А что у Вас делает обработчик прерываний? И зачем тут прерывания?

Первая посылка - это все 8 байт (data[8]). Про прерывания был мой второй вопрос ;) Дело в том, что при конфигурации DMA в Cube галка "DMA channel 5 global interrupt" не снимается. Мне прерывания не нужны. Контроль отправки посылки можно делать опросом бита TCIF5 регистра DMA2->ISR.

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Первая посылка - это все 8 байт (data[8]). Про прерывания был мой второй вопрос ;) Дело в том, что при конфигурации DMA в Cube галка "DMA channel 5 global interrupt" не снимается. Мне прерывания не нужны. Контроль отправки посылки можно делать опросом бита TCIF5 регистра DMA2->ISR.

Да, это у меня тоже после обновления КУБа возникло с галками... Пришлось откатиться на старую версию. Или писать callback, что мне не нужно было совсем... но работало.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Да, это у меня тоже после обновления КУБа возникло с галками... Пришлось откатиться на старую версию. Или писать callback, что мне не нужно было совсем... но работало.

А причем здесь прерывания? У меня обработчик прерывания пустой, но huart4.State переходит в состояние HAL_UART_STATE_BUSY_TX. Мне нужно State менять на Ready в обработчике прерывания?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Вчера CMSIS, сегодня HAL, завтра еще что-нибудь придумают.. в итоге сделал все через регистры - быстро, красиво и универсально. Все работает, тему можно считать закрытой.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Вдруг кто еще столкнется с этим.

Вот на форуме stm нашли в чем причина

 

Если в кратце, то обработчик прерывания по завершению передачи от DMA (UART_DMATransmitCplt) не восстанавливает состояние уарта (huart->State).

что бы все работало без правки исходников HAL надо определить штатный обработчик прерывания UART который и вернет состояние в HAL_UART_STATE_READY.

void USARTx_IRQHandler(void)
{
HAL_UART_IRQHandler(&UartHandle);
}

Альтернативно, если прерывания от UART не нужны, то можно изменить саму UART_DMATransmitCplt

Вот как это предложили на форуме st.

 

static void UART_DMATransmitCplt(DMA_HandleTypeDef *hdma)    
{
  UART_HandleTypeDef* huart = ( UART_HandleTypeDef* )((DMA_HandleTypeDef* )hdma)->Parent;
  /* DMA Normal mode*/
  if ( HAL_IS_BIT_CLR(hdma->Instance->CCR, DMA_CCR_CIRC) )
{
    huart->TxXferCount = 0;
    
    /* Disable the DMA transfer for transmit request by setting the DMAT bit
       in the UART CR3 register */
    CLEAR_BIT(huart->Instance->CR3, USART_CR3_DMAT);


    /* Enable the UART Transmit Complete Interrupt */   
    __HAL_UART_ENABLE_IT(huart, UART_IT_TC);
        huart->State=HAL_UART_STATE_READY;  //<--- i add this line to solve the //problem
  }
  /* DMA Circular mode */
  else
  {
    HAL_UART_TxCpltCallback(huart);
  }
}

 

В описании на драйверы HAL (я смотрел Description of STM32F0xx HAL drivers rev 1) про это ничего нет.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

В соседней теме, где нас обозвали теоретиками мы как раз обсуждали этот вопрос.

 

Дело в том, что DMA начинает слать следующий байт по сигналу инициириванному флагом буфер пуст, но по логике статус должен стать равным HAL_UART_STATE_READY после пересылки байта. В предыдущей версии куба внутри обработчика прерывания DMA в цикле крутились все время пока передается последний байт. В более новой версии поступили иначе. Разрешили прерывание по UART_IT_TC и перенесли код в соответствующий обработчик прерывания. Вот обработчик для 429го процессора, а все детали вы можете посмотерть в соседней теме.

 

/**
  * @brief  Wraps up transmission in non blocking mode.
  * @param  huart: pointer to a UART_HandleTypeDef structure that contains
  *                the configuration information for the specified UART module.
  * @retval HAL status
  */
static HAL_StatusTypeDef UART_EndTransmit_IT(UART_HandleTypeDef *huart)
{
  /* Disable the UART Transmit Complete Interrupt */    
  __HAL_UART_DISABLE_IT(huart, UART_IT_TC);
  
  /* Check if a receive process is ongoing or not */
  if(huart->State == HAL_UART_STATE_BUSY_TX_RX) 
  {
    huart->State = HAL_UART_STATE_BUSY_RX;
  }
  else
  {
    /* Disable the UART Parity Error Interrupt */
    __HAL_UART_DISABLE_IT(huart, UART_IT_PE);

    /* Disable the UART Error Interrupt: (Frame error, noise error, overrun error) */
    __HAL_UART_DISABLE_IT(huart, UART_IT_ERR);

    huart->State = HAL_UART_STATE_READY;
  }
  
  HAL_UART_TxCpltCallback(huart);
  
  return HAL_OK;
}

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Привет всем. Аналогичная проблемма. Советы выше не помогают.

Не выходит из while...

Как такое может быть?

 

image.jpg

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.

Гость
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...