From: Jerry Van Baren <gerald.vanbaren@ge.com>
To: u-boot@lists.denx.de
Subject: [U-Boot-Users] [PATCH] ColdFire: Fix UART baudrate at 115200
Date: Wed, 28 May 2008 17:29:21 -0400 [thread overview]
Message-ID: <483DCEB1.3040509@ge.com> (raw)
In-Reply-To: <4791E710007FEB4BBF83775D787F462F072225AD@az33exm22.fsl.freescale.net>
Liew Tsi Chung wrote:
> Jerry,
>
> The calculation you provided does not work, I tried it before.
> The best approach is reverse calculation after finding the closer
> counter (or divider), then find the smaller gap to the bus frequency.
>
> Using the calculation without the fix: counter = ((bus_freq / baudrate)
> + 31 )/ 32
Where are you getting the +31 from? Is this in the User's Manual?
> Bus freq 140Mhz and baudrate 115200
>
> counter = ((140000000 / 115200) + 31) / 32
> counter = 38
>
> However, the 38 divider shows partial garbage message when output to the
> terminal.
>
> Now, perform reverse calculation to obtain bus frequency.
> bus_freq = ((counter * 32) - 31) * 115200
Computations are for mathematicians. Real engineers measure the actual
frequency. ;-)
If you change the " - 31" to " - 42", your computations will result in a
different divisor. Why are you subtracting what appears to be an
arbitrary number (31)?
> bus_freq = ((38 * 32) - 31) * 115200
> bus_freq = 136512000
> diff = 140000000 - 136512000 = 3488000
>
> counter bus_freq diff
> ======= ========= =======
> 36 129139200 way too off!
> 37 132825600 7174400
> 38 136512000 3488000
> 39 140198400 198400 <=== Work@this counter! Small
> diff.
> 40 143884800 3884800
>
> Regards,
> TsiChung
Are you sure your input frequency is 140MHz and not 144MHZ??? Have you
read the itty-bitty numbers on the crystal? Have you put a scope on it
and actually measured it? Never trust those hardware people. ;-)
Looking at the MFC5407 (arbitrarily, not knowing what processor you
have), the dividers are as expected and *do not* match your "- 31"
calculations. They have a simple example and simple math that matches
(no "- 31").
Hmmm, the MFC5407 has a max CLKIN (and thus bus clock) of 54MHz. You
must have a different flavor. MFC548x maxes at 50MHz. What processor
are you using? Ahh, MFC5249 has a 140MHz bus. Still is a straight
forward divide-by n*32, no "- 31".
gvb
> -----Original Message-----
> From: Jerry Van Baren [mailto:gerald.vanbaren at ge.com]
> Sent: Wednesday, May 28, 2008 1:45 PM
> To: Liew Tsi Chung
> Cc: U-Boot-Users; Wolfgang Denx; Rigby John
> Subject: Re: [U-Boot-Users] [PATCH] ColdFire: Fix UART baudrate at
> 115200
>
> Tsi-Chung.Liew wrote:
>> From: TsiChung Liew <Tsi-Chung.Liew@freescale.com>
>>
>> If bus frequency is larger than 133MHz, the UART cannot output
>> baudrate at 115200 correctly.
>>
>> Signed-off-by: TsiChung Liew <Tsi-Chung.Liew@freescale.com>
>> ---
>> drivers/serial/mcfuart.c | 5 ++++-
>> 1 files changed, 4 insertions(+), 1 deletions(-)
>>
>> diff --git a/drivers/serial/mcfuart.c b/drivers/serial/mcfuart.c index
>
>> 88f3eb1..fca76bd 100644
>> --- a/drivers/serial/mcfuart.c
>> +++ b/drivers/serial/mcfuart.c
>> @@ -64,7 +64,10 @@ int serial_init(void)
>>
>> /* Setting up BaudRate */
>> counter = (u32) (gd->bus_clk / (gd->baudrate));
>> - counter >>= 5;
>> + counter = (counter + 31) >> 5;
>> +
>> + if ((gd->bus_clk > 133333333) && (gd->baudrate >= 115200))
>> + counter++;
>>
>> /* write to CTUR: divide counter upper byte */
>> uart->ubg1 = (u8) ((counter & 0xff00) >> 8);
>
> This doesn't look right at all. It looks like you are patching up
> integer math problems by using different bad math and then special
> casing the result. (In the metal working world, this is known as
> "measure with a micrometer, mark with chalk, cut with a torch, and grind
> to fit.")
>
> Part A:
> -------
> > counter = (u32) (gd->bus_clk / (gd->baudrate));
>
> If you want this to be more accurate, you should round it:
>
> > counter = (u32) ((gd->bus_clk + (gd->baudrate / 2)) /
> (gd->baudrate));
>
> Part B:
> -------
> > + counter = (counter + 31) >> 5;
>
> This is not rounding properly, it is doing a "ceiling".
>
> > + counter = (counter + 16) >> 5;
>
> Part C:
> -------
>
> > + if ((gd->bus_clk > 133333333) && (gd->baudrate >= 115200))
> > + counter++;
>
> This looks totally bogus. I very strongly suspect you need this because
> the above parts A: and B: are not rounding the division math properly,
> resulting in a wrong divisor *for your configuration*. While the above
> conditional may result in the correct divisor *for your configuration,*
> it probably will be wrong for some finite set of *other* configurations.
>
> If I got my algebra correct and my parenthesis balanced, I believe the
> above is trying to calculate the following formula:
> counter = (u32) (
> ((gd->bus_clk + (gd->baudrate / 2) +
> (gd->baudrate * 16))
> / (gd->baudrate * 32);
>
> Note, however, that (gd->baudrate / 2) is going to be relatively small
> compared to gd->bus_clk and (gd->baudrate * 16), so I suspect that the
> above formula could be changed to the following formula with no
> significant impact in accuracy:
> counter = (u32) (
> ((gd->bus_clk + (gd->baudrate * 16))
> / (gd->baudrate * 32);
>
> Hmmmm, checking the math with 133e6 for the bus rate with full precision
> math (i.e. a calculator), I get a divisor value of 36.08 (truncated to
> an integer => 36). Your hack-math results in a divisor of 38. The last
> formula I proposed above result in a divisor of 36.58 (truncated to an
> integer => 36). That checks.
>
> Real math => 36.08
> Hack-math => 38 (109375 baud => 5.1% off)
> Last formula => 36 (115451 baud => 0.2% off)
>
> For 160e6 bus frequency:
> Real math => 43.40
> Hack-math => 44 (113636 baud => 1.4% off)
> Last formula => 43 (116279 baud => 0.1% off)
>
> I don't see how your formula works (well, actually it works but only
> because async serial can handle ~10% error). In fact, it looks to me
> that your "correction" actually results in *more* error than the
> original calculation *without* rounding. What is your actual bus speed?
>
> What are to using on the other end of the serial line - I'm wondering
> if your receiver end is substantially off, causing a stack-up error that
> is causing your problem??? Is your board hardware marginal at 115200
> baud - what does it look like on a scope???
>
> Best regards,
> gvb
>
next prev parent reply other threads:[~2008-05-28 21:29 UTC|newest]
Thread overview: 7+ messages / expand[flat|nested] mbox.gz Atom feed top
2008-05-28 18:05 [U-Boot-Users] [PATCH] ColdFire: Fix UART baudrate at 115200 Tsi-Chung.Liew
2008-05-28 18:45 ` Jerry Van Baren
2008-05-28 20:05 ` Liew Tsi Chung
2008-05-28 21:29 ` Jerry Van Baren [this message]
2008-05-28 23:35 ` Liew Tsi Chung
2008-05-29 3:56 ` Jerry Van Baren
2008-05-29 16:45 ` Liew Tsi Chung
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=483DCEB1.3040509@ge.com \
--to=gerald.vanbaren@ge.com \
--cc=u-boot@lists.denx.de \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.