5
\$\begingroup\$

After setting up my project for a custom STM32F7 board which includes a FT2232H UART<->USB converter I got multiple problems when sending (and receiving data). The code I use is mostly generated by CubeMX and is at the end of the post.

First of all I can't get the stm to transmit at baud rates higher then the standard 115200, according to the datasheets both the FT2232H and the STM32F7 should be capable of at least 12M baud. For the FT2232H it's working as I send some characters from my terminal (USB side) and got the char back when I shorted the RX and TX pins on the FT2232H output side.

Second is that I can't call the sendUART() function multiple times in a row, why isn't the DMA Fifo used to store the stuff I want to send?

Also whats the right way to echo back all received data but make use of the fifo so no data is lost when it's not polled in time?

Maybe these are dumb questions but I already tried to find a solution on here and the rest of the internet but can't find any.

void MX_UART4_Init(void)
{

  huart4.Instance = UART4;
  huart4.Init.BaudRate = 115200;
  huart4.Init.WordLength = UART_WORDLENGTH_8B;
  huart4.Init.StopBits = UART_STOPBITS_1;
  huart4.Init.Parity = UART_PARITY_NONE;
  huart4.Init.Mode = UART_MODE_TX_RX;
  huart4.Init.HwFlowCtl = UART_HWCONTROL_NONE;
  huart4.Init.OverSampling = UART_OVERSAMPLING_16;
  huart4.Init.OneBitSampling = UART_ONE_BIT_SAMPLE_DISABLE;
  huart4.AdvancedInit.AdvFeatureInit = UART_ADVFEATURE_NO_INIT;
  if (HAL_UART_Init(&huart4) != HAL_OK)
  {
    _Error_Handler(__FILE__, __LINE__);
  }

}

void HAL_UART_MspInit(UART_HandleTypeDef* uartHandle)
{

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

  /* USER CODE END UART4_MspInit 0 */
    /* UART4 clock enable */
    __HAL_RCC_UART4_CLK_ENABLE();

    /**UART4 GPIO Configuration    
    PA0/WKUP     ------> UART4_TX
    PA1     ------> UART4_RX 
    */
    GPIO_InitStruct.Pin = GPIO_PIN_0|GPIO_PIN_1;
    GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
    GPIO_InitStruct.Pull = GPIO_PULLUP;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
    GPIO_InitStruct.Alternate = GPIO_AF8_UART4;
    HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);

    /* UART4 DMA Init */
    /* UART4_TX Init */
    hdma_uart4_tx.Instance = DMA1_Stream4;
    hdma_uart4_tx.Init.Channel = DMA_CHANNEL_4;
    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_MEDIUM;
    hdma_uart4_tx.Init.FIFOMode = DMA_FIFOMODE_ENABLE;
    hdma_uart4_tx.Init.FIFOThreshold = DMA_FIFO_THRESHOLD_FULL;
    hdma_uart4_tx.Init.MemBurst = DMA_MBURST_SINGLE;
    hdma_uart4_tx.Init.PeriphBurst = DMA_PBURST_SINGLE;
    if (HAL_DMA_Init(&hdma_uart4_tx) != HAL_OK)
    {
      _Error_Handler(__FILE__, __LINE__);
    }

    __HAL_LINKDMA(uartHandle,hdmatx,hdma_uart4_tx);

    /* UART4_RX Init */
    hdma_uart4_rx.Instance = DMA1_Stream2;
    hdma_uart4_rx.Init.Channel = DMA_CHANNEL_4;
    hdma_uart4_rx.Init.Direction = DMA_PERIPH_TO_MEMORY;
    hdma_uart4_rx.Init.PeriphInc = DMA_PINC_DISABLE;
    hdma_uart4_rx.Init.MemInc = DMA_MINC_ENABLE;
    hdma_uart4_rx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;
    hdma_uart4_rx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;
    hdma_uart4_rx.Init.Mode = DMA_NORMAL;
    hdma_uart4_rx.Init.Priority = DMA_PRIORITY_MEDIUM;
    hdma_uart4_rx.Init.FIFOMode = DMA_FIFOMODE_ENABLE;
    hdma_uart4_rx.Init.FIFOThreshold = DMA_FIFO_THRESHOLD_FULL;
    hdma_uart4_rx.Init.MemBurst = DMA_MBURST_SINGLE;
    hdma_uart4_rx.Init.PeriphBurst = DMA_PBURST_SINGLE;
    if (HAL_DMA_Init(&hdma_uart4_rx) != HAL_OK)
    {
      _Error_Handler(__FILE__, __LINE__);
    }

    __HAL_LINKDMA(uartHandle,hdmarx,hdma_uart4_rx);

  /* USER CODE BEGIN UART4_MspInit 1 */

  /* USER CODE END UART4_MspInit 1 */
  }
}

