On the Arduino running at 16MHz, setting the baudrate to 115200 results
in a 3.5% error, which is enough to cause occasional framing errors with
some adapters which are quite hard to debug.
This patch factors the code for computing the period in a single place
and adds a warning when the baudrate skew exceeds 3%.
Signed-off-by: Bernie Innocenti <bernie@codewiz.org>
git-svn-id: https://src.develer.com/svnoss/bertos/trunk@4773
38d2e660-2303-0410-9eaa-
f027e97ec537
volatile bool sending;
};
volatile bool sending;
};
+static uint16_t uart_period(unsigned long bps)
+{
+ uint16_t period = DIV_ROUND(CPU_FREQ / 16UL, bps) - 1;
+
+ #ifdef _DEBUG
+ long skew = bps - (long)(period + 1) * (CPU_FREQ / 16);
+ /* 8N1 is reliable within 3% skew */
+ if ((unsigned long)ABS(skew) > bps / (100 / 3))
+ kprintf("Baudrate off by %ldbps\n", skew);
+ #endif
+ //DB(kprintf("uart_period(bps=%lu): period=%u\n", bps, period);)
+ return period;
+}
static void uart0_setbaudrate(UNUSED_ARG(struct SerialHardware *, _hw), unsigned long rate)
{
static void uart0_setbaudrate(UNUSED_ARG(struct SerialHardware *, _hw), unsigned long rate)
{
- /* Compute baud-rate period */
- uint16_t period = DIV_ROUND(CPU_FREQ / 16UL, rate) - 1;
+ uint16_t period = uart_period(rate);
- UBRR0H = (period) >> 8;
- UBRR0L = (period);
-
- //DB(kprintf("uart0_setbaudrate(rate=%lu): period=%d\n", rate, period);)
}
static void uart0_setparity(UNUSED_ARG(struct SerialHardware *, _hw), int parity)
}
static void uart0_setparity(UNUSED_ARG(struct SerialHardware *, _hw), int parity)
static void uart1_setbaudrate(UNUSED_ARG(struct SerialHardware *, _hw), unsigned long rate)
{
static void uart1_setbaudrate(UNUSED_ARG(struct SerialHardware *, _hw), unsigned long rate)
{
- /* Compute baud-rate period */
- uint16_t period = DIV_ROUND(CPU_FREQ / 16UL, rate) - 1;
-
- UBRR1H = (period) >> 8;
- UBRR1L = (period);
-
- //DB(kprintf("uart1_setbaudrate(rate=%ld): period=%d\n", rate, period);)
+ uint16_t period = uart_period(rate);
+ UBRR1H = period >> 8;
+ UBRR1L = period;
}
static void uart1_setparity(UNUSED_ARG(struct SerialHardware *, _hw), int parity)
}
static void uart1_setparity(UNUSED_ARG(struct SerialHardware *, _hw), int parity)
static void uart2_setbaudrate(UNUSED_ARG(struct SerialHardware *, _hw), unsigned long rate)
{
static void uart2_setbaudrate(UNUSED_ARG(struct SerialHardware *, _hw), unsigned long rate)
{
- /* Compute baud-rate period */
- uint16_t period = DIV_ROUND(CPU_FREQ / 16UL, rate) - 1;
-
- UBRR2H = (period) >> 8;
- UBRR2L = (period);
-
- //DB(kprintf("uart2_setbaudrate(rate=%ld): period=%d\n", rate, period);)
+ uint16_t period = uart_period(rate);
+ UBRR2H = period >> 8;
+ UBRR2L = period;
}
static void uart2_setparity(UNUSED_ARG(struct SerialHardware *, _hw), int parity)
}
static void uart2_setparity(UNUSED_ARG(struct SerialHardware *, _hw), int parity)
static void uart3_setbaudrate(UNUSED_ARG(struct SerialHardware *, _hw), unsigned long rate)
{
static void uart3_setbaudrate(UNUSED_ARG(struct SerialHardware *, _hw), unsigned long rate)
{
- /* Compute baud-rate period */
- uint16_t period = DIV_ROUND(CPU_FREQ / 16UL, rate) - 1;
-
- UBRR3H = (period) >> 8;
- UBRR3L = (period);
-
- //DB(kprintf("uart3_setbaudrate(rate=%ld): period=%d\n", rate, period);)
+ uint16_t period = uart_period(rate);
+ UBRR3H = period >> 8;
+ UBRR3L = period;
}
static void uart3_setparity(UNUSED_ARG(struct SerialHardware *, _hw), int parity)
}
static void uart3_setparity(UNUSED_ARG(struct SerialHardware *, _hw), int parity)