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