📜 ⬆️ ⬇️

Calculation of prescaler parameters for 8250-compatible USART

This evening I will tell you a tale about how you can effectively calculate the parameters of the prescaler, which is usually used to set the USART clock frequency of the ports, in particular the 8250-compatible, used in the Intel SoC.


Currently there are at least two Intel SoC lines that use a fractional prescaler USART.
  1. Medfield, CloverTrail, Tangier
  2. BayTrail, Braswell

What is the difference between them, I'll tell you later.

Below are the formulas by which Fusart is calculated — the USART clock frequency, and baud — the transmission rate.
')



Rest
Fref is the frequency before the prescaler, m is the numerator, n is the denominator of the rational fraction of the prescaler, prescaler is the integer divided by Fusart , DLAB is the 16-bit divider presented in 8250-compatible chips.

Of the entire set, we know only two quantities, namely: Fref and baud . The size of the prescaler is usually equal to 16 and in some chips there is no possibility to change it (this is precisely what distinguishes the Intel SoC lines from each other)

Calculation of prescaler



Since we are working with a fractional prescaler, and not with a full PLL, then from (1) it follows




And therefore we can already calculate the value of the prescaler
prescaler = 16 fusart = baud * prescaler if fref < fusart: if fref >= baud: prescaler = fref / baud else: prescaler = 1 fusart = baud * prescaler 


Fusart calculation



The previous part only works if it does not (3) . Otherwise, the Fusart can be very low relative to Fref at the requested rather low transmission rate, for example 110 baud.

And since the numerator and denominator of the divider are usually of equal width (in bits), it would be nice to limit their divergence. To do this, let's bring Fusart to Fref as much as possible.
 fusart <<= int(math.log(fref / fusart, 2)) 

Why was this approach chosen? The thing is, if we have an overflow of DLAB , and it is only 16-bit, then in the case of the use of the power of two, we can track it with the simplest bit operations.

The queue for the denominator



Obviously, now from (1,2) , there follows a simple proportion



Thus, we can easily calculate the numerator and denominator of the rational fraction prescaler.
 divisor = gcd(fref, fusart) n = fref / divisor while n > (2 ** width - 1): divisor <<= 1 n >>= 1 m = fusart / divisor 


Here, width is the width in bits of the numerator and denominator.

That's all. For those who wish, the source code in Python can be found on GitHub Gist (it has already been updated several times and may be updated in the future).

Example calculation for Fref = 50MHz, width = 24 bits
The output is in the format 1) m , 2) n , 3) prescaler , 4) Fusart , 5) a mysterious number, 6) a list of transmission rates, in brackets the value DLAB .

24 25 12 48000000 64000000 4000000 (1)
49 50 14 49000000 56000000 3.5 million (1)
4 5 16 40 000 000 40 000 000 2500 000 (1)
16 25 16 320000 32000000 500000 (4), 1,000,000 (2), 2,000,000 (1)
24 25 16 48000000 48000000 1500000 (2), 3000000 (1)
2304 3125 16 36864000 36864000 576000 (4), 1152000 (2)
8192 15625 16 26214400 26214400 50 (32768), 200 (8192)
9216 15625 16 29491200 29491200 1800 (1024), 57600 (32), 115200 (16), 230400 (8), 460800 (4), 921600 (2), 1843200 (1)
12288 15625 16 39321600 39321600 75 (32768), 150 (16384), 300 (8192), 600 (4096), 1200 (2048), 2400 (1024), 4800 (512), 9600 (256), 19200 (128), 38400 (64)
45056 78125 16 28835840 28835840 110 (16384)
274432 390625 16 35127296 35127296 134 (16384)


Please note that the above algorithm is simple and fast, although not so accurate, but it satisfies our goal.

Source: https://habr.com/ru/post/252833/


All Articles