mirror of
https://github.com/apache/nuttx.git
synced 2026-05-28 03:45:50 +08:00
stm32l5/nucleo-l552ze: enable LPUART1 console on ST-Link VCP
Three fixes to make LPUART1 work as NSH console on Nucleo-L552ZE-Q: 1. stm32l5_lowputc: add LPUART-specific BRR formula (256 * fCK / baud) instead of reusing the standard USART divisor calculation. 2. stm32_boot: enable VDDIO2 and reconfigure LPUART1 GPIOs (PG7/PG8) in board_initialize. The low-level setup runs before VDDIO2 is enabled, so GPIOG writes silently fail. 3. stm32l5_serial: fix LPUART1 apbclock (PCLK1 not PCLK2), add LPUART BRR branch in setformat, cast to uint64_t to prevent 32-bit overflow in (fCK << 8). Also switch nsh defconfig from USART3 to LPUART1, add GPIO_LPUART1 pin definitions in board.h, and update board documentation. Signed-off-by: anjiahao <anjiahao@xiaomi.com>
This commit is contained in:
@@ -114,18 +114,27 @@ Use make menuconfig to configure USART3 as the console::
|
|||||||
CONFIG_USART3_PARITY=0
|
CONFIG_USART3_PARITY=0
|
||||||
CONFIG_USART3_2STOP=0
|
CONFIG_USART3_2STOP=0
|
||||||
|
|
||||||
Virtual COM Port
|
LPUART1 - Virtual COM Port (Default)
|
||||||
----------------
|
-------------------------------------
|
||||||
Yet another option is to use LPUART1 and the USB virtual COM port. This
|
The default nsh configuration uses LPUART1 on the ST-Link USB virtual COM
|
||||||
option may be more convenient for long term development, but is painful
|
port. LPUART1 TX/RX are on PG7/PG8 which are powered by VDDIO2.
|
||||||
to use during board bring-up. However as LPUART peripheral has not been
|
|
||||||
implemented for STM32L5, this cannot currently be used.
|
|
||||||
|
|
||||||
Solder Bridges. This configuration requires::
|
Solder Bridges (active by default on Nucleo-L552ZE-Q)::
|
||||||
|
|
||||||
PG7 LPUART1 TX SB127 ON and SB124 OFF (Default)
|
PG7 LPUART1 TX SB127 ON and SB124 OFF (Default)
|
||||||
PG8 LPUART1 RX SB129 ON and SB126 OFF (Default)
|
PG8 LPUART1 RX SB129 ON and SB126 OFF (Default)
|
||||||
|
|
||||||
|
Use make menuconfig to configure LPUART1 as the console::
|
||||||
|
|
||||||
|
CONFIG_STM32L5_LPUART1=y
|
||||||
|
CONFIG_LPUART1_SERIAL_CONSOLE=y
|
||||||
|
CONFIG_LPUART1_RXBUFSIZE=256
|
||||||
|
CONFIG_LPUART1_TXBUFSIZE=256
|
||||||
|
CONFIG_LPUART1_BAUD=115200
|
||||||
|
CONFIG_LPUART1_BITS=8
|
||||||
|
CONFIG_LPUART1_PARITY=0
|
||||||
|
CONFIG_LPUART1_2STOP=0
|
||||||
|
|
||||||
You can also put USART3 on the virtual COM port by reworking the solder
|
You can also put USART3 on the virtual COM port by reworking the solder
|
||||||
bridges as follows::
|
bridges as follows::
|
||||||
|
|
||||||
@@ -134,7 +143,7 @@ bridges as follows::
|
|||||||
|
|
||||||
Default
|
Default
|
||||||
-------
|
-------
|
||||||
As shipped, the virtual COM port is enabled.
|
As shipped, the virtual COM port is connected to LPUART1.
|
||||||
|
|
||||||
Configurations
|
Configurations
|
||||||
==============
|
==============
|
||||||
@@ -170,23 +179,9 @@ NOTES:
|
|||||||
b. Execute 'make menuconfig' in nuttx/ in order to start the
|
b. Execute 'make menuconfig' in nuttx/ in order to start the
|
||||||
reconfiguration process.
|
reconfiguration process.
|
||||||
|
|
||||||
2. Unless stated otherwise, all configurations generate console
|
2. The default nsh configuration generates console output on LPUART1
|
||||||
output on USART3, as described above under "Serial Console". The
|
via the ST-Link virtual COM port. See "Serial Consoles" above for
|
||||||
elevant configuration settings are listed below::
|
details and alternative USART3 configuration.
|
||||||
|
|
||||||
CONFIG_STM32L5_USART3=y
|
|
||||||
CONFIG_STM32L5_USART3_SERIALDRIVER=y
|
|
||||||
CONFIG_STM32L5_USART=y
|
|
||||||
|
|
||||||
CONFIG_USART3_SERIALDRIVER=y
|
|
||||||
CONFIG_USART3_SERIAL_CONSOLE=y
|
|
||||||
|
|
||||||
CONFIG_USART3_RXBUFSIZE=256
|
|
||||||
CONFIG_USART3_TXBUFSIZE=256
|
|
||||||
CONFIG_USART3_BAUD=115200
|
|
||||||
CONFIG_USART3_BITS=8
|
|
||||||
CONFIG_USART3_PARITY=0
|
|
||||||
CONFIG_USART3_2STOP=0
|
|
||||||
|
|
||||||
3. All of these configurations are set up to build under Linux using the
|
3. All of these configurations are set up to build under Linux using the
|
||||||
"GNU Tools for ARM Embedded Processors" that is maintained by ARM
|
"GNU Tools for ARM Embedded Processors" that is maintained by ARM
|
||||||
|
|||||||
@@ -222,6 +222,21 @@
|
|||||||
|
|
||||||
/* Calculate USART BAUD rate divider */
|
/* Calculate USART BAUD rate divider */
|
||||||
|
|
||||||
|
# if defined(CONFIG_LPUART1_SERIAL_CONSOLE)
|
||||||
|
|
||||||
|
/* Baud rate for LPUART:
|
||||||
|
*
|
||||||
|
* baud = 256 * fCK / LPUARTDIV
|
||||||
|
* LPUARTDIV = 256 * fCK / baud
|
||||||
|
*
|
||||||
|
* LPUARTDIV must be in range [0x300, 0xFFFFF].
|
||||||
|
*/
|
||||||
|
|
||||||
|
# define STM32L5_BRR_VALUE \
|
||||||
|
((((uint64_t)STM32L5_APBCLOCK << 8) + (STM32L5_CONSOLE_BAUD >> 1)) / STM32L5_CONSOLE_BAUD)
|
||||||
|
|
||||||
|
# else
|
||||||
|
|
||||||
/* Baud rate for standard USART (SPI mode included):
|
/* Baud rate for standard USART (SPI mode included):
|
||||||
*
|
*
|
||||||
* In case of oversampling by 16, the equation is:
|
* In case of oversampling by 16, the equation is:
|
||||||
@@ -249,6 +264,8 @@
|
|||||||
((STM32L5_USARTDIV8 & 0xfff0) | ((STM32L5_USARTDIV8 & 0x000f) >> 1))
|
((STM32L5_USARTDIV8 & 0xfff0) | ((STM32L5_USARTDIV8 & 0x000f) >> 1))
|
||||||
# endif
|
# endif
|
||||||
|
|
||||||
|
# endif /* CONFIG_LPUART1_SERIAL_CONSOLE */
|
||||||
|
|
||||||
#endif /* HAVE_CONSOLE */
|
#endif /* HAVE_CONSOLE */
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
|
|||||||
@@ -476,7 +476,7 @@ static struct stm32l5_serial_s g_lpuart1priv =
|
|||||||
.bits = CONFIG_LPUART1_BITS,
|
.bits = CONFIG_LPUART1_BITS,
|
||||||
.stopbits2 = CONFIG_LPUART1_2STOP,
|
.stopbits2 = CONFIG_LPUART1_2STOP,
|
||||||
.baud = CONFIG_LPUART1_BAUD,
|
.baud = CONFIG_LPUART1_BAUD,
|
||||||
.apbclock = STM32L5_PCLK2_FREQUENCY,
|
.apbclock = STM32L5_PCLK1_FREQUENCY,
|
||||||
.usartbase = STM32L5_LPUART1_BASE,
|
.usartbase = STM32L5_LPUART1_BASE,
|
||||||
.tx_gpio = GPIO_LPUART1_TX,
|
.tx_gpio = GPIO_LPUART1_TX,
|
||||||
.rx_gpio = GPIO_LPUART1_RX,
|
.rx_gpio = GPIO_LPUART1_RX,
|
||||||
@@ -1021,51 +1021,37 @@ static void stm32l5serial_setformat(struct uart_dev_s *dev)
|
|||||||
uint32_t cr1;
|
uint32_t cr1;
|
||||||
uint32_t brr;
|
uint32_t brr;
|
||||||
|
|
||||||
/* In case of oversampling by 8, the equation is:
|
#ifdef CONFIG_STM32L5_LPUART1_SERIALDRIVER
|
||||||
*
|
if (priv->usartbase == STM32L5_LPUART1_BASE)
|
||||||
* baud = 2 * fCK / usartdiv8
|
|
||||||
* usartdiv8 = 2 * fCK / baud
|
|
||||||
*/
|
|
||||||
|
|
||||||
usartdiv8 = ((priv->apbclock << 1) + (priv->baud >> 1)) / priv->baud;
|
|
||||||
|
|
||||||
/* Baud rate for standard USART (SPI mode included):
|
|
||||||
*
|
|
||||||
* In case of oversampling by 16, the equation is:
|
|
||||||
* baud = fCK / usartdiv16
|
|
||||||
* usartdiv16 = fCK / baud
|
|
||||||
* = 2 * usartdiv8
|
|
||||||
*/
|
|
||||||
|
|
||||||
/* Use oversamply by 8 only if the divisor is small. But what is small? */
|
|
||||||
|
|
||||||
cr1 = stm32l5serial_getreg(priv, STM32L5_USART_CR1_OFFSET);
|
|
||||||
if (usartdiv8 > 2000)
|
|
||||||
{
|
{
|
||||||
/* Use usartdiv16 */
|
/* LPUART BRR = 256 * fCK / baud */
|
||||||
|
|
||||||
brr = (usartdiv8 + 1) >> 1;
|
brr = (((uint64_t)priv->apbclock << 8) +
|
||||||
|
(priv->baud >> 1)) / priv->baud;
|
||||||
/* Clear oversampling by 8 to enable oversampling by 16 */
|
stm32l5serial_putreg(priv, STM32L5_USART_BRR_OFFSET, brr);
|
||||||
|
|
||||||
cr1 &= ~USART_CR1_OVER8;
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
#endif
|
||||||
{
|
{
|
||||||
DEBUGASSERT(usartdiv8 >= 8);
|
usartdiv8 = ((priv->apbclock << 1) + (priv->baud >> 1)) / priv->baud;
|
||||||
|
|
||||||
/* Perform mysterious operations on bits 0-3 */
|
cr1 = stm32l5serial_getreg(priv, STM32L5_USART_CR1_OFFSET);
|
||||||
|
if (usartdiv8 > 2000)
|
||||||
|
{
|
||||||
|
brr = (usartdiv8 + 1) >> 1;
|
||||||
|
cr1 &= ~USART_CR1_OVER8;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
DEBUGASSERT(usartdiv8 >= 8);
|
||||||
|
brr = ((usartdiv8 & 0xfff0) | ((usartdiv8 & 0x000f) >> 1));
|
||||||
|
cr1 |= USART_CR1_OVER8;
|
||||||
|
}
|
||||||
|
|
||||||
brr = ((usartdiv8 & 0xfff0) | ((usartdiv8 & 0x000f) >> 1));
|
stm32l5serial_putreg(priv, STM32L5_USART_CR1_OFFSET, cr1);
|
||||||
|
stm32l5serial_putreg(priv, STM32L5_USART_BRR_OFFSET, brr);
|
||||||
/* Set oversampling by 8 */
|
|
||||||
|
|
||||||
cr1 |= USART_CR1_OVER8;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
stm32l5serial_putreg(priv, STM32L5_USART_CR1_OFFSET, cr1);
|
|
||||||
stm32l5serial_putreg(priv, STM32L5_USART_BRR_OFFSET, brr);
|
|
||||||
|
|
||||||
/* Configure parity mode */
|
/* Configure parity mode */
|
||||||
|
|
||||||
regval = stm32l5serial_getreg(priv, STM32L5_USART_CR1_OFFSET);
|
regval = stm32l5serial_getreg(priv, STM32L5_USART_CR1_OFFSET);
|
||||||
|
|||||||
@@ -35,6 +35,7 @@ CONFIG_INPUT=y
|
|||||||
CONFIG_INPUT_BUTTONS=y
|
CONFIG_INPUT_BUTTONS=y
|
||||||
CONFIG_INPUT_BUTTONS_LOWER=y
|
CONFIG_INPUT_BUTTONS_LOWER=y
|
||||||
CONFIG_LINE_MAX=64
|
CONFIG_LINE_MAX=64
|
||||||
|
CONFIG_LPUART1_SERIAL_CONSOLE=y
|
||||||
CONFIG_NSH_ARCHINIT=y
|
CONFIG_NSH_ARCHINIT=y
|
||||||
CONFIG_NSH_BUILTIN_APPS=y
|
CONFIG_NSH_BUILTIN_APPS=y
|
||||||
CONFIG_NSH_DISABLE_IFUPDOWN=y
|
CONFIG_NSH_DISABLE_IFUPDOWN=y
|
||||||
@@ -49,11 +50,10 @@ CONFIG_READLINE_TABCOMPLETION=y
|
|||||||
CONFIG_RR_INTERVAL=200
|
CONFIG_RR_INTERVAL=200
|
||||||
CONFIG_SCHED_WAITPID=y
|
CONFIG_SCHED_WAITPID=y
|
||||||
CONFIG_STACK_COLORATION=y
|
CONFIG_STACK_COLORATION=y
|
||||||
|
CONFIG_STM32L5_LPUART1=y
|
||||||
CONFIG_STM32L5_RTC=y
|
CONFIG_STM32L5_RTC=y
|
||||||
CONFIG_STM32L5_RTC_AUTO_LSECLOCK_START_DRV_CAPABILITY=y
|
CONFIG_STM32L5_RTC_AUTO_LSECLOCK_START_DRV_CAPABILITY=y
|
||||||
CONFIG_STM32L5_USART3=y
|
|
||||||
CONFIG_SYSTEM_NSH=y
|
CONFIG_SYSTEM_NSH=y
|
||||||
CONFIG_SYSTEM_STACKMONITOR=y
|
CONFIG_SYSTEM_STACKMONITOR=y
|
||||||
CONFIG_SYSTEM_TEE=y
|
CONFIG_SYSTEM_TEE=y
|
||||||
CONFIG_TASK_NAME_SIZE=0
|
CONFIG_TASK_NAME_SIZE=0
|
||||||
CONFIG_USART3_SERIAL_CONSOLE=y
|
|
||||||
|
|||||||
@@ -173,6 +173,11 @@
|
|||||||
#define GPIO_USART3_RX GPIO_USART3_RX_4 /* PD9 */
|
#define GPIO_USART3_RX GPIO_USART3_RX_4 /* PD9 */
|
||||||
#define GPIO_USART3_TX GPIO_USART3_TX_4 /* PD8 */
|
#define GPIO_USART3_TX GPIO_USART3_TX_4 /* PD8 */
|
||||||
|
|
||||||
|
/* LPUART1: Connected to STLink VCP by default on Nucleo-L552ZE-Q */
|
||||||
|
|
||||||
|
#define GPIO_LPUART1_RX GPIO_LPUART1_RX_4 /* PG8 */
|
||||||
|
#define GPIO_LPUART1_TX GPIO_LPUART1_TX_4 /* PG7 */
|
||||||
|
|
||||||
/* LED definitions **********************************************************/
|
/* LED definitions **********************************************************/
|
||||||
|
|
||||||
/* The Nucleo-144 board has numerous LEDs but only three, LD1 a Green LED,
|
/* The Nucleo-144 board has numerous LEDs but only three, LD1 a Green LED,
|
||||||
|
|||||||
@@ -32,6 +32,8 @@
|
|||||||
|
|
||||||
#include "arm_internal.h"
|
#include "arm_internal.h"
|
||||||
#include "nucleo-l552ze.h"
|
#include "nucleo-l552ze.h"
|
||||||
|
#include "stm32l5_pwr.h"
|
||||||
|
#include "stm32l5_gpio.h"
|
||||||
|
|
||||||
#include <arch/board/board.h>
|
#include <arch/board/board.h>
|
||||||
|
|
||||||
@@ -52,6 +54,18 @@
|
|||||||
|
|
||||||
void stm32l5_board_initialize(void)
|
void stm32l5_board_initialize(void)
|
||||||
{
|
{
|
||||||
|
stm32l5_pwr_vddio2_valid(true);
|
||||||
|
|
||||||
|
#if defined(CONFIG_STM32L5_LPUART1)
|
||||||
|
/* LPUART1 uses PG7/PG8 which are powered by VDDIO2. The GPIO config in
|
||||||
|
* stm32l5_lowsetup() runs before VDDIO2 is enabled, so GPIOG writes
|
||||||
|
* silently fail. Reconfigure here after VDDIO2 is valid.
|
||||||
|
*/
|
||||||
|
|
||||||
|
stm32l5_configgpio(GPIO_LPUART1_TX);
|
||||||
|
stm32l5_configgpio(GPIO_LPUART1_RX);
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef CONFIG_ARCH_LEDS
|
#ifdef CONFIG_ARCH_LEDS
|
||||||
/* Configure on-board LEDs if LED support has been selected. */
|
/* Configure on-board LEDs if LED support has been selected. */
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user