From e5267f00a51e1610b42867bddd298bc36c419bfc Mon Sep 17 00:00:00 2001 From: dechao_gong Date: Mon, 17 Aug 2026 17:09:20 +0800 Subject: [PATCH] arch/arm/rtl8720f: add ADC driver support Wire the shared Ameba ADC driver into the RTL8720F build: add the per-chip ameba_adc_chip.h (9 channels, CH0..CH5 external on PA13..PA18, PINMUX function 5, APB clock on bit24), the board ADC table and registration, the adc board config, and build glue for both cmake and make (including the fwlib RAM-layer ameba_adc.c in ameba_board.mk). Document the ADC on the board index. Signed-off-by: dechao_gong Assisted-by: Claude --- .../rtl8720f/boards/rtl8720f_evb/index.rst | 17 ++++ arch/arm/src/rtl8720f/CMakeLists.txt | 12 +++ arch/arm/src/rtl8720f/Make.defs | 4 + arch/arm/src/rtl8720f/ameba_adc_chip.h | 86 ++++++++++++++++++ arch/arm/src/rtl8720f/ameba_board.mk | 8 ++ .../rtl8720f_evb/configs/adc/defconfig | 53 +++++++++++ .../rtl8720f/rtl8720f_evb/src/CMakeLists.txt | 7 +- boards/arm/rtl8720f/rtl8720f_evb/src/Makefile | 6 +- .../rtl8720f/rtl8720f_evb/src/rtl8720f_adc.c | 89 +++++++++++++++++++ .../rtl8720f_evb/src/rtl8720f_bringup.c | 10 +++ .../rtl8720f_evb/src/rtl8720f_rtl8720f_evb.h | 12 +++ 11 files changed, 302 insertions(+), 2 deletions(-) create mode 100644 arch/arm/src/rtl8720f/ameba_adc_chip.h create mode 100644 boards/arm/rtl8720f/rtl8720f_evb/configs/adc/defconfig create mode 100644 boards/arm/rtl8720f/rtl8720f_evb/src/rtl8720f_adc.c diff --git a/Documentation/platforms/arm/rtl8720f/boards/rtl8720f_evb/index.rst b/Documentation/platforms/arm/rtl8720f/boards/rtl8720f_evb/index.rst index 64fd298d08f..b917e20a053 100644 --- a/Documentation/platforms/arm/rtl8720f/boards/rtl8720f_evb/index.rst +++ b/Documentation/platforms/arm/rtl8720f/boards/rtl8720f_evb/index.rst @@ -41,6 +41,8 @@ Supported in this NuttX port: on the SDK fwlib register layer * PWM output exposed as a ``/dev/pwm0`` character device, driven directly on the SDK fwlib timer register layer +* ADC channels exposed as an ``/dev/adc0`` character device, driven directly + on the SDK fwlib register layer Buttons and LEDs ================ @@ -144,6 +146,21 @@ example:: nsh> pwm -d 25 -f 1000 # 1 kHz, 25% duty on /dev/pwm0 +adc +--- + +Minimal NSH with the ADC driver and the ``adc`` example enabled (no Wi-Fi). +The board registers its channels from a table (see +``boards/arm/rtl8720f/rtl8720f_evb/src/rtl8720f_adc.c``): ``/dev/adc0`` samples +CH0 on PA13 and CH1 on PA14. Edit that table -- channel numbers and the analog +pad each is wired to -- to match a board's wiring; the external channels +CH0..CH5 map to pads PA13..PA18 and are muxed to the ADC function through the +SDK ROM, while internal channels carry ``AMEBA_ADC_PIN_NC``. Every listed +channel is sampled, in order, on each trigger. Read the channels with the +example:: + + nsh> adc -n 1 # one sweep of /dev/adc0 + nsh --- diff --git a/arch/arm/src/rtl8720f/CMakeLists.txt b/arch/arm/src/rtl8720f/CMakeLists.txt index 7918bc09a10..a9bfd641aac 100644 --- a/arch/arm/src/rtl8720f/CMakeLists.txt +++ b/arch/arm/src/rtl8720f/CMakeLists.txt @@ -66,6 +66,10 @@ if(CONFIG_AMEBA_PWM) list(APPEND SRCS ${AMEBA_COMMON}/ameba_pwm.c) endif() +if(CONFIG_AMEBA_ADC) + list(APPEND SRCS ${AMEBA_COMMON}/ameba_adc.c) +endif() + target_include_directories(arch PRIVATE ${AMEBA_COMMON}) target_sources(arch PRIVATE ${SRCS}) @@ -144,6 +148,14 @@ if(CONFIG_AMEBA_PWM) list(APPEND AMEBA_FWLIB_SRCS ${AMEBA_SOC}/fwlib/ram_common/ameba_tim.c) endif() +# ADC (SAR) register layer. The ADC driver (arch/.../common/ameba/ameba_adc.c) +# calls the fwlib ADC API; the data tables and helpers it indexes live in this +# RAM source and must be compiled in (--gc-sections drops the unused +# interrupt/timer-trigger helpers). +if(CONFIG_AMEBA_ADC) + list(APPEND AMEBA_FWLIB_SRCS ${AMEBA_SOC}/fwlib/ram_common/ameba_adc.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/rtl8720f/Make.defs b/arch/arm/src/rtl8720f/Make.defs index ba3dc354b81..58a8959944d 100644 --- a/arch/arm/src/rtl8720f/Make.defs +++ b/arch/arm/src/rtl8720f/Make.defs @@ -76,6 +76,10 @@ ifeq ($(CONFIG_AMEBA_PWM),y) CHIP_CSRCS += ameba_pwm.c endif +ifeq ($(CONFIG_AMEBA_ADC),y) +CHIP_CSRCS += ameba_adc.c +endif + ############################################################################ # Realtek RTL8720F SDK integration # diff --git a/arch/arm/src/rtl8720f/ameba_adc_chip.h b/arch/arm/src/rtl8720f/ameba_adc_chip.h new file mode 100644 index 00000000000..a74b26d45c7 --- /dev/null +++ b/arch/arm/src/rtl8720f/ameba_adc_chip.h @@ -0,0 +1,86 @@ +/**************************************************************************** + * arch/arm/src/rtl8720f/ameba_adc_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_ADC_CHIP_H +#define __ARCH_ARM_SRC_RTL8720F_AMEBA_ADC_CHIP_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* Per-chip ADC wiring for RTL8720F. The shared driver + * (arch/arm/src/common/ameba/ameba_adc.c) includes this header to learn how + * many channels the converter can list, the crossbar pad-mux code that turns + * a pad into an analog input, and the peripheral-clock masks. A port to + * another Ameba chip supplies a same-named header on the chip include path; + * the shared driver is never edited -- it reads only the macros below, and + * it drives the ADC through the SDK fwlib API, which internally selects the + * secure/non-secure register alias (via TrustZone_IsSecure()), so no + * register base appears here at all. + * + * Values below are taken from the RTL8720F fwlib headers (verified, not + * guessed): PINMUX_FUNCTION_ADC=5 (ameba_pinmux.h), ADC_IRQ=34 + * (ameba_vector_table.h), APBPeriph_ADC and APBPeriph_ADC_CLOCK + * (sysreg_lsys.h) -- note the clock mask uses bit24 while the function mask + * uses bit23, unlike amebadplus where both are bit23. RTL8720F does not + * route the ADC through the cap-touch/CTC block, so no second clock domain + * is needed and AMEBA_ADC_AUXCLK_* stay undefined. + * + * External channels CH0..CH5 map to pads PA13,PA14,PA15,PA16,PA17,PA18 + * (from ameba_adc.h ADC_CHx_PIN); CH6..CH8 are fixed internal channels with + * no pad. The 16-bit conversion word (channel id in [19:16], data in + * [15:0]) is identical on every current Ameba chip, so the driver extracts + * it directly and no macro is needed here. + */ + +#define AMEBA_ADC_NCHAN 9 /* ADC_CH_NUM: CH0..CH5 ext, 6..8 int */ +#define AMEBA_ADC_MAXLIST 16 /* Channel-switch list depth (Cvlist) */ +#define AMEBA_ADC_PINMUX_FID 5 /* PINMUX_FUNCTION_ADC */ +#define AMEBA_ADC_IRQ 34 /* ADC_IRQ (unused by this polling drv) */ + +/* sizeof(fwlib ADC_InitTypeDef): OpMode/CvlistLen/Cvlist[16] then + * RxThresholdLevel/SpecialCh and an ADC_Chan[8] sub-struct ({u8,u16}=4 bytes + * each) -> 52 bytes, the largest of any current Ameba chip. The shared + * driver sizes its stack mirror from this so ADC_StructInit() cannot + * overflow it. + */ + +#define AMEBA_ADC_INIT_SIZE 52 + +/* APBPeriph_ADC (function) and APBPeriph_ADC_CLOCK masks. On this chip the + * function selector is bit30|bit23 and the clock selector is bit30|bit24. + * RTL8720F needs no second clock domain, so AMEBA_ADC_AUXCLK_* are left + * undefined (amebalite/amebasmart define them to gate APBPeriph_CTC too). + */ + +#define AMEBA_ADC_APBPERIPH (((uint32_t)1 << 30) | ((uint32_t)1 << 23)) +#define AMEBA_ADC_APBPERIPH_CLK (((uint32_t)1 << 30) | ((uint32_t)1 << 24)) + +#endif /* __ARCH_ARM_SRC_RTL8720F_AMEBA_ADC_CHIP_H */ diff --git a/arch/arm/src/rtl8720f/ameba_board.mk b/arch/arm/src/rtl8720f/ameba_board.mk index 9931c1fe317..8384e73b29e 100644 --- a/arch/arm/src/rtl8720f/ameba_board.mk +++ b/arch/arm/src/rtl8720f/ameba_board.mk @@ -153,6 +153,14 @@ ifeq ($(CONFIG_AMEBA_PWM),y) AMEBA_FWLIB_SRCS += $(AMEBA_SOC)/fwlib/ram_common/ameba_tim.c endif +# ADC (SAR) register layer. The ADC driver +# (arch/.../common/ameba/ameba_adc.c) calls the fwlib ADC API; the data tables +# and helpers it indexes live in this RAM source and must be compiled in +# (--gc-sections drops the unused interrupt/timer-trigger helpers). +ifeq ($(CONFIG_AMEBA_ADC),y) +AMEBA_FWLIB_SRCS += $(AMEBA_SOC)/fwlib/ram_common/ameba_adc.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/boards/arm/rtl8720f/rtl8720f_evb/configs/adc/defconfig b/boards/arm/rtl8720f/rtl8720f_evb/configs/adc/defconfig new file mode 100644 index 00000000000..84cc266a586 --- /dev/null +++ b/boards/arm/rtl8720f/rtl8720f_evb/configs/adc/defconfig @@ -0,0 +1,53 @@ +# +# 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_ADC=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_ADC=y +CONFIG_EXAMPLES_ADC_GROUPSIZE=2 +CONFIG_EXAMPLES_ADC_NSAMPLES=1 +CONFIG_EXAMPLES_ADC_SWTRIG=y +CONFIG_EXAMPLES_HELLO=y +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_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/rtl8720f/rtl8720f_evb/src/CMakeLists.txt b/boards/arm/rtl8720f/rtl8720f_evb/src/CMakeLists.txt index e09dd066457..514f1b66d96 100644 --- a/boards/arm/rtl8720f/rtl8720f_evb/src/CMakeLists.txt +++ b/boards/arm/rtl8720f/rtl8720f_evb/src/CMakeLists.txt @@ -42,13 +42,18 @@ if(CONFIG_AMEBA_PWM) list(APPEND SRCS rtl8720f_pwm.c) endif() +if(CONFIG_AMEBA_ADC) + list(APPEND SRCS rtl8720f_adc.c) +endif() + target_sources(board PRIVATE ${SRCS}) if(CONFIG_AMEBA_GPIO OR CONFIG_AMEBA_UART OR CONFIG_AMEBA_I2C OR CONFIG_AMEBA_SPI - OR CONFIG_AMEBA_PWM) + OR CONFIG_AMEBA_PWM + OR CONFIG_AMEBA_ADC) # 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 diff --git a/boards/arm/rtl8720f/rtl8720f_evb/src/Makefile b/boards/arm/rtl8720f/rtl8720f_evb/src/Makefile index 08dd553040d..8e0f4508014 100644 --- a/boards/arm/rtl8720f/rtl8720f_evb/src/Makefile +++ b/boards/arm/rtl8720f/rtl8720f_evb/src/Makefile @@ -44,10 +44,14 @@ ifeq ($(CONFIG_AMEBA_PWM),y) CSRCS += rtl8720f_pwm.c endif +ifeq ($(CONFIG_AMEBA_ADC),y) +CSRCS += rtl8720f_adc.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)$(CONFIG_AMEBA_I2C)$(CONFIG_AMEBA_SPI)$(CONFIG_AMEBA_PWM),) +ifneq ($(CONFIG_AMEBA_GPIO)$(CONFIG_AMEBA_UART)$(CONFIG_AMEBA_I2C)$(CONFIG_AMEBA_SPI)$(CONFIG_AMEBA_PWM)$(CONFIG_AMEBA_ADC),) CFLAGS += ${INCDIR_PREFIX}$(TOPDIR)$(DELIM)arch$(DELIM)arm$(DELIM)src$(DELIM)common$(DELIM)ameba endif diff --git a/boards/arm/rtl8720f/rtl8720f_evb/src/rtl8720f_adc.c b/boards/arm/rtl8720f/rtl8720f_evb/src/rtl8720f_adc.c new file mode 100644 index 00000000000..22175e6220c --- /dev/null +++ b/boards/arm/rtl8720f/rtl8720f_evb/src/rtl8720f_adc.c @@ -0,0 +1,89 @@ +/**************************************************************************** + * boards/arm/rtl8720f/rtl8720f_evb/src/rtl8720f_adc.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 + +#include "ameba_gpio.h" +#include "ameba_adc.h" +#include "rtl8720f_rtl8720f_evb.h" + +#ifdef CONFIG_AMEBA_ADC + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/* Channels sampled on /dev/adc0 and the analog pad each is wired to. The + * external channels CH0..CH5 map to pads PA13..PA18; this board exposes CH0 + * on PA13 and CH1 on PA14. Any external channel can be listed here; + * internal channels (CH6..CH8) would carry AMEBA_ADC_PIN_NC. + */ + +static const uint8_t g_adc_channels[] = +{ + 0, /* ADC_CH0 */ + 1, /* ADC_CH1 */ +}; + +static const uint8_t g_adc_pins[] = +{ + AMEBA_PA(13), /* CH0 -> PA13 */ + AMEBA_PA(14), /* CH1 -> PA14 */ +}; + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: rtl8720f_adc_initialize + * + * Description: + * Register the board's ADC channels at /dev/adc0. + * + ****************************************************************************/ + +int rtl8720f_adc_initialize(void) +{ + int ret; + + ret = ameba_adc_register("/dev/adc0", g_adc_channels, g_adc_pins, + nitems(g_adc_channels)); + if (ret < 0) + { + syslog(LOG_ERR, + "ERROR: ameba_adc_register(/dev/adc0) failed: %d\n", ret); + return ret; + } + + return OK; +} + +#endif /* CONFIG_AMEBA_ADC */ diff --git a/boards/arm/rtl8720f/rtl8720f_evb/src/rtl8720f_bringup.c b/boards/arm/rtl8720f/rtl8720f_evb/src/rtl8720f_bringup.c index aab22384188..3f5667edd89 100644 --- a/boards/arm/rtl8720f/rtl8720f_evb/src/rtl8720f_bringup.c +++ b/boards/arm/rtl8720f/rtl8720f_evb/src/rtl8720f_bringup.c @@ -170,6 +170,16 @@ int rtl8720f_bringup(void) } #endif +#ifdef CONFIG_AMEBA_ADC + /* Register the board's ADC channels at /dev/adc0. */ + + ret = rtl8720f_adc_initialize(); + if (ret < 0) + { + syslog(LOG_ERR, "ERROR: rtl8720f_adc_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. diff --git a/boards/arm/rtl8720f/rtl8720f_evb/src/rtl8720f_rtl8720f_evb.h b/boards/arm/rtl8720f/rtl8720f_evb/src/rtl8720f_rtl8720f_evb.h index d025a111b9b..e7fe186adbc 100644 --- a/boards/arm/rtl8720f/rtl8720f_evb/src/rtl8720f_rtl8720f_evb.h +++ b/boards/arm/rtl8720f/rtl8720f_evb/src/rtl8720f_rtl8720f_evb.h @@ -79,6 +79,18 @@ int rtl8720f_spi_initialize(void); int rtl8720f_pwm_initialize(void); #endif +#ifdef CONFIG_AMEBA_ADC +/**************************************************************************** + * Name: rtl8720f_adc_initialize + * + * Description: + * Register the board's ADC channels at /dev/adc0. + * + ****************************************************************************/ + +int rtl8720f_adc_initialize(void); +#endif + #ifdef CONFIG_RTL8720F_WIFI /**************************************************************************** * Name: rtl8720f_wifi_initialize