From 4169a1b8136808f4f67b37ad03d93a45993d6eff Mon Sep 17 00:00:00 2001 From: dechao_gong Date: Fri, 31 Jul 2026 11:45:17 +0800 Subject: [PATCH] arch/arm/rtl8721f: add UART character driver support Expose the RTL8721F general-purpose UARTs through the shared Ameba serial driver in arch/arm/src/common/ameba. Only the chip-specific glue is added: a new ameba_uart_chip.h supplying the green2 register bases, IRQs, clock masks and UART TX/RX pin-mux function codes, plus the build wiring and a board port table registering UART0 at /dev/ttyS1. The common serial layer is reused unchanged. A new "uart" board config enables the driver with the serialrx and serialblaster examples and runtime TERMIOS support. Verified on RTL8721F EVB hardware with a PA24/PA25 loopback: single-message echo, 2600-byte serialrx/serialblaster throughput with no loss, and TERMIOS reconfiguration (CS7 data-bit truncation, parity and stop-bit ioctl round-trip, and 9600 baud reprogramming) all pass. Signed-off-by: dechao_gong Assisted-by: Claude --- .../rtl8721f/boards/rtl8721f_evb/index.rst | 24 ++++ arch/arm/src/rtl8721f/CMakeLists.txt | 12 ++ arch/arm/src/rtl8721f/Make.defs | 4 + arch/arm/src/rtl8721f/ameba_board.mk | 9 ++ arch/arm/src/rtl8721f/ameba_uart_chip.h | 78 +++++++++++++ .../rtl8721f_evb/configs/uart/defconfig | 54 +++++++++ .../rtl8721f/rtl8721f_evb/src/CMakeLists.txt | 8 +- boards/arm/rtl8721f/rtl8721f_evb/src/Makefile | 8 +- .../rtl8721f_evb/src/rtl8721f_bringup.c | 10 ++ .../rtl8721f_evb/src/rtl8721f_rtl8721f_evb.h | 14 +++ .../rtl8721f/rtl8721f_evb/src/rtl8721f_uart.c | 105 ++++++++++++++++++ 11 files changed, 323 insertions(+), 3 deletions(-) create mode 100644 arch/arm/src/rtl8721f/ameba_uart_chip.h create mode 100644 boards/arm/rtl8721f/rtl8721f_evb/configs/uart/defconfig create mode 100644 boards/arm/rtl8721f/rtl8721f_evb/src/rtl8721f_uart.c diff --git a/Documentation/platforms/arm/rtl8721f/boards/rtl8721f_evb/index.rst b/Documentation/platforms/arm/rtl8721f/boards/rtl8721f_evb/index.rst index 61064265230..e20c76a57bb 100644 --- a/Documentation/platforms/arm/rtl8721f/boards/rtl8721f_evb/index.rst +++ b/Documentation/platforms/arm/rtl8721f/boards/rtl8721f_evb/index.rst @@ -30,6 +30,10 @@ Supported in this NuttX port: partition) * Wi-Fi station and SoftAP through the ``wapi`` tool * DHCP client (STA) and DHCP server (SoftAP) +* GPIO pins exposed as ``/dev/gpioN`` character devices (input, output and + interrupt), driven directly on the SDK fwlib register layer +* General-purpose UARTs exposed as ``/dev/ttySN`` serial devices, driven + directly on the SDK fwlib register layer Buttons and LEDs ================ @@ -65,6 +69,26 @@ Pins are encoded with the ``AMEBA_PA()`` / ``AMEBA_PB()`` helpers from ``arch/arm/src/common/ameba/ameba_gpio.h`` (port A/B, pin 0-31), matching the Ameba SDK ``PinName`` layout. +uart +---- + +Minimal NSH with the general-purpose UART driver and the ``serialrx`` / +``serialblaster`` examples enabled (no Wi-Fi). The LOG-UART owns the console +and ``/dev/ttyS0``, so the board registers UART0 from its table (see +``boards/arm/rtl8721f/rtl8721f_evb/src/rtl8721f_uart.c``) as ``/dev/ttyS1`` at +115200 8N1. Edit that table -- controller, TX/RX pads and baud -- to match a +board's wiring. The TX/RX pads use the same ``AMEBA_PA()`` / ``AMEBA_PB()`` +encoding as the GPIO table; the driver muxes them to the UART function and +pulls RX high through the SDK ROM. Exercise the port with the examples (loop TX +back to RX, or wire it to a host serial adapter):: + + nsh> serialrx /dev/ttyS1 2600 & # start the receiver first + nsh> serialblaster /dev/ttyS1 2600 # then loop TX back to RX + +The line format can be changed at runtime through ``tcsetattr()`` (the config +enables ``CONFIG_SERIAL_TERMIOS``). UART3 is shared with Bluetooth and is not +exposed by the driver. + nsh --- diff --git a/arch/arm/src/rtl8721f/CMakeLists.txt b/arch/arm/src/rtl8721f/CMakeLists.txt index 53d0f2c479a..b64d618e018 100644 --- a/arch/arm/src/rtl8721f/CMakeLists.txt +++ b/arch/arm/src/rtl8721f/CMakeLists.txt @@ -50,6 +50,10 @@ if(CONFIG_AMEBA_GPIO) list(APPEND SRCS ${AMEBA_COMMON}/ameba_gpio.c) endif() +if(CONFIG_AMEBA_UART) + list(APPEND SRCS ${AMEBA_COMMON}/ameba_uart.c) +endif() + target_include_directories(arch PRIVATE ${AMEBA_COMMON}) target_sources(arch PRIVATE ${SRCS}) @@ -96,6 +100,14 @@ if(CONFIG_RTL8721F_FLASH_FS) list(APPEND AMEBA_FWLIB_SRCS ${AMEBA_SOC}/fwlib/ram_common/ameba_flash_ram.c) endif() +# UART register layer. The UART driver (arch/.../common/ameba/ameba_uart.c) +# calls the fwlib UART API, all of which resolves to the ROM symbol table; but +# the ROM routines index the fwlib data tables (UART_DEV_TABLE, APBPeriph_UARTx) +# which live in this RAM source and must be compiled in. +if(CONFIG_AMEBA_UART) + list(APPEND AMEBA_FWLIB_SRCS ${AMEBA_SOC}/fwlib/ram_common/ameba_uart.c) +endif() + # Silence a couple of warnings the vendored SDK sources trip under NuttX's # warning set, scoped to this fwlib compile only (never relaxing NuttX's own): # -Wno-int-conversion: the SDK passes NULL to irq_register()'s u32 "Data" diff --git a/arch/arm/src/rtl8721f/Make.defs b/arch/arm/src/rtl8721f/Make.defs index 487ba422188..bbd38f0161c 100644 --- a/arch/arm/src/rtl8721f/Make.defs +++ b/arch/arm/src/rtl8721f/Make.defs @@ -60,6 +60,10 @@ ifeq ($(CONFIG_AMEBA_GPIO),y) CHIP_CSRCS += ameba_gpio.c endif +ifeq ($(CONFIG_AMEBA_UART),y) +CHIP_CSRCS += ameba_uart.c +endif + ############################################################################ # Realtek RTL8721F SDK integration # diff --git a/arch/arm/src/rtl8721f/ameba_board.mk b/arch/arm/src/rtl8721f/ameba_board.mk index c223d8975da..a986df8b311 100644 --- a/arch/arm/src/rtl8721f/ameba_board.mk +++ b/arch/arm/src/rtl8721f/ameba_board.mk @@ -140,6 +140,15 @@ endif # calls the fwlib GPIO API. On RTL8721F (amebagreen2) GPIO_INTStatusGet and # GPIO_INTStatusClearEdge ARE in the ROM symbol table (ameba_rom_symbol_bcut.ld), # so unlike RTL8721Dx no fwlib ram_common source needs to be compiled in here. + +# UART register layer. The UART driver (arch/.../common/ameba/ameba_uart.c) +# calls the fwlib UART API, all of which resolves to the ROM symbol table; but +# the ROM routines index the fwlib data tables (UART_DEV_TABLE, APBPeriph_UARTx) +# which live in this RAM source and must be compiled in (--gc-sections drops +# the unused DMA/monitor helpers). +ifeq ($(CONFIG_AMEBA_UART),y) +AMEBA_FWLIB_SRCS += $(AMEBA_SOC)/fwlib/ram_common/ameba_uart.c +endif # -Wno-int-conversion: the vendored SDK passes NULL to irq_register()'s u32 # "Data" (interrupt context) argument in many places -- an intentional # NULL-as-context idiom. Silence -Wint-conversion for the SDK fwlib sources diff --git a/arch/arm/src/rtl8721f/ameba_uart_chip.h b/arch/arm/src/rtl8721f/ameba_uart_chip.h new file mode 100644 index 00000000000..4a5abcaf7e9 --- /dev/null +++ b/arch/arm/src/rtl8721f/ameba_uart_chip.h @@ -0,0 +1,78 @@ +/**************************************************************************** + * arch/arm/src/rtl8721f/ameba_uart_chip.h + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +#ifndef __ARCH_ARM_SRC_RTL8721F_AMEBA_UART_CHIP_H +#define __ARCH_ARM_SRC_RTL8721F_AMEBA_UART_CHIP_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include + +#include + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* Per-chip UART wiring for RTL8721F (amebagreen2). The shared driver + * (arch/arm/src/common/ameba/ameba_uart.c) includes this header to learn how + * many general-purpose UARTs the chip exposes and, for each, its register + * base, peripheral-clock masks, NVIC vector and crossbar pad-mux codes. See + * the RTL8721DX version of this header for the full contract; the notes + * below cover only what differs on this chip. + * + * The AP core is km4tz (TrustZone secure) here, but the fwlib UART_DEV_TABLE + * (fwlib/ram_common/ameba_uart.c) points at the *non-secure* UARTx_DEV bases + * unconditionally, so -- exactly as on RTL8721DX -- the driver programs the + * controllers through the non-secure alias (0x4080_C000 / 0x4080_D000). The + * APBPeriph function/clock masks match RTL8721DX; only the register bases, + * NVIC vectors and pad-mux function codes are chip-specific. + */ + +#define AMEBA_NUART 2 + +#define AMEBA_UART_PORT_BASES { 0x4080c000ul, 0x4080d000ul } + +#define AMEBA_UART_PORT_IRQS { RTL8721F_IRQ_UART0, RTL8721F_IRQ_UART1 } + +/* APBPeriph_UARTx (function) and APBPeriph_UARTx_CLOCK masks. Equal on this + * chip; kept as two lists so chips where they differ can supply both. + */ + +#define AMEBA_UART_APBPERIPH \ + { (((uint32_t)1 << 30) | ((uint32_t)1 << 6)), \ + (((uint32_t)1 << 30) | ((uint32_t)1 << 7)) } + +#define AMEBA_UART_APBPERIPH_CLK \ + { (((uint32_t)1 << 30) | ((uint32_t)1 << 6)), \ + (((uint32_t)1 << 30) | ((uint32_t)1 << 7)) } + +/* Direction-specific crossbar pad-mux function codes (PINMUX_FUNCTION_*). */ + +#define AMEBA_UART_TXFID { 95, 99 } /* UART0_TXD, UART1_TXD */ +#define AMEBA_UART_RXFID { 96, 100 } /* UART0_RXD, UART1_RXD */ + +#endif /* __ARCH_ARM_SRC_RTL8721F_AMEBA_UART_CHIP_H */ diff --git a/boards/arm/rtl8721f/rtl8721f_evb/configs/uart/defconfig b/boards/arm/rtl8721f/rtl8721f_evb/configs/uart/defconfig new file mode 100644 index 00000000000..4bd2df61a96 --- /dev/null +++ b/boards/arm/rtl8721f/rtl8721f_evb/configs/uart/defconfig @@ -0,0 +1,54 @@ +# +# This file is autogenerated: PLEASE DO NOT EDIT IT. +# +# You can use "make menuconfig" to make any modifications to the installed .config file. +# You can then do "make savedefconfig" to generate a new defconfig file that includes your +# modifications. +# +# CONFIG_DEBUG_WARN is not set +CONFIG_AMEBA_UART=y +CONFIG_ARCH="arm" +CONFIG_ARCH_BOARD="rtl8721f_evb" +CONFIG_ARCH_BOARD_RTL8721F_EVB=y +CONFIG_ARCH_CHIP="rtl8721f" +CONFIG_ARCH_CHIP_RTL8721F=y +CONFIG_ARCH_INTERRUPTSTACK=2048 +CONFIG_ARCH_STACKDUMP=y +CONFIG_ARMV8M_SYSTICK=y +CONFIG_BUILTIN=y +CONFIG_DEBUG_ASSERTIONS=y +CONFIG_DEBUG_FEATURES=y +CONFIG_DEBUG_FULLOPT=y +CONFIG_DEBUG_SYMBOLS=y +CONFIG_DEFAULT_TASK_STACKSIZE=4096 +CONFIG_EXAMPLES_HELLO=y +CONFIG_EXAMPLES_SERIALBLASTER=y +CONFIG_EXAMPLES_SERIALBLASTER_DEVPATH="/dev/ttyS1" +CONFIG_EXAMPLES_SERIALRX=y +CONFIG_EXAMPLES_SERIALRX_DEVPATH="/dev/ttyS1" +CONFIG_FS_PROCFS=y +CONFIG_FS_TMPFS=y +CONFIG_IDLETHREAD_STACKSIZE=4096 +CONFIG_INIT_ENTRYPOINT="nsh_main" +CONFIG_LIBC_MEMFD_ERROR=y +CONFIG_MM_DEFAULT_ALIGNMENT=32 +CONFIG_NSH_BUILTIN_APPS=y +CONFIG_NSH_FILEIOSIZE=512 +CONFIG_NSH_READLINE=y +CONFIG_PREALLOC_TIMERS=4 +CONFIG_RAM_SIZE=401408 +CONFIG_RAM_START=0x20006000 +CONFIG_RR_INTERVAL=200 +CONFIG_SCHED_HPWORK=y +CONFIG_SCHED_HPWORKPRIORITY=192 +CONFIG_SCHED_LPWORK=y +CONFIG_SERIAL_TERMIOS=y +CONFIG_STACK_COLORATION=y +CONFIG_START_DAY=16 +CONFIG_START_MONTH=6 +CONFIG_START_YEAR=2026 +CONFIG_SYSTEM_NSH=y +CONFIG_SYSTEM_NSH_STACKSIZE=2500 +CONFIG_TIMER=y +CONFIG_TIMER_ARCH=y +CONFIG_USEC_PER_TICK=1000 diff --git a/boards/arm/rtl8721f/rtl8721f_evb/src/CMakeLists.txt b/boards/arm/rtl8721f/rtl8721f_evb/src/CMakeLists.txt index c1df13e93cf..a617cffaa01 100644 --- a/boards/arm/rtl8721f/rtl8721f_evb/src/CMakeLists.txt +++ b/boards/arm/rtl8721f/rtl8721f_evb/src/CMakeLists.txt @@ -26,10 +26,14 @@ if(CONFIG_AMEBA_GPIO) list(APPEND SRCS rtl8721f_gpio.c) endif() +if(CONFIG_AMEBA_UART) + list(APPEND SRCS rtl8721f_uart.c) +endif() + target_sources(board PRIVATE ${SRCS}) -if(CONFIG_AMEBA_GPIO) - # The board pin table pulls in the shared driver's public headers from +if(CONFIG_AMEBA_GPIO OR CONFIG_AMEBA_UART) + # The board pin tables pull in the shared drivers' public headers from # arch/arm/src/common/ameba/, not on the default board include path. target_include_directories(board PRIVATE ${NUTTX_DIR}/arch/arm/src/common/ameba) diff --git a/boards/arm/rtl8721f/rtl8721f_evb/src/Makefile b/boards/arm/rtl8721f/rtl8721f_evb/src/Makefile index 480895cd47d..9f36cddb198 100644 --- a/boards/arm/rtl8721f/rtl8721f_evb/src/Makefile +++ b/boards/arm/rtl8721f/rtl8721f_evb/src/Makefile @@ -26,10 +26,16 @@ CSRCS = rtl8721f_boot.c rtl8721f_bringup.c ifeq ($(CONFIG_AMEBA_GPIO),y) CSRCS += rtl8721f_gpio.c +endif -# The board pin table pulls in the shared driver's public header from +ifeq ($(CONFIG_AMEBA_UART),y) +CSRCS += rtl8721f_uart.c +endif + +# The board pin tables pull in the shared drivers' public headers from # arch/arm/src/common/ameba/, which is not on the default board include path. +ifneq ($(CONFIG_AMEBA_GPIO)$(CONFIG_AMEBA_UART),) CFLAGS += ${INCDIR_PREFIX}$(TOPDIR)$(DELIM)arch$(DELIM)arm$(DELIM)src$(DELIM)common$(DELIM)ameba endif diff --git a/boards/arm/rtl8721f/rtl8721f_evb/src/rtl8721f_bringup.c b/boards/arm/rtl8721f/rtl8721f_evb/src/rtl8721f_bringup.c index a52bbf29fcf..63a9cae246f 100644 --- a/boards/arm/rtl8721f/rtl8721f_evb/src/rtl8721f_bringup.c +++ b/boards/arm/rtl8721f/rtl8721f_evb/src/rtl8721f_bringup.c @@ -144,6 +144,16 @@ int rtl8721f_bringup(void) } #endif +#ifdef CONFIG_AMEBA_UART + /* Register the board's general-purpose UART ports at /dev/ttySN. */ + + ret = rtl8721f_uart_initialize(); + if (ret < 0) + { + syslog(LOG_ERR, "ERROR: rtl8721f_uart_initialize failed: %d\n", ret); + } +#endif + IPC_patch_function(rtos_critical_enter, rtos_critical_exit, AMEBA_RTOS_CRITICAL_SEMA); IPC_SEMDelayStub(rtos_time_delay_ms); diff --git a/boards/arm/rtl8721f/rtl8721f_evb/src/rtl8721f_rtl8721f_evb.h b/boards/arm/rtl8721f/rtl8721f_evb/src/rtl8721f_rtl8721f_evb.h index f14760b29bb..acbc7c21e83 100644 --- a/boards/arm/rtl8721f/rtl8721f_evb/src/rtl8721f_rtl8721f_evb.h +++ b/boards/arm/rtl8721f/rtl8721f_evb/src/rtl8721f_rtl8721f_evb.h @@ -95,6 +95,20 @@ void ameba_ipc_initialize(void); int rtl8721f_gpio_initialize(void); #endif +#ifdef CONFIG_AMEBA_UART +/**************************************************************************** + * Name: rtl8721f_uart_initialize + * + * Description: + * Register the board's general-purpose UART ports with the NuttX serial + * upper half at /dev/ttyS1 and up + * (boards/arm/rtl8721f/rtl8721f_evb/src/rtl8721f_uart.c). + * + ****************************************************************************/ + +int rtl8721f_uart_initialize(void); +#endif + #ifdef CONFIG_RTL8721F_FLASH_FS /**************************************************************************** * Name: ameba_flash_fs_initialize diff --git a/boards/arm/rtl8721f/rtl8721f_evb/src/rtl8721f_uart.c b/boards/arm/rtl8721f/rtl8721f_evb/src/rtl8721f_uart.c new file mode 100644 index 00000000000..6c2cccc4aad --- /dev/null +++ b/boards/arm/rtl8721f/rtl8721f_evb/src/rtl8721f_uart.c @@ -0,0 +1,105 @@ +/**************************************************************************** + * boards/arm/rtl8721f/rtl8721f_evb/src/rtl8721f_uart.c + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include + +#include "ameba_gpio.h" +#include "ameba_uart.h" +#include "rtl8721f_rtl8721f_evb.h" + +#ifdef CONFIG_AMEBA_UART + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/* One entry per general-purpose UART exposed to NuttX. The LOG-UART owns + * the console and /dev/ttyS0, so these ports are registered starting at + * /dev/ttyS1 in the order listed below. The TX/RX pads are examples used by + * the `uart` config (examples/serialrx / serialblaster) -- any pad can be + * routed to a UART through the pin mux, so adjust them to match your board's + * wiring. + */ + +struct rtl8721f_uart_s +{ + const char *path; /* Device path (/dev/ttyS1, ...) */ + int uart; /* Controller index (AMEBA_UART0/AMEBA_UART1) */ + uint8_t txpin; /* TX pad (AMEBA_PA()/AMEBA_PB() encoding) */ + uint8_t rxpin; /* RX pad (AMEBA_PA()/AMEBA_PB() encoding) */ + uint32_t baud; /* Initial baud rate */ +}; + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +static const struct rtl8721f_uart_s g_uart_ports[] = +{ + { + "/dev/ttyS1", AMEBA_UART0, AMEBA_PA(24), AMEBA_PA(25), 115200 + }, +}; + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: rtl8721f_uart_initialize + * + * Description: + * Register the board's general-purpose UART ports with the NuttX serial + * upper half. + * + ****************************************************************************/ + +int rtl8721f_uart_initialize(void) +{ + int ret; + size_t i; + + for (i = 0; i < nitems(g_uart_ports); i++) + { + ret = ameba_uart_register(g_uart_ports[i].path, g_uart_ports[i].uart, + g_uart_ports[i].txpin, g_uart_ports[i].rxpin, + g_uart_ports[i].baud); + if (ret < 0) + { + syslog(LOG_ERR, + "ERROR: ameba_uart_register(%s) failed: %d\n", + g_uart_ports[i].path, ret); + return ret; + } + } + + return OK; +} + +#endif /* CONFIG_AMEBA_UART */