From 517cca1528492422030102f6c1a6691420c1c1a0 Mon Sep 17 00:00:00 2001 From: arighi Date: Tue, 15 Mar 2011 16:59:25 +0000 Subject: [PATCH] ser_avr: warn for excessive baudrate skew 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 git-svn-id: https://src.develer.com/svnoss/bertos/trunk@4773 38d2e660-2303-0410-9eaa-f027e97ec537 --- bertos/cpu/avr/drv/ser_avr.c | 52 +++++++++++++++++------------------- 1 file changed, 25 insertions(+), 27 deletions(-) diff --git a/bertos/cpu/avr/drv/ser_avr.c b/bertos/cpu/avr/drv/ser_avr.c index 7bfc8d2c..ce44fd19 100644 --- a/bertos/cpu/avr/drv/ser_avr.c +++ b/bertos/cpu/avr/drv/ser_avr.c @@ -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) -- 2.25.1