STM32F101RB USART2 - Page 1
Forum section: electronics / general

author: maurosmartins
author_rank: Regular Contributor
timestamp: February 19, 2017, 09:16:08 pm
content: Hello all,I'm trying to configure USART on a STM32F101RB micrcontroller with Atollic True Studio.the uC clock is configured as external clock (8Mhz) divided by 2 and pll'ed by 9 to a total 36Mhz.I'm using the HAL to initialize the microcontroller, but so far I hadn't had success. I know the hw is working ok because setting that port with mikroC... it works.normal usart initializationCode:static void MX_USART2_UART_Init(void){huart2.Instance = USART2;huart2.Init.BaudRate = 115200;huart2.Init.WordLength = UART_WORDLENGTH_8B;huart2.Init.StopBits = UART_STOPBITS_1;huart2.Init.Parity = UART_PARITY_NONE;huart2.Init.Mode = UART_MODE_TX_RX;huart2.Init.HwFlowCtl = UART_HWCONTROL_NONE;huart2.Init.OverSampling = UART_OVERSAMPLING_16;if (HAL_UART_Init(&huart2) != HAL_OK){Error_Handler();}}Clock for porta has already been enabled by calling:Code:__HAL_RCC_GPIOA_CLK_ENABLE();and finally the Hw initialization is as follows:Code:void HAL_UART_MspInit(UART_HandleTypeDef* huart){GPIO_InitTypeDef GPIO_InitStruct;if(huart->Instance==USART2){__HAL_RCC_AFIO_CLK_ENABLE();AFIO->MAPR &= (~AFIO_MAPR_USART2_REMAP_Msk);__HAL_RCC_USART2_CLK_ENABLE();/**USART2 GPIO ConfigurationPA2 ------> USART2_TXPA3 ------> USART2_RX*/GPIO_InitStruct.Pin = GPIO_PIN_2;GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);GPIO_InitStruct.Pin = GPIO_PIN_3;GPIO_InitStruct.Mode = GPIO_MODE_INPUT;GPIO_InitStruct.Pull = GPIO_NOPULL;HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);}}with this I've tryed to send the eternal "Hello World" as follows:Code:while(1){char msg[] = "Hello World!\n\r";HAL_UART_Transmit(&huart2, (uint8_t*)msg, strlen(msg), 0xFFFF);}but no success, I've even checked if alternative pins were enabled, but, they were not.any ideas of what can be wrong?thanks in advanced,Best regards Mauro.

author: newbrain
author_rank: Super Contributor
timestamp: February 21, 2017, 10:06:44 am
content: Everything seems to be in order...__HAL_AFIO_REMAP_USART2_DISABLE() can be used instead of the direct AFIO register write, but it does the very same thing.Are the clocks and PLL correctly set up (they seem to be, according t the description)?Could you show you clock chain initialization code?Does the code actually reach the transmit call (usual methods to check, debugger or GPIO pin toggle)?

author: AndyC_772
author_rank: Super Contributor
timestamp: February 21, 2017, 10:15:45 am
content: This is, unfortunately, the problem with using manufacturer libraries. You never *really* know what they're doing, or failing to do, until you go through the code in detail to check it.I abandoned the use of the HAL quite early on in my STM32 career, and never looked back. Keep the ST header files for their useful definitions of register names and values, but don't use the code at all. Just poke the hardware, it's not that hard - especially since you have to pass all the essential parameters to the HAL anyway.IMHO the HAL doesn't offer useful abstraction or simplification, just obfuscation.If you already have working UART2 code, you could possibly try:- configure the UART using HAL- immediately afterwards, reconfigure the UART using your own code- check that it now works OK- remove settings from your own code until you find the one which allowed the port to work. (There may, of course, be more than one).

