/ * @brief * Configure USART/UART operating in asynchronous mode to use a given * baudrate (or as close as possible to specified baudrate). * * @param[in] usart * Pointer to USART/UART peripheral register block. * * @param[in] refFreq * USART/UART reference clock frequency in Hz that will be used. If set to 0, * the currently configured reference clock is assumed. * * @param[i
| 119 | * compared to link partner. |
| 120 | ******************************************************************************/ |
| 121 | void USART_BaudrateAsyncSet(USART_TypeDef *usart, |
| 122 | uint32_t refFreq, |
| 123 | uint32_t baudrate, |
| 124 | USART_OVS_TypeDef ovs) |
| 125 | { |
| 126 | uint32_t clkdiv; |
| 127 | uint32_t oversample; |
| 128 | |
| 129 | /* Inhibit divide by 0 */ |
| 130 | EFM_ASSERT(baudrate); |
| 131 | |
| 132 | /* |
| 133 | * We want to use integer division to avoid forcing in float division |
| 134 | * utils, and yet keep rounding effect errors to a minimum. |
| 135 | * |
| 136 | * CLKDIV in asynchronous mode is given by: |
| 137 | * |
| 138 | * CLKDIV = 256 * (fHFPERCLK/(oversample * br) - 1) |
| 139 | * or |
| 140 | * CLKDIV = (256 * fHFPERCLK)/(oversample * br) - 256 |
| 141 | * |
| 142 | * The basic problem with integer division in the above formula is that |
| 143 | * the dividend (256 * fHFPERCLK) may become higher than max 32 bit |
| 144 | * integer. Yet, we want to evaluate dividend first before dividing in |
| 145 | * order to get as small rounding effects as possible. We do not want |
| 146 | * to make too harsh restrictions on max fHFPERCLK value either. |
| 147 | * |
| 148 | * One can possibly factorize 256 and oversample/br. However, |
| 149 | * since the last 6 bits of CLKDIV are don't care, we can base our |
| 150 | * integer arithmetic on the below formula |
| 151 | * |
| 152 | * CLKDIV / 64 = (4 * fHFPERCLK)/(oversample * br) - 4 |
| 153 | * |
| 154 | * and calculate 1/64 of CLKDIV first. This allows for fHFPERCLK |
| 155 | * up to 1GHz without overflowing a 32 bit value! |
| 156 | */ |
| 157 | |
| 158 | /* HFPERCLK used to clock all USART/UART peripheral modules */ |
| 159 | if (!refFreq) |
| 160 | { |
| 161 | refFreq = CMU_ClockFreqGet(cmuClock_HFPER); |
| 162 | } |
| 163 | |
| 164 | /* Map oversampling */ |
| 165 | switch (ovs) |
| 166 | { |
| 167 | case USART_CTRL_OVS_X16: |
| 168 | EFM_ASSERT(baudrate <= (refFreq / 16)); |
| 169 | oversample = 16; |
| 170 | break; |
| 171 | |
| 172 | case USART_CTRL_OVS_X8: |
| 173 | EFM_ASSERT(baudrate <= (refFreq / 8)); |
| 174 | oversample = 8; |
| 175 | break; |
| 176 | |
| 177 | case USART_CTRL_OVS_X6: |
| 178 | EFM_ASSERT(baudrate <= (refFreq / 6)); |
no test coverage detected