# Calculation of pre-splitter parameters for 8250-compatible USART

- Tutorial

Tonight I will tell a ~~fairy tale~~ on how to efficiently calculate the parameters of the splitter, which is usually used to set the clock frequency of USART ports, in particular the 8250-compatible ones used in Intel SoC.

At the moment, there are at least two lines of Intel SoC that use USART with a fractional pre-divider

What is the difference between them, I will tell a little later.

Below are the formulas used to calculate

The remaining

From the whole set, we know only two quantities, namely:

### Calculation of

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

And therefore, we can already calculate the

The previous part only works if it is not satisfied (3) . Otherwise,

And since the numerator and denominator of the divider are usually of equal width (in bits), it would be nice to limit their discrepancy. To do this, bring

Why is this approximation chosen? The thing is, if we have

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

Thus, we easily calculate the numerator and denominator of the rational fraction of the pre-divisor.

Here

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

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

At the moment, there are at least two lines of Intel SoC that use USART with a fractional pre-divider

- Medfield, CloverTrail, Tangier
- BayTrail, Braswell

What is the difference between them, I will tell a little later.

Below are the formulas used to calculate

*Fusart*- USART clock frequency, and*baud*-*baud*rate.The remaining

*Frefs*are the frequency before the pre-divider,*m*is the numerator,*n*is the denominator of the rational fraction of the pre-divider,*prescaler*is the integer by which*Fusart*is divided ,*DLAB*is the 16-bit divider, presented in 8250-compatible chips.From the whole set, we know only two quantities, namely:

*Fref*and*baud*. The value of*prescaler*is usually equal to 16 and in some chips there is no possibility to change it (this is what distinguishes the Intel SoC line from each other)### Calculation of *prescaler*

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

And therefore, we can already calculate the

*prescaler*value```
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 is not satisfied (3) . Otherwise,

*Fusart*may turn out to be very low relative to*Fref*at the requested rather low bit 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 discrepancy. To do this, bring

*Fusart*to*Fref*as far as possible.```
fusart <<= int(math.log(fref / fusart, 2))
```

Why is this approximation chosen? The thing is, if we have

*DLAB*overflow , and it is only 16-bit, then if we use the power of two, we can track this with the simplest bit operations.### Denominator Queue

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

Thus, we easily calculate the numerator and denominator of the rational fraction of the pre-divisor.

```
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 for Python can be found on the GitHub Gist (it has already been updated several times and may be updated in the future).

**Calculation example for Fref = 50MHz, width = 24 bits**

Вывод в формате 1)

24 25 12 48000000 64000000 4000000(1)

49 50 14 49000000 56000000 3500000(1)

4 5 16 40000000 40000000 2500000(1)

16 25 16 32000000 32000000 500000(4),1000000(2),2000000(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)

*m*, 2)*n*, 3)*prescaler*, 4)*Fusart*, 5) загадочное число, 6) список скоростей передачи, в скобках значение*DLAB*.24 25 12 48000000 64000000 4000000(1)

49 50 14 49000000 56000000 3500000(1)

4 5 16 40000000 40000000 2500000(1)

16 25 16 32000000 32000000 500000(4),1000000(2),2000000(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.