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 <dechao_gong@realsil.com.cn>
Assisted-by: Claude <noreply@anthropic.com>
This commit is contained in:
dechao_gong 2026-08-17 17:09:20 +08:00 committed by Alin Jerpelea
parent 07fd8cc936
commit e5267f00a5
11 changed files with 302 additions and 2 deletions

View file

@ -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
---

View file

@ -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"

View file

@ -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
#

View file

@ -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 <nuttx/config.h>
#include <stdint.h>
/****************************************************************************
* 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 */

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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 <nuttx/config.h>
#include <sys/param.h>
#include <syslog.h>
#include <errno.h>
#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 */

View file

@ -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.

View file

@ -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