void HAL_UART_MspDeInit(UART_HandleTypeDef* uartHandle)
{

  if(uartHandle->Instance==UART4)
  {
  /* USER CODE BEGIN UART4_MspDeInit 0 */

  /* USER CODE END UART4_MspDeInit 0 */
    /* Peripheral clock disable */
    __HAL_RCC_UART4_CLK_DISABLE();

    /**UART4 GPIO Configuration    
    PA0/WKUP     ------> UART4_TX
    PA1     ------> UART4_RX 
    */
    HAL_GPIO_DeInit(GPIOA, GPIO_PIN_0|GPIO_PIN_1);

    /* UART4 DMA DeInit */
    HAL_DMA_DeInit(uartHandle->hdmatx);
    HAL_DMA_DeInit(uartHandle->hdmarx);
  /* USER CODE BEGIN UART4_MspDeInit 1 */

  /* USER CODE END UART4_MspDeInit 1 */
  }
} 

/* USER CODE BEGIN 1 */
void sendUART(char msg[]){
    //HAL_UART_Transmit(&huart4,(uint8_t *) msg, strlen(msg),10000);
    HAL_UART_Transmit_DMA(&huart4,(uint8_t *) msg, strlen(msg));
}

void echo(){
    if(HAL_UART_Receive_DMA(&huart4, (uint8_t *)aRxBuffer, RXBUFFERSIZE) != HAL_OK){}
    else if(HAL_UART_Transmit_DMA(&huart4, (uint8_t*)aRxBuffer, RXBUFFERSIZE)!= HAL_OK){
    }
}
\$\endgroup\$

1 Answer 1

6
\$\begingroup\$

First of all I can't get the stm to transmit at baud rates higher then the standard 115200, according to the datasheets both the FT2232H and the STM32F7 should be capable of at least 12M baud.

The hardware supports speeds up to 27 Mbit (well, you haven't told your part number, I'm looking at the F756 datasheet), but according to stm32f7xx_hal_uart.h, HAL won't accept a speed above 9M

#define IS_UART_BAUDRATE(BAUDRATE) ((BAUDRATE) < 9000001)

Moreover, it depends on the system clock speed, in the default configuration, when you don't touch the Clock Configuration tab in STM32CubeMX, everything operates on the 16 MHz internal HSI clock. That means at most 1 Mbit while you are using UART_OVERSAMPLING_16, or twice that if you switch to UART_OVERSAMPLING_8 (but then you'd lose noise detection).

Second is that I can't call the sendUART() function multiple times in a row, why isn't the DMA Fifo used to store the stuff I want to send?

Although there is a 16 byte DMA FIFO, it's not accessible to the software. There is no way to just append some more data to an ongoing DMA transfer. HAL does nothing but starts a DMA transfer from the buffer address supplied by the caller.

You have to wait until the transfer is finished, or suspend DMA, and still wait until the FIFO is empty. You can of course allocate a buffer yourself, add data as it comes, and restart DMA whenever it finishes and there is new data in the buffer.

Also whats the right way to echo back all received data but make use of the fifo so no data is lost when it's not polled in time?

It looks like to me, that you can't have both DMA and interrupts on every received character. At least, the ISR status register value would be useless, and the interrupt handler won't be able to decide what to do. Reading it could even interfere with the DMA transfer. Therefore, you must choose one.

Using DMA to put the data in a buffer (or two), you can then poll the transfer counter regularly in the idle loop or a timer interrupt. There won't be an immediate response, but it'd perhaps not matter at all, because the USB interface would incur some delay too.

\$\endgroup\$
2
  • \$\begingroup\$ Thanks for the answer. I configured the clocks and the UART is running on the 200Mhz SYSCLK so according to CubeMX there should be a theoretical max. baud rate of 12.5M with oversampling set to 16 samples. \$\endgroup\$
    – JaneDoe
    Sep 22, 2017 at 8:36
  • \$\begingroup\$ If you set the UART clock source to the 200MHz SYSCLK (Where do you do it? It's not in the code above), then you'd get 12.5M, right, but that's not exatly 12M, what the FTDI part is running on. There is a difference of 4.167%, coupled with the inaccuracy of the HSI oscillator it can work, when everything else is perfect (controller is not too warm, signals are sharp and noise-free), but I'd try it with 192 MHz to get a better match. \$\endgroup\$ Sep 25, 2017 at 6:48

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.