OpenCores
no use no use 1/1 no use no use
Uart 16550
by kellya on Jul 12, 2011
kellya
Posts: 3
Joined: May 5, 2011
Last seen: Sep 19, 2011
It seems I found a bug in the UART 16550 core, and don't have a solution: when I try to send the character 0 (0x0, not '0') it modifies all the characters I send after that.

I really ned to send some 0 value for communicating with a iRobot Create...

I am using this core in the minsoc project, with the example code given with it.

Had someone experienced the same problem?

Thanks

Kellya
RE: Uart 16550
by yannv on Jul 12, 2011
yannv
Posts: 20
Joined: Feb 6, 2009
Last seen: Jan 14, 2021
This sounds much more likely to be a configuration issue than a hardware bug. How do those characters get modified? The serial protocol used by the 16550 is highly dependent on the baud rate matching in sender and recipient, and the particular value 0 (any value with leading 0s and trailing 1s, actually) has very few transitions to synchronize on (for smarter oversampling receivers). So you may have the baudrate a bit off, and it still works for most characters, but not these. If the 0 is received as a frame error, break or 1, this is likely what happened. Resynchronization occurs when you leave the line idle for a while.

What clock input, baud rate and DLL/DLM values are you using?
RE: Uart 16550
by kellya on Jul 13, 2011
kellya
Posts: 3
Joined: May 5, 2011
Last seen: Sep 19, 2011
The internal clock is at 100MHz, and I use a divider of 5. Then, in software, I kept the clock to 20MHz and my Baud rate is on the board and on the PC at 57600 Baud.
I do not receive particular character, but only garbage: I receive well the first 0 but, after it, the pattern seems to become random.

I did not found the solution yet, but your idea seems good because when I reduce the reception baud rate (so on the PC) I obtain again coherent results (if I send allways 0, I receive allways the same character, depending only on the baudrate I use).
RE: Uart 16550
by kellya on Jul 13, 2011
kellya
Posts: 3
Joined: May 5, 2011
Last seen: Sep 19, 2011
I forgot to say that I compute DLL and DLM this way:
divisor = IN_CLK/(16 * UART_BAUD_RATE);
REG8(UART_BASE + UART_DLM) = (divisor >> 8) & 0x000000ff;
REG8(UART_BASE + UART_DLL) = divisor & 0x000000ff;

with IN_CLK = 20000000 and UART_BAUD_RATE=57600
RE: Uart 16550
by yannv on Jul 14, 2011
yannv
Posts: 20
Joined: Feb 6, 2009
Last seen: Jan 14, 2021
Then it really does sound like a baud rate precision problem. 20MHz/57600baud is a factor of 3125/9 or 5^5/3^2, so it's not easily adjustable. The 16550 can only do division by whole multiples of 16, so cannot reach the optimal divider of 347.22.. (infinite 2s). It can do 21*16=336 or 22*16=352.

When you do your integer division, you end up truncating towards 0, which may not be the closest divider. A simple trick to get a closer rounding is to replace IN_CLK/(16 * UART_BAUD_RATE) with (IN_CLK/UART_BAUD_RATE+8)/16, since 8/16=0.5. You then get the divisor 22, resulting in 56.8kbaud rather than 59.5kbaud. This reduces your divider generated baud rate error from +3.3% to -1.4%. It could be enough to solve your immediate problem.

This can be one reason to choose a communication friendly crystal such as 49.152MHz instead of 50MHz; it is exactly 128 times 38400, though you'd still need one PLL layer to reach exactly 57600 (which is 3*19200).
no use no use 1/1 no use no use
© copyright 1999-2026 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.