Skip to content

Commit 28304b5

Browse files
uart: fixing baud divisor calculation to add support for 230400 bps
Added code to configure the UART fractional divisor to improve the UART timing at higher speeds such as 230400, 460800 and 921600 bps. Signed-off-by: Dan O'Donovan <dan@emutex.com>
1 parent b96562d commit 28304b5

File tree

2 files changed

+12
-1
lines changed

2 files changed

+12
-1
lines changed

system/libarc32_edu/drivers/ns16550.c

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,7 @@ INCLUDE FILES: drivers/uart.h
8282
#define REG_MDC 0x04 /* Modem control reg. */
8383
#define REG_LSR 0x05 /* Line status reg. */
8484
#define REG_MSR 0x06 /* Modem status reg. */
85+
#define REG_DLF 0x30 /* Divisor Latch Fraction. */
8586

8687
/* equates for interrupt enable register */
8788

@@ -203,6 +204,7 @@ INCLUDE FILES: drivers/uart.h
203204
#define MDC(n) (uart[n].port + REG_MDC * UART_REG_ADDR_INTERVAL)
204205
#define LSR(n) (uart[n].port + REG_LSR * UART_REG_ADDR_INTERVAL)
205206
#define MSR(n) (uart[n].port + REG_MSR * UART_REG_ADDR_INTERVAL)
207+
#define DLF(n) (uart[n].port + REG_DLF * UART_REG_ADDR_INTERVAL)
206208

207209
#define IIRC(n) uart[n].iirCache
208210

@@ -247,7 +249,7 @@ void uart_init(int which, /* UART channel to initialize */
247249
)
248250
{
249251
unsigned int oldLevel; /* old interrupt lock level */
250-
uint32_t divisor; /* baud rate divisor */
252+
uint32_t divisor, fdivisor, tmp; /* baud rate divisors */
251253
uint8_t mdc = 0;
252254

253255
uart[which].port = init_info->regs;
@@ -257,13 +259,22 @@ void uart_init(int which, /* UART channel to initialize */
257259

258260
oldLevel = interrupt_lock();
259261

262+
/* The formula for calculating these baud rate divisors is:
263+
* baud rate = (Fbase) / (16 * (divisor+(fdivisor/16))
264+
*/
265+
260266
/* calculate baud rate divisor */
261267
divisor = (init_info->sys_clk_freq / init_info->baud_rate) >> 4;
268+
/* Calculate baud rate fractional divisor from the remainder.
269+
* The result is rounded to the nearest whole number */
270+
tmp = init_info->baud_rate >> 4;
271+
fdivisor = (((init_info->sys_clk_freq >> 4) % init_info->baud_rate) + (tmp >> 1)) / tmp;
262272

263273
/* set the DLAB to access the baud rate divisor registers */
264274
OUTBYTE(LCR(which), LCR_DLAB);
265275
OUTBYTE(BRDL(which), (unsigned char)(divisor & 0xff));
266276
OUTBYTE(BRDH(which), (unsigned char)((divisor >> 8) & 0xff));
277+
OUTBYTE(DLF(which), (unsigned char)(fdivisor & 0xf));
267278

268279
/* specify the format of the asynchronous data communication exchange */
269280
OUTBYTE(LCR(which), init_info->async_format);
248 Bytes
Binary file not shown.

0 commit comments

Comments
 (0)