cancel
Showing results for 
Search instead for 
Did you mean: 

UART DMA Initialization problem while jumping from bootloader to application code

Ashvajit-CC
Associate II

Hi, I am facing an issue on STM32F469 where UART is not initialized with DMA properly if I dont add  some delay around 300ms as show in my initialization. 

/* Reset of all peripherals, Initializes the Flash interface and the Systick. */
  HAL_Init();

  /* USER CODE BEGIN Init */

  /* USER CODE END Init */

  /* Configure the system clock */
  SystemClock_Config();

  /* USER CODE BEGIN SysInit */

  /* USER CODE END SysInit */

  /* Initialize all configured peripherals */
  MX_GPIO_Init();
  MX_DMA_Init();
  MX_ADC1_Init();
  MX_ADC3_Init();
  MX_I2C1_Init();
  MX_RTC_Init();
  MX_SPI2_Init();
  MX_TIM1_Init();
  MX_TIM2_Init();
  MX_TIM5_Init();
  MX_SPI3_Init();
  MX_UART8_Init();
  //MX_USART2_UART_Init();
  MX_RNG_Init();

  MX_USB_DEVICE_Init();
  /* USER CODE BEGIN 2 */
  HAL_GPIO_WritePin(EN_3V3_SW_GPIO_Port, EN_3V3_SW_Pin, GPIO_PIN_SET);
  HAL_Delay(300);
  Serial_Receive();

This serial receive function

void    Serial_Receive(void)
{
    HAL_UARTEx_ReceiveToIdle_DMA(&huart8,Serial_RX_Buffer, SERIAL_RX_BUFF_SIZE);
    __HAL_DMA_DISABLE_IT(&hdma_uart8_rx,DMA_IT_HT);
}

 Here's my UART Initialization code

/* UART8 init function */
void MX_UART8_Init(void)
{

  /* USER CODE BEGIN UART8_Init 0 */

  /* USER CODE END UART8_Init 0 */

  /* USER CODE BEGIN UART8_Init 1 */

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

  /* USER CODE END UART8_Init 2 */
}
void HAL_UART_MspInit(UART_HandleTypeDef* uartHandle)
{

  GPIO_InitTypeDef GPIO_InitStruct = {0};
  if(uartHandle->Instance==UART8)
  {
  /* USER CODE BEGIN UART8_MspInit 0 */

  /* USER CODE END UART8_MspInit 0 */
    /* UART8 clock enable */
    __HAL_RCC_UART8_CLK_ENABLE();

    __HAL_RCC_GPIOE_CLK_ENABLE();
    /**UART8 GPIO Configuration
    PE1     ------> UART8_TX
    PE0     ------> UART8_RX
    */
    GPIO_InitStruct.Pin = RF_UART8_TX_Pin|RF_UART8_RX_Pin;
    GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
    GPIO_InitStruct.Pull = GPIO_NOPULL;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
    GPIO_InitStruct.Alternate = GPIO_AF8_UART8;
    HAL_GPIO_Init(GPIOE, &GPIO_InitStruct);

    /* UART8 DMA Init */
    /* UART8_RX Init */
    hdma_uart8_rx.Instance = DMA1_Stream6;
    hdma_uart8_rx.Init.Channel = DMA_CHANNEL_5;
    hdma_uart8_rx.Init.Direction = DMA_PERIPH_TO_MEMORY;
    hdma_uart8_rx.Init.PeriphInc = DMA_PINC_DISABLE;
    hdma_uart8_rx.Init.MemInc = DMA_MINC_ENABLE;
    hdma_uart8_rx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;
    hdma_uart8_rx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;
    hdma_uart8_rx.Init.Mode = DMA_NORMAL;
    hdma_uart8_rx.Init.Priority = DMA_PRIORITY_LOW;
    hdma_uart8_rx.Init.FIFOMode = DMA_FIFOMODE_DISABLE;
    if (HAL_DMA_Init(&hdma_uart8_rx) != HAL_OK)
    {
      Error_Handler();
    }

    __HAL_LINKDMA(uartHandle,hdmarx,hdma_uart8_rx);

    /* UART8 interrupt Init */
    HAL_NVIC_SetPriority(UART8_IRQn, 6, 0);
    HAL_NVIC_EnableIRQ(UART8_IRQn);
  /* USER CODE BEGIN UART8_MspInit 1 */

  /* USER CODE END UART8_MspInit 1 */
  }
  else if(uartHandle->Instance==USART2)
  {
  /* USER CODE BEGIN USART2_MspInit 0 */

  /* USER CODE END USART2_MspInit 0 */
    /* USART2 clock enable */
    __HAL_RCC_USART2_CLK_ENABLE();

    __HAL_RCC_GPIOD_CLK_ENABLE();
    /**USART2 GPIO Configuration
    PD6     ------> USART2_RX
    PD5     ------> USART2_TX
    */
    GPIO_InitStruct.Pin = GPIO_PIN_6|GPIO_PIN_5;
    GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
    GPIO_InitStruct.Pull = GPIO_NOPULL;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
    GPIO_InitStruct.Alternate = GPIO_AF7_USART2;
    HAL_GPIO_Init(GPIOD, &GPIO_InitStruct);

  /* USER CODE BEGIN USART2_MspInit 1 */

  /* USER CODE END USART2_MspInit 1 */
  }
}

