Skip to content

Instantly share code, notes, and snippets.

@lupyuen
Last active June 16, 2024 17:02
Show Gist options
  • Save lupyuen/4df6624c9691149099f177a18618e6a7 to your computer and use it in GitHub Desktop.
Save lupyuen/4df6624c9691149099f177a18618e6a7 to your computer and use it in GitHub Desktop.
Apache NuttX RTOS 16550 UART Driver: Print Baud Divisor. See https://lupyuen.github.io/articles/release#appendix-uart-clock-for-jh7110
// Output for Star64 JH7110: dlm=0x0, dll=0xd
// Output for Milk-V Duo S / Sophgo SG2000: dlm=0x0, dll=0xe
/****************************************************************************
* Name: u16550_setup
*
* Description:
* Configure the UART baud, bits, parity, fifos, etc. This
* method is called the first time that the serial port is
* opened.
*
****************************************************************************/
static int u16550_setup(FAR struct uart_dev_s *dev)
{
#ifndef CONFIG_16550_SUPRESS_CONFIG
FAR struct u16550_s *priv = (FAR struct u16550_s *)dev->priv;
uint16_t div;
uint32_t lcr;
#if defined(CONFIG_SERIAL_IFLOWCONTROL) || defined(CONFIG_SERIAL_OFLOWCONTROL)
uint32_t mcr;
#endif
/* Clear fifos */
u16550_serialout(priv, UART_FCR_OFFSET,
(UART_FCR_RXRST | UART_FCR_TXRST));
/* Set trigger */
u16550_serialout(priv, UART_FCR_OFFSET,
(UART_FCR_FIFOEN | UART_FCR_RXTRIGGER_8));
/* Set up the IER */
priv->ier = u16550_serialin(priv, UART_IER_OFFSET);
/* Set up the LCR */
lcr = 0;
switch (priv->bits)
{
case 5 :
lcr |= UART_LCR_WLS_5BIT;
break;
case 6 :
lcr |= UART_LCR_WLS_6BIT;
break;
case 7 :
lcr |= UART_LCR_WLS_7BIT;
break;
default:
case 8 :
lcr |= UART_LCR_WLS_8BIT;
break;
}
if (priv->stopbits2)
{
lcr |= UART_LCR_STB;
}
if (priv->parity == 1)
{
lcr |= UART_LCR_PEN;
}
else if (priv->parity == 2)
{
lcr |= (UART_LCR_PEN | UART_LCR_EPS);
}
#ifdef CONFIG_16550_WAIT_LCR
/* Wait till UART is not busy before setting LCR */
if (u16550_wait(priv) < 0)
{
_err("UART wait failed\n");
return ERROR;
}
#endif /* CONFIG_16550_WAIT_LCR */
/* Enter DLAB=1 */
u16550_serialout(priv, UART_LCR_OFFSET, (lcr | UART_LCR_DLAB));
uint32_t dlm = u16550_serialin(priv, UART_DLM_OFFSET);////
uint32_t dll = u16550_serialin(priv, UART_DLL_OFFSET);////
#ifdef TODO ////
/* Set the BAUD divisor */
div = u16550_divisor(priv);
u16550_serialout(priv, UART_DLM_OFFSET, div >> 8);
u16550_serialout(priv, UART_DLL_OFFSET, div & 0xff);
#endif //// TODO
#ifdef CONFIG_16550_WAIT_LCR
/* Wait till UART is not busy before setting LCR */
if (u16550_wait(priv) < 0)
{
_err("UART wait failed\n");
return ERROR;
}
#endif /* CONFIG_16550_WAIT_LCR */
/* Clear DLAB */
u16550_serialout(priv, UART_LCR_OFFSET, lcr);
/* Configure the FIFOs */
u16550_serialout(priv, UART_FCR_OFFSET,
(UART_FCR_RXTRIGGER_8 | UART_FCR_TXRST | UART_FCR_RXRST |
UART_FCR_FIFOEN));
/* Set up the auto flow control */
#if defined(CONFIG_SERIAL_IFLOWCONTROL) || defined(CONFIG_SERIAL_OFLOWCONTROL)
mcr = u16550_serialin(priv, UART_MCR_OFFSET);
if (priv->flow)
{
mcr |= UART_MCR_AFCE;
}
else
{
mcr &= ~UART_MCR_AFCE;
}
mcr |= UART_MCR_RTS;
u16550_serialout(priv, UART_MCR_OFFSET, mcr);
#endif /* defined(CONFIG_SERIAL_IFLOWCONTROL) || defined(CONFIG_SERIAL_OFLOWCONTROL) */
/* Reconfigure DMA Rx timeout value */
#ifdef HAVE_16550_UART_DMA
u16550_dmarxconfig(dev);
#endif
#endif
_info("dlm=0x%x, dll=0x%x\n", dlm, dll);////
return OK;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment