AnsweredAssumed Answered

stm32f415 USB vs. USART1

Question asked by Daniel Glasser on May 19, 2017
Latest reply on Aug 11, 2017 by Tyler Gilbert

I have a custom board that uses an STM32F415RGT6.  It has USB_OTG_FS_DP on pin 45 (PA12), USB_OTG_FS_DM on pin 44 (PA11), USART1_RX on pin 42 (PA10), USART1_TX on pin 43 (PA9), plus lots of other connections.

 

I created a project using STM32CubeMX (whatever the release before 4.21.0 was), and "Firmware Package for Family STM32F4" v1.15.0.

 

  • USART1 is configured as Asynchronous, 9600 bit/s, 8 bits, no parity, 1 stop bit, hardware flow control disabled, Async, DMA (circular) for Rx, DMA (normal) for Tx, priority low for both Rx and Tx DMA, USART1 global interrupt and both DMA stream interrupts enabled.  Nothing out of the ordinary.
  • USB_OTG_FS is configured for device only, CDC (virtual com port), global interrupt enabled, no DMA.  Again, nothing out of the ordinary.

 

Plugging the USB connection into a host works fine; the device enumerates and I can open the virtual com port from a terminal emulator and my board can receive and send data over the USB.  So far so good.

My board has a data acquisition chip connected to USART1 that starts sending data to the STM32 when it comes out of reset.  The data is received, my firmware on the STM32 handles it and sends data to the host over the USB connection.  Still good, this is working as expected.

 

The problem is that when my software/firmware on the STM32 sends data to the on-board data acquisition device, PA12 (USB_OTG_FS_DP), which is carrying on the USB connection, is pulled to ground, causing the USB connection to reset. I tried this on 3 copies of the board, same thing each time.  In order to rule out some sort of a short or other oddment on the card, my hardware tech lifted the USART1_TX leg so that it isn't connected to anything on the board, and we still see PA12 go low when the software tries to send data on USART1.

 

Here is the init code extracted from the STM32CubeMX generated "usart.c" for initializing USART1:

/* USART1 init function */  void MX_USART1_UART_Init(void) {   huart1.Instance = USART1;   huart1.Init.BaudRate = 9600;   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;   if (HAL_UART_Init(&huart1) != HAL_OK)   {     Error_Handler();   } }

Here is the code from "HAL_UART_MspInit()" in the same file that deals with USART1:

  else if(uartHandle->Instance==USART1)   {   /* USER CODE BEGIN USART1_MspInit 0 */    /* USER CODE END USART1_MspInit 0 */     /* Peripheral clock enable */     __HAL_RCC_USART1_CLK_ENABLE();        /**USART1 GPIO Configuration         PA9     ------> USART1_TX     PA10     ------> USART1_RX      */     GPIO_InitStruct.Pin = USART1_RX_Pin|USART1_TX_Pin;     GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;     GPIO_InitStruct.Pull = GPIO_PULLUP;     GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;     GPIO_InitStruct.Alternate = GPIO_AF7_USART1;     HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);      /* Peripheral DMA init*/        hdma_usart1_rx.Instance = DMA2_Stream2;     hdma_usart1_rx.Init.Channel = DMA_CHANNEL_4;     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_CIRCULAR;     hdma_usart1_rx.Init.Priority = DMA_PRIORITY_LOW;     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);      hdma_usart1_tx.Instance = DMA2_Stream7;     hdma_usart1_tx.Init.Channel = DMA_CHANNEL_4;     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_LOW;     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);      /* Peripheral interrupt init */     HAL_NVIC_SetPriority(USART1_IRQn, 5, 0);     HAL_NVIC_EnableIRQ(USART1_IRQn);   /* USER CODE BEGIN USART1_MspInit 1 */    /* USER CODE END USART1_MspInit 1 */   }

I have not edited this particular code since it was generated by STM32CubeMX, and I see nothing wrong with it so far as how it configures the GPIOs.

 

I am surprised by the behavior I'm seeing, and have not seen anyone else complaining about this, so it must be something with this configuration that causes this undesired behavior.  I remain at a loss to explain it, and have not figured out how to work around it other than to add an external USB to serial chip and connect USART3 to that for the host data connection.  I don't like that solution, but for the prototype, that's what we've done.

 

Any suggestions for a solution are appreciated.

usb_otg_fs stm32f4 usart 

Outcomes