2015-08-14 10:42 AM
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);2015-08-14 11:22 AM
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.2015-08-14 11:54 AM
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.2015-08-14 11:57 AM
2015-08-14 01:10 PM
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 HzWhen 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.2015-08-14 01:13 PM
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);
}
2015-08-14 01:44 PM
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.Daniel2015-08-14 03:39 PM
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...