ser_avr: warn for excessive baudrate skew
authorarighi <arighi@38d2e660-2303-0410-9eaa-f027e97ec537>
Tue, 15 Mar 2011 16:59:25 +0000 (16:59 +0000)
committerarighi <arighi@38d2e660-2303-0410-9eaa-f027e97ec537>
Tue, 15 Mar 2011 16:59:25 +0000 (16:59 +0000)
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

bertos/cpu/avr/drv/ser_avr.c

index 7bfc8d2c3aec4ded98cb4e7e1d1b76a368e4ae41..ce44fd1983c08d7027f4b5b04233bb2ae95fd3f1 100644 (file)
@@ -458,7 +458,20 @@ struct AvrSerial
        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;
+}
 
 /*
  * Callbacks
@@ -495,15 +508,12 @@ static void uart0_enabletxirq(struct SerialHardware *_hw)
 
 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);
 
 #if !CPU_AVR_ATMEGA103
-       UBRR0H = (period) >> 8;
+       UBRR0H = period >> 8;
 #endif
-       UBRR0L = (period);
-
-       //DB(kprintf("uart0_setbaudrate(rate=%lu): period=%d\n", rate, period);)
+       UBRR0L = period;
 }
 
 static void uart0_setparity(UNUSED_ARG(struct SerialHardware *, _hw), int parity)
@@ -548,13 +558,9 @@ static void uart1_enabletxirq(struct SerialHardware *_hw)
 
 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)
@@ -599,13 +605,9 @@ static void uart2_enabletxirq(struct SerialHardware *_hw)
 
 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)
@@ -650,13 +652,9 @@ static void uart3_enabletxirq(struct SerialHardware *_hw)
 
 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)