MCPcopy Create free account
hub / github.com/RT-Thread/rt-thread / USART_BaudrateSyncSet

Function USART_BaudrateSyncSet

bsp/efm32/Libraries/emlib/src/em_usart.c:411–469  ·  view source on GitHub ↗

/ * @brief * Configure USART operating in synchronous mode to use a given baudrate * (or as close as possible to specified baudrate). * * @details * The configuration will be set to use a baudrate <= the specified baudrate * in order to ensure that the baudrate does not exceed the specified value. * * Fractional clock division is suppressed, although the HW design allows it. *

Source from the content-addressed store, hash-verified

409 * Baudrate to try to achieve for USART.
410 ******************************************************************************/
411void USART_BaudrateSyncSet(USART_TypeDef *usart, uint32_t refFreq, uint32_t baudrate)
412{
413 uint32_t clkdiv;
414
415 /* Inhibit divide by 0 */
416 EFM_ASSERT(baudrate);
417
418 /*
419 * We want to use integer division to avoid forcing in float division
420 * utils, and yet keep rounding effect errors to a minimum.
421 *
422 * CLKDIV in synchronous mode is given by:
423 *
424 * CLKDIV = 256 * (fHFPERCLK/(2 * br) - 1)
425 * or
426 * CLKDIV = (256 * fHFPERCLK)/(2 * br) - 256 = (128 * fHFPERCLK)/br - 256
427 *
428 * The basic problem with integer division in the above formula is that
429 * the dividend (128 * fHFPERCLK) may become higher than max 32 bit
430 * integer. Yet, we want to evaluate dividend first before dividing in
431 * order to get as small rounding effects as possible. We do not want
432 * to make too harsh restrictions on max fHFPERCLK value either.
433 *
434 * One can possibly factorize 128 and br. However, since the last
435 * 6 bits of CLKDIV are don't care, we can base our integer arithmetic
436 * on the below formula without loosing any extra precision:
437 *
438 * CLKDIV / 64 = (2 * fHFPERCLK)/br - 4
439 *
440 * and calculate 1/64 of CLKDIV first. This allows for fHFPERCLK
441 * up to 2GHz without overflowing a 32 bit value!
442 */
443
444 /* HFPERCLK used to clock all USART/UART peripheral modules */
445 if (!refFreq)
446 {
447 refFreq = CMU_ClockFreqGet(cmuClock_HFPER);
448 }
449
450 /* Calculate and set CLKDIV with fractional bits */
451 clkdiv = 2 * refFreq;
452 clkdiv += baudrate - 1;
453 clkdiv /= baudrate;
454 clkdiv -= 4;
455 clkdiv *= 64;
456 /* Make sure we don't use fractional bits by rounding CLKDIV */
457 /* up (and thus reducing baudrate, not increasing baudrate above */
458 /* specified value). */
459 clkdiv += 0xc0;
460 clkdiv &= 0xffffff00;
461
462 /* Verify that resulting clock divider is within limits */
463 EFM_ASSERT(clkdiv <= _USART_CLKDIV_MASK);
464
465 /* If EFM_ASSERT is not enabled, make sure we don't write to reserved bits */
466 clkdiv &= _USART_CLKDIV_DIV_MASK;
467
468 usart->CLKDIV = clkdiv;

Callers 3

efm_hw_eth_initFunction · 0.85
efm_spiSd_speedFunction · 0.85
USART_InitSyncFunction · 0.85

Calls 1

CMU_ClockFreqGetFunction · 0.85

Tested by

no test coverage detected