AnsweredAssumed Answered

Bug in the STM32F4xx std periferal library USART module

Question asked by chernikov.vasily on Oct 29, 2015
Hello. The issue: file stm32f4xx_usart.c, function USART_Init, fractional divider calculation code:

/* Determine the fractional part */
fractionaldivider = integerdivider - (100 * (tmpreg >> 4));
 
/* Implement the fractional part in the register */
if ((USARTx->CR1 & USART_CR1_OVER8) != 0)
{
  tmpreg |= ((((fractionaldivider * 8) + 50) / 100)) & ((uint8_t)0x07);
}
else /* if ((USARTx->CR1 & USART_CR1_OVER8) == 0) */
{
  tmpreg |= ((((fractionaldivider * 16) + 50) / 100)) & ((uint8_t)0x0F);
}
 
It does not take into account that the result of(((fractionaldivider * 8) + 50) / 100) or (((fractionaldivider * 16) + 50) / 100) could become equal to, respectively, 8 or 16. It would be required in that case to increment integer divider part while leaving fractional part equal to 0. And, in general, no masking of muldiv result (either by 0x07 or by 0x0f) is required since that result is in the masked range "by desing" — except of the case described.

Needed something like this:

/* Determine the fractional part */
fractionaldivider = integerdivider - (100 * (tmpreg >> 4));
 
/* Implement the fractional part in the register */
if ((USARTx->CR1 & USART_CR1_OVER8) != 0)
{
  fractionaldivider = ((fractionaldivider * 8) + 50) / 100;
  tmpreg += (fractionaldivider < 8) ? fractionaldivider : 0x10;
}
else /* if ((USARTx->CR1 & USART_CR1_OVER8) == 0) */
{
  tmpreg += ((((fractionaldivider * 16) + 50) / 100));
}

Outcomes