I am de initializing my UART before jumping from bootloader code to application but still I am getting this issue

void UART8_DeInit(void) {
    // De-initialize the UART peripheral
    // Stop any ongoing UART DMA transfers
    HAL_UART_AbortReceive(&huart8);
    HAL_UART_AbortTransmit(&huart8);

    // Deinitialize the DMA
    HAL_DMA_DeInit(huart8.hdmarx);

    // Deinitialize the UART
    HAL_UART_DeInit(&huart8);

    // Reset the UART and DMA clocks
    __HAL_RCC_UART8_FORCE_RESET();
    __HAL_RCC_UART8_RELEASE_RESET();
    __HAL_RCC_DMA1_FORCE_RESET();
    __HAL_RCC_DMA1_RELEASE_RESET();

    // Disable UART interrupts
    HAL_NVIC_DisableIRQ(USART_IRQn);

}

 

But this is not an only case for this.

In other project where I use 2 UARTs with DMA and other peripherals like SPI and I2C on STM32G0, same thing happens with UART2 but in that project I have set a timeout, where if I don't get interrupt on USART2 I re initialize USART2 and sort of works. 

So, I suspect there's something in initialization that's causing this problem or could be something that am doing wrong ??

4 REPLIES 4
Ozone
Principal

It seems your code implicitely relies upon reset values of peripheral config registers.
This is not the case when you use a peripheral in the bootloader, and then directly jump to your application.

I'm not a HAL/Cube user, but I'm pretty sure there is a corresponding Deinit - call for every init function.
Call this deinitialisation routines for every peripheral you use in the BL - either within the BL or in your application.
IMHO the BL (immediately before starting the application) is the best place to do this.

Ashvajit-CC
Associate II

I am de-initialzing every peripheral that I use from bootloader section before jumping to application address.

      HAL_NVIC_DisableIRQ(EXTI1_IRQn);
	//-- reset peripherals to guarantee flawless start of user application
	HAL_GPIO_DeInit(GPIOE,GPIO_PIN_8|GPIO_PIN_9|GPIO_PIN_10|GPIO_PIN_11);
	//USBD_DeInit(&hUsbDeviceFS);
     UART8_DeInit();
     USBD_DeInit(&hUsbDeviceFS);

	  __HAL_RCC_GPIOH_CLK_DISABLE();
	  __HAL_RCC_GPIOE_CLK_DISABLE();
	  __HAL_RCC_GPIOA_CLK_DISABLE();
	HAL_RCC_DeInit();
	HAL_DeInit();
	SysTick->CTRL = 0;
	SysTick->LOAD = 0;
	SysTick->VAL = 0;

But as I mentioned, this error is not only limited to only one case.


@Ashvajit-CC wrote:

In other project where I use 2 UARTs with DMA and other peripherals like SPI and I2C on STM32G0, same thing happens with UART2 but in that project I have set a timeout, where if I don't get interrupt on USART2 I re initialize USART2 and sort of works. 

 


 

TDK
Guru

Debug the code. Run it and hit pause when it "doesn't work". Examine where execution is at. Look at the uart handle to see if it has any error codes. You are handling errors right? Look at the register values to understand why it isn't currently receiving.

If you feel a post has answered your question, please click "Accept as Solution".
Pavel A.
Evangelist III

The best way to de-initialize stuff in STM32 is to avoid initializing it at all. So many times advised in this forum by @Piranha  IIRC and others. When bootloader decides to jump to the app, it stores a magic in the SRAM and calls NVIC_SystemReset, which does the reset job. Then the bootloader regains control and checks the magic BEFORE initializing anything else. If it sees the magic, it just jumps to the app.