cancel
Showing results for 
Search instead for 
Did you mean: 

STM32L051C6T6 USART buard rate not correct when using MSI

danielblesener9
Associate II
Posted on August 14, 2015 at 19:42

I have USART1/2 working fine when using HSI. When using MSI clock (code below) I do not see the correct output frequency on the scope.

I am setting the MSI to 2.097MHz. I measured this as 2.31MHz from MCO. 

I am setting USART1 to 115200. The BRR reg states 17 which should give me 2130000/18 = 118K. 

When measuring the usart signal on a scope I see about 101K.Very confusing. Let me know if you see any errors or have any pointers. Thanks.

  HAL_RCC_DeInit();

    

  RCC_OscInitTypeDef RCC_OscInitStruct;

  RCC_ClkInitTypeDef RCC_ClkInitStruct;

  RCC_PeriphCLKInitTypeDef PeriphClkInit;

  __PWR_CLK_ENABLE();

  __HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE3);

  RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_MSI;

  RCC_OscInitStruct.MSIState = RCC_MSI_ON;

  //RCC_OscInitStruct.MSICalibrationValue = ?;//This is automatically loaded with calibration value from factor at 25C - change if temp changes

  RCC_OscInitStruct.MSIClockRange = RCC_MSIRANGE_5;

  RCC_OscInitStruct.PLL.PLLState = RCC_PLL_NONE;

  HAL_RCC_OscConfig(&RCC_OscInitStruct);

  RCC_ClkInitStruct.ClockType = (RCC_CLOCKTYPE_SYSCLK | RCC_CLOCKTYPE_HCLK | RCC_CLOCKTYPE_PCLK1 | RCC_CLOCKTYPE_PCLK2);

  RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_MSI;

  RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;

  //APB2 must be at least as fast as APB1

  RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1;

  RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;

  HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_0);

  PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_USART1|RCC_PERIPHCLK_USART2;

  PeriphClkInit.Usart1ClockSelection = RCC_USART1CLKSOURCE_PCLK2;

  PeriphClkInit.Usart2ClockSelection = RCC_USART2CLKSOURCE_PCLK1;

  HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit);

  //HAL_SYSTICK_Config(HAL_RCC_GetHCLKFreq()/100);

  //HAL_SYSTICK_CLKSourceConfig(SYSTICK_CLKSOURCE_HCLK);

  

  SystemCoreClockUpdate();

  

  __CRC_CLK_ENABLE();

}

//////////////////////////////////////USART///////////////////////////////////////////

    __USART1_CLK_ENABLE();                          // Enable USART 1 clock

    husart1.Instance                                 = USART1;

    husart1.Init.BaudRate                            = 115200;

    husart1.Init.WordLength                          = UART_WORDLENGTH_8B;

    husart1.Init.StopBits                            = UART_STOPBITS_1;

    husart1.Init.Parity                              = UART_PARITY_NONE;

    husart1.Init.Mode                                = UART_MODE_TX_RX;

    husart1.Init.HwFlowCtl                           = UART_HWCONTROL_NONE;

    husart1.Init.OverSampling                        = UART_OVERSAMPLING_16;

    husart1.AdvancedInit.AdvFeatureInit              = UART_ADVFEATURE_RXOVERRUNDISABLE_INIT|UART_ADVFEATURE_DMADISABLEONERROR_INIT;

    husart1.AdvancedInit.OverrunDisable              = UART_ADVFEATURE_OVERRUN_DISABLE;

    husart1.AdvancedInit.DMADisableonRxError         = UART_ADVFEATURE_DMA_DISABLEONRXERROR;

    

    HAL_UART_Init(&husart1);                        // Initializes the USART1 according to the specified parameters above and creates the associated handle.

    //husart1.Instance->BRR = 0xB6;

/* Enable the USART1 Receive interrupt: this interrupt is generated when the USART1 receive data register is not empty */

    __HAL_UART_ENABLE_IT(&husart1, UART_IT_RXNE);

    __HAL_UART_DISABLE_IT(&husart1, UART_IT_TC);

    __HAL_UART_DISABLE_IT(&husart1, UART_IT_WUF);

    __HAL_UART_DISABLE_IT(&husart1, UART_IT_CM);

    __HAL_UART_DISABLE_IT(&husart1, UART_IT_CTS);

    __HAL_UART_DISABLE_IT(&husart1, UART_IT_LBD);

    __HAL_UART_DISABLE_IT(&husart1, UART_IT_TXE);

    __HAL_UART_DISABLE_IT(&husart1, UART_IT_IDLE);

    __HAL_UART_DISABLE_IT(&husart1, UART_IT_PE);

    __HAL_UART_DISABLE_IT(&husart1, UART_IT_ERR);
