cancel
Showing results for 
Search instead for 
Did you mean: 

Mixing HAL and Direct Register Manipulation

minion_SLAYER
Associate II

Hello. I am writing a code to read ADC data from an AC voltage sensor. I used HAL to initialize ADC 1 and USART2 for checking the values in Putty. However, I would like to use direct register manipulation to send data to USART6 so that it can transmit the data to a wifi module which sends the data to a website for monitoring. However, I am not getting correct values in USART6 (confirmed by using serial monitor in IDE which I am using to check data received by the wifi module which is ESP32 to be specific). The output is gibberish as opposed to the data obtained from USART2. Is it possible that there's clashing between the initialization of USART2 in HAL and USART6 in bare metal?

If I try using bare metal for USART2 and USART6, would there be any difference? I have read from another question here that you cannot mix HAL and bare metal code when accessing the same peripheral, but I wonder if that applies for the GPIO peripherals I'd be using as well (ADC GPIOs in HAL and USART GPIOs in bare metal)

1 ACCEPTED SOLUTION

Accepted Solutions
minion_SLAYER
Associate II

Hello! To answer my own question, yes it is possible.

For my first problem wherein the output received from ESP32 is gibberish, I realized that the way I was parsing the data being received by my wifi module was compatible to my register manipulation configuration of USART using FIFO. Transmission via the HAL_UART_Transmit command with USART2 is blocking and is not FIFO so naturally, my ESP32 code was not able to properly parse the data. A workaround for this is to use a UART Ring buffer to make the transmission via HAL similar to the FIFO implementation but I found it too tedious so in the end, I had to configure both USART2 and USART6 via bare metal programming and it worked.

Moreover, I found that the default HAL sysclk configuration for my nucleoboard sets the system clock to 84MHz. I missed this very important part of the HAL code so I made mistakes with the baud rate calculations (wherein I used 16MHz as the system clock). It's also very important to delete the "residual" configurations for GPIO and USART that the HAL code made in order to avoid conflicts with the bare metal manipulation. I am sure that this is a rookie mistake, but I enjoyed and learned a lot from this one. It made me appreciate bare metal programming even more due to its overall flexibility, and I felt like I had more control on my program as opposed to the parts where I used HAL (ADC and System Clock configurations). Thank you to everyone who helped!

View solution in original post

11 REPLIES 11
Pavel A.
Evangelist III

 Is it possible that there's clashing between the initialization of USART2 in HAL and USART6 in bare metal?

Yes. Initialization of one USART in HAL calls the "MSP" function (generated by Cube) that is shared by all UARTs. It can break pins setup of the other ("bare metal") UART. Mixing HAL and non HAL code is possible but should be done  accurately.

 

 

USARTx->BRR might be different as USART2 / USART6 are on different APB ?

Get a scope on the signal, send a 'U' pattern, check bit timing

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..

I decided to implement USART2 and USART6 in bare-metal instead in order to avoid these differences and so that I have better control of their timings. Reinitialized ADC with HAL and for HAL only and included a header file for the USART baremetal initialization. However, I am not sure which parts of the HAL Code I should remove. Upon initialization of the HAL code, it still initialized the GPIO pins so I commented that out. There was also an MSP init in the header file which I commented out as well. Is that okay? I am relatively new to STM32 for context.

//  /*Configure GPIO pins : USART_TX_Pin USART_RX_Pin */
//  GPIO_InitStruct.Pin = USART_TX_Pin|USART_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_AF7_USART2;
//  HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);

 

There was also an MSP init in the header file which I commented out as well

//void HAL_UART_MspInit(UART_HandleTypeDef* huart)
//{
//  GPIO_InitTypeDef GPIO_InitStruct = {0};
//  if(huart->Instance==USART2)
//  {
//  /* USER CODE BEGIN USART2_MspInit 0 */
//
//  /* USER CODE END USART2_MspInit 0 */
//    /* Peripheral clock enable */
//    __HAL_RCC_USART2_CLK_ENABLE();
//
//    __HAL_RCC_GPIOA_CLK_ENABLE();
//    /**USART2 GPIO Configuration
//    PA2     ------> USART2_TX
//    PA3     ------> USART2_RX
//    */
//    GPIO_InitStruct.Pin = USART_TX_Pin|USART_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_AF7_USART2;
//    HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
//
//  /* USER CODE BEGIN USART2_MspInit 1 */
//
//  /* USER CODE END USART2_MspInit 1 */
//  }
//
//}

is it okay to remove this MSP function if I use bare metal for both USART2 & 6?

Yes

If you've otherwise initialized everything properly these can go. Pre HAL it was common to put all the initialization code in one subroutine rather than have HAL_UART_Init() call secondary hidden functions

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
minion_SLAYER
Associate II

Hello! To answer my own question, yes it is possible.

For my first problem wherein the output received from ESP32 is gibberish, I realized that the way I was parsing the data being received by my wifi module was compatible to my register manipulation configuration of USART using FIFO. Transmission via the HAL_UART_Transmit command with USART2 is blocking and is not FIFO so naturally, my ESP32 code was not able to properly parse the data. A workaround for this is to use a UART Ring buffer to make the transmission via HAL similar to the FIFO implementation but I found it too tedious so in the end, I had to configure both USART2 and USART6 via bare metal programming and it worked.

Moreover, I found that the default HAL sysclk configuration for my nucleoboard sets the system clock to 84MHz. I missed this very important part of the HAL code so I made mistakes with the baud rate calculations (wherein I used 16MHz as the system clock). It's also very important to delete the "residual" configurations for GPIO and USART that the HAL code made in order to avoid conflicts with the bare metal manipulation. I am sure that this is a rookie mistake, but I enjoyed and learned a lot from this one. It made me appreciate bare metal programming even more due to its overall flexibility, and I felt like I had more control on my program as opposed to the parts where I used HAL (ADC and System Clock configurations). Thank you to everyone who helped!


@minion_SLAYER wrote:

I felt like I had more control on my program as opposed to the parts where I used HAL 


Indeed more control - but with that comes more responsibility (eg, ensuring that you understand  the clock config!)