author: Jeroen3
author_rank: Super Contributor
timestamp: February 21, 2017, 10:27:29 am
content: Code:__HAL_RCC_GPIOA_CLK_ENABLE();GPIOA->CRL &= ~(GPIO_CRL_CNF3_Msk| GPIO_CRL_MODE3_Msk);GPIOA->CRL |= (1u << GPIO_CRL_CNF3_Pos)| (0u << GPIO_CRL_MODE3_Pos) ;GPIOA->CRL &= ~(GPIO_CRL_CNF2_Msk| GPIO_CRL_MODE2_Msk);GPIOA->CRL |= (2u << GPIO_CRL_CNF2_Pos)| (2u << GPIO_CRL_MODE2_Pos);__HAL_RCC_USART2_CLK_ENABLE();__NOP();__HAL_RCC_USART2_FORCE_RESET();__NOP();__HAL_RCC_USART2_RELEASE_RESET();USART2->BRR = UART_BRR_SAMPLING16(pclk1, 115200);USART2->CR1 = USART_CR1_TE | USART_CR1_UE;char *p = "Hello World\n";while(*p!='\0'){while((USART2->SR & USART_SR_TXE) != USART_SR_TXE){ __NOP(); }USART2->DR = *p++;}Thatallyou need.Dont get distracted by the vendor lib. Know your bare metals.

author: maurosmartins
author_rank: Regular Contributor
timestamp: February 21, 2017, 02:01:59 pm
content: Hello all,thank you very much for your replies.Jeroen3 I later when I get home I'll try your code and see if it works properly, thank you for sending.In the meanwhile I saw this in the reference manual:and analyzing the clock tree:does this mean in addition to the clocks I have already enabled, I also have to enable one for the APB1 Peripherals?Best regards, Mauro.

author: Jeroen3
author_rank: Super Contributor
timestamp: February 21, 2017, 02:28:34 pm
content: Yes, obviously. You also need to setup the dividers.But this is the part where you can use the HAL. It provides you functions to pull the actual hz's from the registers if the base oscillator (internal/external) is known.

author: AndyC_772
author_rank: Super Contributor
timestamp: February 21, 2017, 05:56:26 pm
content: Why bother with the HAL? It takes just three writes to the RCC to set up the clock tree and enable the PLL as the clock source.You may also need a call to __USART2_CLK_ENABLE() (or whatever similar function is needed by that specific device) as well. This is an in-line macro that gets expanded directly into a register write; it doesn't result in any additional functions being added to your code.

author: maurosmartins
author_rank: Regular Contributor
timestamp: February 21, 2017, 09:56:44 pm
content: Hello all,without any surprise Jeroen3 code worked like a charm! again, thank you for sending.Quote from: Jeroen3 on February 21, 2017, 10:27:29 amI've inspected it and, I would like to clarify something, in my previous post I saw this:but if I'm correct this is only the indication for each one of the bits in the RCC_APB1ENR register that are set using the __HAL_RCC_USART2_CLK_ENABLE() is this ok?another doubt relates to the __HAL_RCC_USART2_FORCE_RESET() and __HAL_RCC_USART2_FORCE_RELEASE_RESET() why do we need to do this?best regards, Mauro.

author: Jeroen3
author_rank: Super Contributor
timestamp: February 22, 2017, 09:50:32 am
content: For power savings you can enable and disable many clocks. Clocked gates use power, static gates do not.You have to enable the clock tree, and each individual peripheral. Some things are enabled after reset for the chip to boot. Some of those can be disabled to save power.__HAL_RCC_USART2_CLK_ENABLE() is just a readable way to write:Code:RCC->APB1ENR |= 0x0020000;The macro is uselessly complicated because it's the vendor lib.__HAL_RCC_USART2_FORCE_RESET() is used toexplicitlyreset the peripheral.You couldassumeyour init function is run only after system reset. But, in engineering, assumptions can be dangerous.What if you perform a software reset where you only reset the Program Counter? What if the program counter takes a hike due to ESD?Running init code on initialized peripherals could result in undefined behavior.Some peripherals already prevent consequential damages by locking some registers from being edited when the peripheral is active. CAN is such an example, since you don't want the CAN bus in your vehicle to lock up if the firmware misbehaves.GPIO also has optional configuration lockbits, since most boards have a few pins that can destroy things if put in the wrong mode. eg: two push-pull outputs driving into each other. This is why on reset all pins are Floating Inputs, they will need external pull resistors to have a defined state during reset.