Cannot set UART to 300 baud
Hi,
Since the commit 20104a6c it is not possible to set the UART baudrate to 300 anymore. We're now using the fractional mode of the SERCOM and sercom->USART.BAUD.FRAC.BAUD can only hold 13 bits while at 300 baud you want to write 10000. It doesn't fit.
To be honest, I don't even know how accurate the 300 baud used to be before this change, but we only use it to emulate sending a break. And that is not possible anymore.
Should we perhaps switch to the non-fractional mode if we detect that there is an overflow of the 13 bits?
Have the same issue. not working anymore... Need 300 Baud to init read smartmeter on IEC. Any news? Still open?
I spent a couple of Hours on this... Arithmetic and Fractional mode end up in the same result: Overflow or inaccurate Baudrates on rates below 600. This is cause the Baudrate is an result of Clock/Divisor wich ends in a Baudrate 274 or 320, but no way for exact 300. The only way i found is to switch the Clocksource of SERCOM5 from 48MHz to 8MHz.
This worked for me on MKR1010
void SERCOM::initUART(SercomUartMode mode, SercomUartSampleRate sampleRate, uint32_t baudrate)
{
initClockNVIC();
// BEGIN: Workaround for
// Cannot set UART to 300 baud #208
// https://github.com/arduino/ArduinoCore-samd/issues/208
// 01.12.22 - Roger Althaus
// Switch SERCOM timer on lower Baudrates from GCLK0 48MHz to GCLK2 8MHz
// to prevent Baud-Register overflows and troubles for Baudrates below 600.
if (mode == UART_INT_CLOCK && sercom == SERCOM5 && baudrate < 600)
{
// Clockchange is based on following article
// https://blog.thea.codes/understanding-the-sam-d21-clocks/
baudrate = baudrate * 6; // Clock is 6 Times slower, so we have to adjust Baudrate
/* Configure GCLK2's divider - in this case, no division - so just divide by one */
GCLK->GENDIV.reg =
GCLK_GENDIV_ID(2) |
GCLK_GENDIV_DIV(1);
/* Setup GCLK2 using the internal 8 MHz oscillator */
GCLK->GENCTRL.reg =
GCLK_GENCTRL_ID(2) |
GCLK_GENCTRL_SRC_OSC8M |
/* Improve the duty cycle. */
GCLK_GENCTRL_IDC |
GCLK_GENCTRL_GENEN;
/* Wait for the write to complete */
while (GCLK->STATUS.bit.SYNCBUSY) {};
/* Connect GCLK2 to SERCOM5 */
GCLK->CLKCTRL.reg =
GCLK_CLKCTRL_CLKEN |
GCLK_CLKCTRL_GEN_GCLK2 |
GCLK_CLKCTRL_ID_SERCOM5_CORE;
/* Wait for the write to complete. */
while (GCLK->STATUS.bit.SYNCBUSY) {};
PM->APBCMASK.reg |= PM_APBCMASK_SERCOM5;
//At this point the peripheral is ready to use!You can software reset the peripheraland start configuring it as needed :
//SERCOM0->SPI.CTRLA.bit.SWRST = 1;
//while (SERCOM0->SPI.SYNCBUSY.bit.SWRST) {};
}
// END: Workaround
resetUART();
....
It would be interesting to have this fixed as an official PR, since like the user above said, 300 baud is still used a lot in IEC smartmeters