[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: [avr-libc-dev] [bugs #11396] Large number jumps to hyperspace
From: |
Joerg Wunsch |
Subject: |
Re: [avr-libc-dev] [bugs #11396] Large number jumps to hyperspace |
Date: |
Thu, 30 Dec 2004 20:59:34 +0100 |
User-agent: |
Mutt/1.4.2.1i |
As Russell Shaw wrote:
> >>> uint16_t baud=9600
> >>> uint16_t reg=16000000/(16*baud) - 1;
> >what about __udivmodsi4?
Yeah. I didn't assume such poor optimization.
> In the real code, uint16_t baud was set at 9600 using a const
> literal passed as an array parameter.
As Eric just closed the bug report as being unreproducible, I gave it
a try to simulate your example code. I cannot reproduce any ``jumps
to nowhere'' behaviour though (and thus basically confirm Eric's
judgement).
However, your above example miscalculates `reg', as the expression
``16*baud'' is computed in uint16_t domain but overflows it. The
result of this subexpression is 153600 but is truncated to 22528.
Maybe this is your problem?
Rewriting the second calculation as:
uint16_t reg=16000000/(16*(unsigned long)baud) - 1;
makes it work for me. Though this is technically right, I think
most people would prefer
uint16_t reg=16000000UL/(16*(unsigned long)baud) - 1;
instead to make it explicit that the clock frequency is also an
unsigned long (even though the C standard is on your side and you're
permitted to omit the `UL'). Writing the UL suffix is also sufficient
to force the entire expression into the UL domain, so this works, too:
uint16_t reg=16000000UL/(16*baud) - 1;
Still, I'd personally prefer the previous version since it makes it
explicit. C type promotion rules are often not easy to understand at
a first glance.
--
cheers, J"org .-.-. --... ...-- -.. . DL8DTL
http://www.sax.de/~joerg/ NIC: JW11-RIPE
Never trust an operating system you don't have sources for. ;-)