arch/arm/rtl8720f: add UART master driver support

Wire the shared common UART driver
(arch/arm/src/common/ameba/ameba_uart.c) into RTL8720F.  Add an
ameba_uart_chip.h supplying the per-chip UART parameters: two
general-purpose controllers (UART0/UART1), their non-secure register
bases (0x401C3000 / 0x401C4000 -- the fwlib UART_DEV_TABLE points at
the non-secure alias), NVIC vectors, APBPeriph function/clock masks
and the crossbar TX/RX pad-mux function codes.

The fwlib ROM UART routines index data tables (UART_DEV_TABLE,
APBPeriph_UARTx) that live in fwlib ram_common/ameba_uart.c, so that
source is compiled in when CONFIG_AMEBA_UART is set.  Wire
CONFIG_AMEBA_UART into Make.defs/CMakeLists/ameba_board.mk, add the
board port table (UART0 at /dev/ttyS1, PA22 TX / PA23 RX, 115200 8N1)
with bringup registration, a uart config and board documentation.

Hardware-verified on rtl8720f_evb: serialrx/serialblaster over a
PA22-to-PA23 TX/RX loopback transferred all 2600 bytes intact.

Assisted-by: Claude <noreply@anthropic.com>
Signed-off-by: dechao_gong <dechao_gong@realsil.com.cn>
This commit is contained in:
dechao_gong 2026-08-12 13:55:09 +08:00 committed by Alan C. Assis
parent 3197472ad4
commit 18d2ae253c
11 changed files with 320 additions and 2 deletions

View file

@ -33,6 +33,8 @@ Supported in this NuttX port:
* 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
================
@ -69,6 +71,25 @@ encoded with the ``AMEBA_PA()`` helper from
``arch/arm/src/common/ameba/ameba_gpio.h`` (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/rtl8720f/rtl8720f_evb/src/rtl8720f_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()`` 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``). UART2 is not exposed by the driver.
nsh
---

View file

@ -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,15 @@ if(CONFIG_RTL8720F_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 (--gc-sections drops the
# unused DMA/monitor helpers).
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"

View file

@ -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 RTL8720F SDK integration
#

View file

@ -117,6 +117,16 @@ AMEBA_FWLIB_SRCS += $(TOPDIR)/arch/arm/src/rtl8720f/ameba_app_start.c \
ifeq ($(CONFIG_RTL8720F_FLASH_FS),y)
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 (--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

View file

@ -0,0 +1,78 @@
/****************************************************************************
* arch/arm/src/rtl8720f/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_RTL8720F_AMEBA_UART_CHIP_H
#define __ARCH_ARM_SRC_RTL8720F_AMEBA_UART_CHIP_H
/****************************************************************************
* Included Files
****************************************************************************/
#include <nuttx/config.h>
#include <stdint.h>
#include <nuttx/irq.h>
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
/* Per-chip UART wiring for RTL8720F. 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/RTL8721F -- the driver
* programs the controllers through the non-secure alias (0x401C_3000 /
* 0x401C_4000). The chip exposes UART0/UART1/UART2, but the LOG-UART owns
* the console and only UART0/UART1 are wired here.
*/
#define AMEBA_NUART 2
#define AMEBA_UART_PORT_BASES { 0x401c3000ul, 0x401c4000ul }
#define AMEBA_UART_PORT_IRQS { RTL8720F_IRQ_UART0, RTL8720F_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 { 65, 69 } /* UART0_TXD, UART1_TXD */
#define AMEBA_UART_RXFID { 66, 70 } /* UART0_RXD, UART1_RXD */
#endif /* __ARCH_ARM_SRC_RTL8720F_AMEBA_UART_CHIP_H */

View file

@ -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="rtl8720f_evb"
CONFIG_ARCH_BOARD_RTL8720F_EVB=y
CONFIG_ARCH_CHIP="rtl8720f"
CONFIG_ARCH_CHIP_RTL8720F=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=262144
CONFIG_RAM_START=0x30008000
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

View file

@ -26,9 +26,13 @@ if(CONFIG_AMEBA_GPIO)
list(APPEND SRCS rtl8720f_gpio.c)
endif()
if(CONFIG_AMEBA_UART)
list(APPEND SRCS rtl8720f_uart.c)
endif()
target_sources(board PRIVATE ${SRCS})
if(CONFIG_AMEBA_GPIO)
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

View file

@ -28,10 +28,14 @@ ifeq ($(CONFIG_AMEBA_GPIO),y)
CSRCS += rtl8720f_gpio.c
endif
ifeq ($(CONFIG_AMEBA_UART),y)
CSRCS += rtl8720f_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),)
ifneq ($(CONFIG_AMEBA_GPIO)$(CONFIG_AMEBA_UART),)
CFLAGS += ${INCDIR_PREFIX}$(TOPDIR)$(DELIM)arch$(DELIM)arm$(DELIM)src$(DELIM)common$(DELIM)ameba
endif

View file

@ -130,6 +130,16 @@ int rtl8720f_bringup(void)
}
#endif
#ifdef CONFIG_AMEBA_UART
/* Register the board's general-purpose UART ports at /dev/ttySN. */
ret = rtl8720f_uart_initialize();
if (ret < 0)
{
syslog(LOG_ERR, "ERROR: rtl8720f_uart_initialize failed: %d\n", ret);
}
#endif
/* Install the inter-core HW IPC-semaphore RTOS hooks LAST -- after all the
* flash / WHC bring-up above, and just before this (board_late_initialize)
* path returns and nx_start() hands off to the init task.

View file

@ -109,5 +109,19 @@ int ameba_flash_fs_initialize(void);
int rtl8720f_gpio_initialize(void);
#endif
#ifdef CONFIG_AMEBA_UART
/****************************************************************************
* Name: rtl8720f_uart_initialize
*
* Description:
* Register the board's general-purpose UART ports with the NuttX serial
* upper half at /dev/ttyS1 and up
* (boards/arm/rtl8720f/rtl8720f_evb/src/rtl8720f_uart.c).
*
****************************************************************************/
int rtl8720f_uart_initialize(void);
#endif
#endif /* __ASSEMBLY__ */
#endif /* __BOARDS_ARM_RTL8720F_RTL8720F_EVB_SRC_RTL8720F_RTL8720F_EVB_H */

View file

@ -0,0 +1,106 @@
/****************************************************************************
* boards/arm/rtl8720f/rtl8720f_evb/src/rtl8720f_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 <nuttx/config.h>
#include <sys/param.h>
#include <syslog.h>
#include "ameba_gpio.h"
#include "ameba_uart.h"
#include "rtl8720f_rtl8720f_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. RTL8720F drives all GPIO through a single port A controller, so
* pads use AMEBA_PA().
*/
struct rtl8720f_uart_s
{
const char *path; /* Device path (/dev/ttyS1, ...) */
int uart; /* Controller index (AMEBA_UART0/AMEBA_UART1) */
uint8_t txpin; /* TX pad (AMEBA_PA() encoding) */
uint8_t rxpin; /* RX pad (AMEBA_PA() encoding) */
uint32_t baud; /* Initial baud rate */
};
/****************************************************************************
* Private Data
****************************************************************************/
static const struct rtl8720f_uart_s g_uart_ports[] =
{
{
"/dev/ttyS1", AMEBA_UART0, AMEBA_PA(22), AMEBA_PA(23), 115200
},
};
/****************************************************************************
* Public Functions
****************************************************************************/
/****************************************************************************
* Name: rtl8720f_uart_initialize
*
* Description:
* Register the board's general-purpose UART ports with the NuttX serial
* upper half.
*
****************************************************************************/
int rtl8720f_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 */