From bf1ac68987a993dcad41e66f72a41e2fedab4c66 Mon Sep 17 00:00:00 2001 From: dechao_gong Date: Mon, 17 Aug 2026 17:09:31 +0800 Subject: [PATCH] arch/arm/rtl8721f: add ADC driver support Wire the shared Ameba ADC driver into the RTL8721F build: add the per-chip ameba_adc_chip.h (12 channels, CH0..CH7 external on PA20,PA19,PA18,PA17,PA15,PA14,PA13,PA12, PINMUX function 5), 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 --- .../rtl8721f/boards/rtl8721f_evb/index.rst | 17 ++++ arch/arm/src/rtl8721f/CMakeLists.txt | 12 +++ arch/arm/src/rtl8721f/Make.defs | 4 + arch/arm/src/rtl8721f/ameba_adc_chip.h | 84 +++++++++++++++++ arch/arm/src/rtl8721f/ameba_board.mk | 8 ++ .../rtl8721f_evb/configs/adc/defconfig | 53 +++++++++++ .../rtl8721f/rtl8721f_evb/src/CMakeLists.txt | 7 +- boards/arm/rtl8721f/rtl8721f_evb/src/Makefile | 6 +- .../rtl8721f/rtl8721f_evb/src/rtl8721f_adc.c | 90 +++++++++++++++++++ .../rtl8721f_evb/src/rtl8721f_bringup.c | 10 +++ .../rtl8721f_evb/src/rtl8721f_rtl8721f_evb.h | 12 +++ 11 files changed, 301 insertions(+), 2 deletions(-) create mode 100644 arch/arm/src/rtl8721f/ameba_adc_chip.h create mode 100644 boards/arm/rtl8721f/rtl8721f_evb/configs/adc/defconfig create mode 100644 boards/arm/rtl8721f/rtl8721f_evb/src/rtl8721f_adc.c diff --git a/Documentation/platforms/arm/rtl8721f/boards/rtl8721f_evb/index.rst b/Documentation/platforms/arm/rtl8721f/boards/rtl8721f_evb/index.rst index a3da36d03d6..a60108ad0f9 100644 --- a/Documentation/platforms/arm/rtl8721f/boards/rtl8721f_evb/index.rst +++ b/Documentation/platforms/arm/rtl8721f/boards/rtl8721f_evb/index.rst @@ -42,6 +42,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 ================ @@ -147,6 +149,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/rtl8721f/rtl8721f_evb/src/rtl8721f_adc.c``): ``/dev/adc0`` samples +CH0 on PA20 and CH1 on PA19. Edit that table -- channel numbers and the analog +pad each is wired to -- to match a board's wiring; the external channels +CH0..CH7 map to pads PA20,PA19,PA18,PA17,PA15,PA14,PA13,PA12 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/rtl8721f/CMakeLists.txt b/arch/arm/src/rtl8721f/CMakeLists.txt index b27e3b4a4e0..97fd6cd291f 100644 --- a/arch/arm/src/rtl8721f/CMakeLists.txt +++ b/arch/arm/src/rtl8721f/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}) @@ -145,6 +149,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/rtl8721f/Make.defs b/arch/arm/src/rtl8721f/Make.defs index d415e3d7723..a110e7c0abe 100644 --- a/arch/arm/src/rtl8721f/Make.defs +++ b/arch/arm/src/rtl8721f/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 RTL8721F SDK integration # diff --git a/arch/arm/src/rtl8721f/ameba_adc_chip.h b/arch/arm/src/rtl8721f/ameba_adc_chip.h new file mode 100644 index 00000000000..17749c7819a --- /dev/null +++ b/arch/arm/src/rtl8721f/ameba_adc_chip.h @@ -0,0 +1,84 @@ +/**************************************************************************** + * arch/arm/src/rtl8721f/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_RTL8721F_AMEBA_ADC_CHIP_H +#define __ARCH_ARM_SRC_RTL8721F_AMEBA_ADC_CHIP_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* Per-chip ADC wiring for RTL8721F (amebagreen2). 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 amebagreen2 fwlib headers (verified, not + * guessed): PINMUX_FUNCTION_ADC=5 (ameba_pinmux.h), ADC_IRQ=42 + * (ameba_vector_table.h), APBPeriph_ADC and APBPeriph_ADC_CLOCK both + * bit30|bit23 (sysreg_lsys.h). RTL8721F 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..CH7 map to pads PA20,PA19,PA18,PA17,PA15,PA14, + * PA13,PA12 (from ameba_adc.h ADC_CHx_PIN); CH8..CH10 and CH14 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 12 /* ADC_CH_NUM: CH0..CH7 ext, rest int */ +#define AMEBA_ADC_MAXLIST 16 /* Channel-switch list depth (Cvlist) */ +#define AMEBA_ADC_PINMUX_FID 5 /* PINMUX_FUNCTION_ADC */ +#define AMEBA_ADC_IRQ 42 /* ADC_IRQ (unused by this polling drv) */ + +/* sizeof(fwlib ADC_InitTypeDef): OpMode/CvlistLen/Cvlist[16] then + * RxThresholdLevel/SpecialCh/SamplePeriodUs(u16) -> 22 bytes. The shared + * driver sizes its stack mirror from this so ADC_StructInit() cannot + * overflow it. + */ + +#define AMEBA_ADC_INIT_SIZE 22 + +/* APBPeriph_ADC (function) and APBPeriph_ADC_CLOCK masks. Equal on this + * chip; both set the bit30 group selector and bit23 for the LP ADC block. + * RTL8721F 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 << 23)) + +#endif /* __ARCH_ARM_SRC_RTL8721F_AMEBA_ADC_CHIP_H */ diff --git a/arch/arm/src/rtl8721f/ameba_board.mk b/arch/arm/src/rtl8721f/ameba_board.mk index b4d0b7f5a09..be40f9c9d38 100644 --- a/arch/arm/src/rtl8721f/ameba_board.mk +++ b/arch/arm/src/rtl8721f/ameba_board.mk @@ -176,6 +176,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/rtl8721f/rtl8721f_evb/configs/adc/defconfig b/boards/arm/rtl8721f/rtl8721f_evb/configs/adc/defconfig new file mode 100644 index 00000000000..8e561d5ad45 --- /dev/null +++ b/boards/arm/rtl8721f/rtl8721f_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="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_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=401408 +CONFIG_RAM_START=0x20006000 +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/rtl8721f/rtl8721f_evb/src/CMakeLists.txt b/boards/arm/rtl8721f/rtl8721f_evb/src/CMakeLists.txt index 0188e21f7e7..b0befd38ddb 100644 --- a/boards/arm/rtl8721f/rtl8721f_evb/src/CMakeLists.txt +++ b/boards/arm/rtl8721f/rtl8721f_evb/src/CMakeLists.txt @@ -42,13 +42,18 @@ if(CONFIG_AMEBA_PWM) list(APPEND SRCS rtl8721f_pwm.c) endif() +if(CONFIG_AMEBA_ADC) + list(APPEND SRCS rtl8721f_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/rtl8721f/rtl8721f_evb/src/Makefile b/boards/arm/rtl8721f/rtl8721f_evb/src/Makefile index 308df01fcd2..65d9785ecda 100644 --- a/boards/arm/rtl8721f/rtl8721f_evb/src/Makefile +++ b/boards/arm/rtl8721f/rtl8721f_evb/src/Makefile @@ -44,10 +44,14 @@ ifeq ($(CONFIG_AMEBA_PWM),y) CSRCS += rtl8721f_pwm.c endif +ifeq ($(CONFIG_AMEBA_ADC),y) +CSRCS += rtl8721f_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/rtl8721f/rtl8721f_evb/src/rtl8721f_adc.c b/boards/arm/rtl8721f/rtl8721f_evb/src/rtl8721f_adc.c new file mode 100644 index 00000000000..c8bda33d67e --- /dev/null +++ b/boards/arm/rtl8721f/rtl8721f_evb/src/rtl8721f_adc.c @@ -0,0 +1,90 @@ +/**************************************************************************** + * boards/arm/rtl8721f/rtl8721f_evb/src/rtl8721f_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 "rtl8721f_rtl8721f_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..CH7 map to pads PA20,PA19,PA18,PA17,PA15,PA14, + * PA13,PA12; this board exposes CH5 on PA14 and CH6 on PA13. Any external + * channel can be listed here; internal channels would carry + * AMEBA_ADC_PIN_NC. + */ + +static const uint8_t g_adc_channels[] = +{ + 5, /* ADC_CH5 */ + 6, /* ADC_CH6 */ +}; + +static const uint8_t g_adc_pins[] = +{ + AMEBA_PA(14), /* CH5 -> PA14 */ + AMEBA_PA(13), /* CH6 -> PA13 */ +}; + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: rtl8721f_adc_initialize + * + * Description: + * Register the board's ADC channels at /dev/adc0. + * + ****************************************************************************/ + +int rtl8721f_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/rtl8721f/rtl8721f_evb/src/rtl8721f_bringup.c b/boards/arm/rtl8721f/rtl8721f_evb/src/rtl8721f_bringup.c index ab3b5bdb5cf..d03f8173759 100644 --- a/boards/arm/rtl8721f/rtl8721f_evb/src/rtl8721f_bringup.c +++ b/boards/arm/rtl8721f/rtl8721f_evb/src/rtl8721f_bringup.c @@ -184,6 +184,16 @@ int rtl8721f_bringup(void) } #endif +#ifdef CONFIG_AMEBA_ADC + /* Register the board's ADC channels at /dev/adc0. */ + + ret = rtl8721f_adc_initialize(); + if (ret < 0) + { + syslog(LOG_ERR, "ERROR: rtl8721f_adc_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 04633cd2a4a..bc4ea8f380f 100644 --- a/boards/arm/rtl8721f/rtl8721f_evb/src/rtl8721f_rtl8721f_evb.h +++ b/boards/arm/rtl8721f/rtl8721f_evb/src/rtl8721f_rtl8721f_evb.h @@ -148,6 +148,18 @@ int rtl8721f_spi_initialize(void); int rtl8721f_pwm_initialize(void); #endif +#ifdef CONFIG_AMEBA_ADC +/**************************************************************************** + * Name: rtl8721f_adc_initialize + * + * Description: + * Register the board's ADC channels at /dev/adc0. + * + ****************************************************************************/ + +int rtl8721f_adc_initialize(void); +#endif + #ifdef CONFIG_RTL8721F_FLASH_FS /**************************************************************************** * Name: ameba_flash_fs_initialize