mirror of
https://github.com/apache/nuttx.git
synced 2026-05-22 05:42:05 +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_2STOP=0
|
||||
|
||||
Virtual COM Port
|
||||
----------------
|
||||
Yet another option is to use LPUART1 and the USB virtual COM port. This
|
||||
option may be more convenient for long term development, but is painful
|
||||
to use during board bring-up. However as LPUART peripheral has not been
|
||||
implemented for STM32L5, this cannot currently be used.
|
||||
LPUART1 - Virtual COM Port (Default)
|
||||
-------------------------------------
|
||||
The default nsh configuration uses LPUART1 on the ST-Link USB virtual COM
|
||||
port. LPUART1 TX/RX are on PG7/PG8 which are powered by VDDIO2.
|
||||
|
||||
Solder Bridges. This configuration requires::
|
||||
Solder Bridges (active by default on Nucleo-L552ZE-Q)::
|
||||
|
||||
PG7 LPUART1 TX SB127 ON and SB124 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
|
||||
bridges as follows::
|
||||
|
||||
@@ -134,7 +143,7 @@ bridges as follows::
|
||||
|
||||
Default
|
||||
-------
|
||||
As shipped, the virtual COM port is enabled.
|
||||
As shipped, the virtual COM port is connected to LPUART1.
|
||||
|
||||
Configurations
|
||||
==============
|
||||
@@ -170,23 +179,9 @@ NOTES:
|
||||
b. Execute 'make menuconfig' in nuttx/ in order to start the
|
||||
reconfiguration process.
|
||||
|
||||
2. Unless stated otherwise, all configurations generate console
|
||||
output on USART3, as described above under "Serial Console". The
|
||||
elevant configuration settings are listed below::
|
||||
|
||||
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
|
||||
2. The default nsh configuration generates console output on LPUART1
|
||||
via the ST-Link virtual COM port. See "Serial Consoles" above for
|
||||
details and alternative USART3 configuration.
|
||||
|
||||
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
|
||||
|
||||
@@ -222,6 +222,21 @@
|
||||
|
||||
/* 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):
|
||||
*
|
||||
* In case of oversampling by 16, the equation is:
|
||||
@@ -249,6 +264,8 @@
|
||||
((STM32L5_USARTDIV8 & 0xfff0) | ((STM32L5_USARTDIV8 & 0x000f) >> 1))
|
||||
# endif
|
||||
|
||||
# endif /* CONFIG_LPUART1_SERIAL_CONSOLE */
|
||||
|
||||
#endif /* HAVE_CONSOLE */
|
||||
|
||||
/****************************************************************************
|
||||
|
||||
@@ -476,7 +476,7 @@ static struct stm32l5_serial_s g_lpuart1priv =
|
||||
.bits = CONFIG_LPUART1_BITS,
|
||||
.stopbits2 = CONFIG_LPUART1_2STOP,
|
||||
.baud = CONFIG_LPUART1_BAUD,
|
||||
.apbclock = STM32L5_PCLK2_FREQUENCY,
|
||||
.apbclock = STM32L5_PCLK1_FREQUENCY,
|
||||
.usartbase = STM32L5_LPUART1_BASE,
|
||||
.tx_gpio = GPIO_LPUART1_TX,
|
||||
.rx_gpio = GPIO_LPUART1_RX,
|
||||
@@ -1021,51 +1021,37 @@ static void stm32l5serial_setformat(struct uart_dev_s *dev)
|
||||
uint32_t cr1;
|
||||
uint32_t brr;
|
||||
|
||||
/* In case of oversampling by 8, the equation is:
|
||||
*
|
||||
* 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)
|
||||
#ifdef CONFIG_STM32L5_LPUART1_SERIALDRIVER
|
||||
if (priv->usartbase == STM32L5_LPUART1_BASE)
|
||||
{
|
||||
/* Use usartdiv16 */
|
||||
/* LPUART BRR = 256 * fCK / baud */
|
||||
|
||||
brr = (usartdiv8 + 1) >> 1;
|
||||
|
||||
/* Clear oversampling by 8 to enable oversampling by 16 */
|
||||
|
||||
cr1 &= ~USART_CR1_OVER8;
|
||||
brr = (((uint64_t)priv->apbclock << 8) +
|
||||
(priv->baud >> 1)) / priv->baud;
|
||||
stm32l5serial_putreg(priv, STM32L5_USART_BRR_OFFSET, brr);
|
||||
}
|
||||
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));
|
||||
|
||||
/* Set oversampling by 8 */
|
||||
|
||||
cr1 |= USART_CR1_OVER8;
|
||||
stm32l5serial_putreg(priv, STM32L5_USART_CR1_OFFSET, cr1);
|
||||
stm32l5serial_putreg(priv, STM32L5_USART_BRR_OFFSET, brr);
|
||||
}
|
||||
|
||||
stm32l5serial_putreg(priv, STM32L5_USART_CR1_OFFSET, cr1);
|
||||
stm32l5serial_putreg(priv, STM32L5_USART_BRR_OFFSET, brr);
|
||||
|
||||
/* Configure parity mode */
|
||||
|
||||
regval = stm32l5serial_getreg(priv, STM32L5_USART_CR1_OFFSET);
|
||||
|
||||
@@ -35,6 +35,7 @@ CONFIG_INPUT=y
|
||||
CONFIG_INPUT_BUTTONS=y
|
||||
CONFIG_INPUT_BUTTONS_LOWER=y
|
||||
CONFIG_LINE_MAX=64
|
||||
CONFIG_LPUART1_SERIAL_CONSOLE=y
|
||||
CONFIG_NSH_ARCHINIT=y
|
||||
CONFIG_NSH_BUILTIN_APPS=y
|
||||
CONFIG_NSH_DISABLE_IFUPDOWN=y
|
||||
@@ -49,11 +50,10 @@ CONFIG_READLINE_TABCOMPLETION=y
|
||||
CONFIG_RR_INTERVAL=200
|
||||
CONFIG_SCHED_WAITPID=y
|
||||
CONFIG_STACK_COLORATION=y
|
||||
CONFIG_STM32L5_LPUART1=y
|
||||
CONFIG_STM32L5_RTC=y
|
||||
CONFIG_STM32L5_RTC_AUTO_LSECLOCK_START_DRV_CAPABILITY=y
|
||||
CONFIG_STM32L5_USART3=y
|
||||
CONFIG_SYSTEM_NSH=y
|
||||
CONFIG_SYSTEM_STACKMONITOR=y
|
||||
CONFIG_SYSTEM_TEE=y
|
||||
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_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 **********************************************************/
|
||||
|
||||
/* The Nucleo-144 board has numerous LEDs but only three, LD1 a Green LED,
|
||||
|
||||
@@ -32,6 +32,8 @@
|
||||
|
||||
#include "arm_internal.h"
|
||||
#include "nucleo-l552ze.h"
|
||||
#include "stm32l5_pwr.h"
|
||||
#include "stm32l5_gpio.h"
|
||||
|
||||
#include <arch/board/board.h>
|
||||
|
||||
@@ -52,6 +54,18 @@
|
||||
|
||||
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
|
||||
/* Configure on-board LEDs if LED support has been selected. */
|
||||
|
||||
|
||||
Reference in New Issue
Block a user