7 REPLIES 7
Posted on August 14, 2015 at 20:22

So 2130000 or 2310000 ?

And I'm pretty sure it would be PCLK/BRR,  not PCLK/(BRR + 1)

Assuming it's supposed to hit 2097000 Hz, BRR=18 should hit 116500

One of your measurements is off.  Send a 0x55 pattern, and measure the width of one high pulse, with as much resolution/precision as possible.

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
danielblesener9
Associate II
Posted on August 14, 2015 at 20:54

Thanks for the response.

I am sure my measurements are correct because when using the HSI everything works fine, and I took measurements when using the HSI to validate them. I see 115200 almost perfectly when using HSI.

When changing the BRR to 0x12, the frequency decreases by a few K as expected. No clue whats wrong. 

I normally would just use 32MHz but low power is crucial here.

If I change the BRR reg to 0xF0, I should see fclk/240 for buad (8875). I see 8537. Much closer. But as the desired baud goes higher the error increases.

danielblesener9
Associate II
Posted on August 14, 2015 at 20:57

Also - I measured 2.13MHz from MCO function. Not 2,31MHz. Typo - my bad.

Posted on August 14, 2015 at 22:10

Do you think you should zero RCC_OscInitStruct.MSICalibrationValue? Otherwise it has a potential to be random data at entry.

With your first example was it 17 or 0x17, because 23 decimal makes a lot more sense with a output baud rate of 101K and a clock ~2323000 Hz

When I see numbers that are internally inconsistent (synchronous gearing is hard to screw up), I first assume the measurements or observations are wrong, and work back from there.

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
Posted on August 14, 2015 at 22:13

The examples do this

static void SystemClock_Config(void)
{
RCC_ClkInitTypeDef RCC_ClkInitStruct;
RCC_OscInitTypeDef RCC_OscInitStruct;
/* Enable Power Control clock */
__PWR_CLK_ENABLE();
/* The voltage scaling allows optimizing the power consumption when the device is
clocked below the maximum system frequency, to update the voltage scaling value
regarding system frequency refer to product datasheet. */
__HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE3);
/* Enable MSI Oscillator */
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_MSI;
RCC_OscInitStruct.MSIState = RCC_MSI_ON;
RCC_OscInitStruct.MSIClockRange = RCC_MSIRANGE_5;
RCC_OscInitStruct.MSICalibrationValue = 0x00;
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_NONE;
HAL_RCC_OscConfig(&RCC_OscInitStruct);
/* Select MSI as system clock source and configure the HCLK, PCLK1 and PCLK2
clocks dividers */
RCC_ClkInitStruct.ClockType = (RCC_CLOCKTYPE_SYSCLK | RCC_CLOCKTYPE_HCLK | RCC_CLOCKTYPE_PCLK1 | RCC_CLOCKTYPE_PCLK2);
RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_MSI;
RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1;
RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;
HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_0);
}

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
danielblesener9
Associate II
Posted on August 14, 2015 at 22:44

I tried zeroing it. But the reference manual (page 171) states the following:

The MSI RC oscillator frequency can vary from one chip to another due to manufacturingprocess variations, this is why each device is factory calibrated by ST for 1% accuracy at anambient temperature, TA, of 25 °C.After reset, the factory calibration value is loaded in the MSICAL[7:0] bits in theRCC_ICSCR register. If the application is subject to voltage or temperature variations, thismay affect the RC oscillator speed. You can trim the MSI frequency in the application byusing the MSITRIM[7:0] bits in the RCC_ICSCR register. For more details on how tomeasure the MSI frequency variation please refer to Section 7.2.14: Internal/external clockmeasurement using TIM21.

If I zero it I am getting rid of the factor calibration value. I think the calibration value is changed by the user during temp variations. I looked in the registers at a few MCU's that work with the HSI on and they were different. When I change the calibration value the USART doesnt work.

Daniel

Posted on August 15, 2015 at 00:39

My issue is with *HOW* some magic value gets into this structure, in the examples a local/auto variable, from a *SET* function. It's an MSI specific value, so isn't going to impact behaviour when HSI or HSE are selected.

I understand the purpose at the register level for the calibration.

I can't place your code snippet in any sort of context, if this is a global structure, if something else has configured the structure with the parameters the chip reset with...

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