[En-Nut-Discussion] Overflow in At91GetPllClock()

Ben Hoyt benhoyt at gmail.com
Mon Sep 11 05:55:57 CEST 2006

I'm using an 18.432MHz crystal with an AT91SAM7S256, and all was working
well till I changed my PLL multiply/divide ratio in the startup code

I want a precise 48.0MHz clock for USB, so I set my PLL ratio to *250/48,
since 18.432MHz*250/48 = 96.0MHz, and then there's another divide by 2 to
give 48.0MHz.

But At91GetPllClock() tries to calculate 18,432,000*250, which is
4,608,000,000 -- a nice 32-bit overflow which mucks up the timing. I've
fixed it by dividing the master clock frequency by 1000 beforehand, then
multiplying by 1000 afterwards ... probably not the ideal fix, but here it
is (from ostimer_at91.c):

static u_int At91GetPllClock(void)
    // divide by 1000 here then multiply at end to avoid 32-bit overflow
    u_int rc = AT91_PLL_MAINCK/1000;
    u_int pllr = inr(CKGR_PLLR);
    u_int divider = (pllr & CKGR_DIV) >> CKGR_DIV_LSB;

    if (divider) {
        rc *= ((pllr & CKGR_MUL) >> CKGR_MUL_LSB) + 1;
        rc /= divider;
    return rc*1000;

Ben Hoyt
Mobile: +64 21 331 841
Email: benhoyt at gmail.com

More information about the En-Nut-Discussion mailing list