Author Topic: STM32F101RB USART2  (Read 2907 times)

0 Members and 2 Guests are viewing this topic.

Offline maurosmartinsTopic starter

  • Regular Contributor
  • *
  • Posts: 62
  • Country: pt
    • Electronics and Embedded systems
STM32F101RB USART2
« on: February 19, 2017, 09:16:08 pm »
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 initialization
Code: [Select]
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: [Select]
__HAL_RCC_GPIOA_CLK_ENABLE();

and finally the Hw initialization is as follows:
Code: [Select]
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 Configuration   
    PA2     ------> USART2_TX
    PA3     ------> 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: [Select]
    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.
 

Offline newbrain

  • Super Contributor
  • ***
  • Posts: 1714
  • Country: se
Re: STM32F101RB USART2
« Reply #1 on: February 21, 2017, 10:06:44 am »
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)?

Nandemo wa shiranai wa yo, shitteru koto dake.
 

Offline AndyC_772

  • Super Contributor
  • ***
  • Posts: 4208
  • Country: gb
  • Professional design engineer
    • Cawte Engineering | Reliable Electronics
Re: STM32F101RB USART2
« Reply #2 on: February 21, 2017, 10:15:45 am »
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).

Offline Jeroen3

  • Super Contributor
  • ***
  • Posts: 4067
  • Country: nl
  • Embedded Engineer
    • jeroen3.nl
Re: STM32F101RB USART2
« Reply #3 on: February 21, 2017, 10:27:29 am »
Code: [Select]
__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++;
}
That all you need.

Dont get distracted by the vendor lib. Know your bare metals.
« Last Edit: February 21, 2017, 10:33:29 am by Jeroen3 »
 

Offline maurosmartinsTopic starter

  • Regular Contributor
  • *
  • Posts: 62
  • Country: pt
    • Electronics and Embedded systems
Re: STM32F101RB USART2
« Reply #4 on: February 21, 2017, 02:01:59 pm »
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.
 

Offline Jeroen3

  • Super Contributor
  • ***
  • Posts: 4067
  • Country: nl
  • Embedded Engineer
    • jeroen3.nl
Re: STM32F101RB USART2
« Reply #5 on: February 21, 2017, 02:28:34 pm »
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.
 

Offline AndyC_772

  • Super Contributor
  • ***
  • Posts: 4208
  • Country: gb
  • Professional design engineer
    • Cawte Engineering | Reliable Electronics
Re: STM32F101RB USART2
« Reply #6 on: February 21, 2017, 05:56:26 pm »
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.

Offline maurosmartinsTopic starter

  • Regular Contributor
  • *
  • Posts: 62
  • Country: pt
    • Electronics and Embedded systems
Re: STM32F101RB USART2
« Reply #7 on: February 21, 2017, 09:56:44 pm »
Hello all,

without any surprise Jeroen3 code worked like a charm! again, thank you for sending.
Code: [Select]
__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++;
}
That all you need.

Dont get distracted by the vendor lib. Know your bare metals.

I'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.
 

Offline Jeroen3

  • Super Contributor
  • ***
  • Posts: 4067
  • Country: nl
  • Embedded Engineer
    • jeroen3.nl
Re: STM32F101RB USART2
« Reply #8 on: February 22, 2017, 09:50:32 am »
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: [Select]
RCC->APB1ENR |= 0x0020000;
The macro is uselessly complicated because it's the vendor lib.

__HAL_RCC_USART2_FORCE_RESET() is used to explicitly reset the peripheral.
You could assume your 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.
« Last Edit: February 22, 2017, 09:55:13 am by Jeroen3 »
 


Share me

Digg  Facebook  SlashDot  Delicious  Technorati  Twitter  Google  Yahoo
Smf