diff --git a/Documentation/platforms/arm/rtl8720f/boards/rtl8720f_evb/index.rst b/Documentation/platforms/arm/rtl8720f/boards/rtl8720f_evb/index.rst index 64fd298d08f61..b917e20a05380 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/Documentation/platforms/arm/rtl8721dx/boards/pke8721daf/index.rst b/Documentation/platforms/arm/rtl8721dx/boards/pke8721daf/index.rst index 14554d6ddae16..3861744e7a2c7 100644 --- a/Documentation/platforms/arm/rtl8721dx/boards/pke8721daf/index.rst +++ b/Documentation/platforms/arm/rtl8721dx/boards/pke8721daf/index.rst @@ -43,6 +43,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 ================ @@ -153,6 +155,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/rtl8721dx/pke8721daf/src/rtl8721dx_adc.c``): ``/dev/adc0`` samples +CH0 on PB19 and CH1 on PB18. Edit that table -- channel numbers and the analog +pad each is wired to -- to match a board's wiring; the external channels +CH0..CH6 map to pads PB19..PB13 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 + Wi-Fi ===== diff --git a/Documentation/platforms/arm/rtl8721f/boards/rtl8721f_evb/index.rst b/Documentation/platforms/arm/rtl8721f/boards/rtl8721f_evb/index.rst index a3da36d03d6ac..a60108ad0f9ca 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/common/ameba/Kconfig b/arch/arm/src/common/ameba/Kconfig index 217d4d2232e41..647750224486e 100644 --- a/arch/arm/src/common/ameba/Kconfig +++ b/arch/arm/src/common/ameba/Kconfig @@ -100,4 +100,21 @@ config AMEBA_PWM The driver (arch/arm/src/common/ameba/ameba_pwm.c) sits on the SDK fwlib RTIM register layer and runs in polling task context. +config AMEBA_ADC + bool "ADC" + default n + select ANALOG + select ADC + ---help--- + Expose the Ameba SAR ADC as a NuttX ADC input at /dev/adc0. The + converter has one channel-switch list; the board selects which + channels are sampled and which analog pad each external channel is + wired to in its bring-up code. Every channel is sampled, in list + order, on each ANIOC_TRIGGER. + + The driver (arch/arm/src/common/ameba/ameba_adc.c) sits on the SDK + fwlib register layer and reads the auto channel-switch FIFO by + polling in task context (the chip does not enable a hardware + software-trigger path). + endmenu # Ameba Peripheral Support diff --git a/arch/arm/src/common/ameba/ameba_adc.c b/arch/arm/src/common/ameba/ameba_adc.c new file mode 100644 index 0000000000000..9ba17598e2635 --- /dev/null +++ b/arch/arm/src/common/ameba/ameba_adc.c @@ -0,0 +1,495 @@ +/**************************************************************************** + * arch/arm/src/common/ameba/ameba_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 + ****************************************************************************/ + +/* NuttX ADC lower half for the Realtek Ameba ADC. The chip has one SAR + * converter fed by a channel-switch list; the board says which channels to + * sample and which analog pad each external channel is wired to, and this + * driver exposes them as one /dev/adc0 device. Every ANIOC_TRIGGER samples + * the whole list, in list order, and hands each raw conversion value to the + * ADC upper half tagged with the hardware channel number the sample came + * from. + * + * The converter is driven through the SDK fwlib ADC API. Those routines are + * marked _LONG_CALL_ but are linked from the fwlib RAM source ameba_adc.c + * (already compiled into every image for the clock/brown-out calibration), + * so no extra source is added to the board build for the ADC. The fwlib API + * takes no register base: it selects the secure or non-secure ADC alias + * itself with TrustZone_IsSecure(), so this driver never touches a base + * address. + * + * On amebadplus the SDK deliberately does not enable the ADC hardware + * software-trigger path (ADC_SWTrigCmd() is compiled out and only logs a + * "not supported" note). The supported on-demand read is a bounded burst of + * the auto channel-switch FIFO: ADC_ReceiveBuf() clears the FIFO, enables + * the auto channel switch, reads exactly the requested number of words and + * disables it again. Reading one word per listed channel therefore yields a + * single polled sweep of the list -- the on-demand, no-interrupt behaviour a + * software trigger would give -- which is what the ANIOC_TRIGGER handler + * does. Everything runs in task context; the ADC_IRQ line is unused. + * + * The chip-specific wiring (channel count, list depth, pad-mux code, clock + * masks) lives in the per-chip ameba_adc_chip.h. To keep the vendor headers + * out of the NuttX include world the few fwlib symbols and constants used + * here are declared locally rather than pulled in from . + */ + +#include + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include "ameba_adc.h" +#include "ameba_adc_chip.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* Second/third argument to fwlib "state" style APIs. */ + +#define AMEBA_DISABLE 0x0 +#define AMEBA_ENABLE 0x1 + +/* fwlib ADC operation mode and pad values (from ameba_adc.h / ameba_gpio.h). + * The auto channel-switch mode is the one ADC_ReceiveBuf() drives; the pad + * is left un-pulled and its digital input buffer is disabled so the analog + * front end sees a clean input. + */ + +#define AMEBA_ADC_AUTO_MODE 0x1 /* ADC_AUTO_MODE */ +#define AMEBA_ADC_CLKDIV_24 0x3 /* ADC_CLK_DIV_24 */ +#define AMEBA_PAD_NOPULL 0x0 /* GPIO_PuPd_NOPULL */ + +/* 16-bit conversion word layout: channel id in [19:16], data in [15:0]. */ + +#define AMEBA_ADC_GET_CHNO(x) (((x) >> 16) & 0x0f) +#define AMEBA_ADC_GET_DATA(x) ((x) & 0xffff) + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +struct ameba_adc_dev_s +{ + const struct adc_callback_s *cb; /* Upper-half receive callback */ + uint8_t nchan; /* Channels in the switch list */ + bool enabled; /* Converter is powered/running */ + + /* Hardware channel number sampled at each list position. */ + + uint8_t chanlist[AMEBA_ADC_MAXLIST]; + + /* Analog pad per list position, AMEBA_ADC_PIN_NC for internal channels. */ + + uint8_t pins[AMEBA_ADC_MAXLIST]; +}; + +/* Layout-compatible mirror of the fwlib ADC_InitTypeDef. The driver only + * ever writes the leading opmode/cvlistlen/cvlist[16] fields (offsets + * 0..17), plus -- on amebadplus only -- the ClkDiv byte at offset 18. That + * prefix is identical on every current Ameba chip, so those writes always + * land on the right fields. + * + * Everything past offset 18 is deliberately NOT named here: the tail order + * differs per chip (amebadplus is ClkDiv/RxThresholdLevel/SpecialCh/ + * ChanInType at 28B, amebagreen2 has RxThresholdLevel/SpecialCh/ + * SamplePeriodUs at 22B, RTL8720F adds an ADC_Chan[8] sub-struct at 52B), + * and giving those bytes amebadplus-specific names would only be correct on + * one chip and misleading on the others. The driver never reads or writes + * them -- it lets ADC_StructInit() fill the WHOLE per-chip struct with the + * correct defaults for whichever fwlib is linked, then overwrites just the + * prefix (and ClkDiv). + * + * The reserved[] tail exists solely so this stack object is at least as + * large as the linked chip's real ADC_InitTypeDef -- otherwise + * ADC_StructInit(), which writes the whole struct, would overflow the + * stack. Each chip header supplies the real sizeof through + * AMEBA_ADC_INIT_SIZE and the static assertion below fails at compile time + * if a new port forgets it or under-sizes it. ClkDiv sits at a fixed + * offset 18 on amebadplus, so it stays named; the reserved run starts right + * after the named prefix. + */ + +/* Byte span of the named prefix (opmode + cvlistlen + cvlist[16] + clkdiv). + * Single source of truth for where the reserved tail begins; the offsetof + * assertion below verifies the compiler laid the prefix out with no padding + * so this really is the prefix size. + */ + +#define AMEBA_ADC_PREFIX_SIZE (1 + 1 + 16 + 1) + +struct ameba_adc_init_s +{ + uint8_t opmode; /* ADC_OpMode */ + uint8_t cvlistlen; /* ADC_CvlistLen */ + uint8_t cvlist[16]; /* ADC_Cvlist[16] */ + uint8_t clkdiv; /* ADC_ClkDiv (amebadplus only, @18) */ + + /* Chip-specific tail (RxThreshold/SpecialCh/... ) -- filled by + * ADC_StructInit(), never touched by this driver. Sized so the whole + * mirror is >= the linked chip's ADC_InitTypeDef; ternary keeps it + * non-empty when a chip's struct is <= the prefix. + */ + + uint8_t reserved[AMEBA_ADC_INIT_SIZE > AMEBA_ADC_PREFIX_SIZE ? + AMEBA_ADC_INIT_SIZE - AMEBA_ADC_PREFIX_SIZE : 1]; +}; + +static_assert(offsetof(struct ameba_adc_init_s, reserved) == + AMEBA_ADC_PREFIX_SIZE, + "ameba_adc_init_s prefix has unexpected padding"); + +static_assert(sizeof(struct ameba_adc_init_s) >= AMEBA_ADC_INIT_SIZE, + "ameba_adc_init_s smaller than the fwlib ADC_InitTypeDef"); + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +/* SDK fwlib ADC / pin / clock API (linked from fwlib RAM ameba_adc.c and the + * ROM pinmux table). None of the ADC calls take a register base -- the + * fwlib picks the secure/non-secure alias internally. + */ + +extern void RCC_PeriphClockCmd(uint32_t periph, uint32_t clock, + uint8_t newstate); +extern void Pinmux_Config(uint8_t pin, uint32_t func); +extern void PAD_PullCtrl(uint8_t pin, uint8_t pulltype); +extern void PAD_SleepPullCtrl(uint8_t pin, uint8_t pulltype); +extern void PAD_InputCtrl(uint8_t pin, uint32_t newstate); +extern void ADC_StructInit(struct ameba_adc_init_s *init); +extern void ADC_Init(struct ameba_adc_init_s *init); +extern void ADC_Cmd(uint32_t newstate); +extern void ADC_ReceiveBuf(uint32_t *buf, uint32_t len); + +/* ADC lower-half operations. */ + +static int ameba_adc_bind(struct adc_dev_s *dev, + const struct adc_callback_s *callback); +static void ameba_adc_reset(struct adc_dev_s *dev); +static int ameba_adc_setup(struct adc_dev_s *dev); +static void ameba_adc_shutdown(struct adc_dev_s *dev); +static void ameba_adc_rxint(struct adc_dev_s *dev, bool enable); +static int ameba_adc_ioctl(struct adc_dev_s *dev, int cmd, + unsigned long arg); + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +static const struct adc_ops_s g_ameba_adc_ops = +{ + .ao_bind = ameba_adc_bind, + .ao_reset = ameba_adc_reset, + .ao_setup = ameba_adc_setup, + .ao_shutdown = ameba_adc_shutdown, + .ao_rxint = ameba_adc_rxint, + .ao_ioctl = ameba_adc_ioctl, +}; + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: ameba_adc_hwinit + * + * Description: + * Program the converter's channel-switch list for auto channel-switch + * reads. ADC_Init() itself loads the list from the init struct, so the + * whole board list is applied in one call; the converter is left disabled + * (setup() powers it on). + * + ****************************************************************************/ + +static void ameba_adc_hwinit(struct ameba_adc_dev_s *priv) +{ + struct ameba_adc_init_s init; + int i; + + memset(&init, 0, sizeof(init)); + ADC_StructInit(&init); + + init.opmode = AMEBA_ADC_AUTO_MODE; + init.cvlistlen = (uint8_t)(priv->nchan - 1); + + /* ClkDiv exists at offset 18 only on amebadplus; on other chips that + * byte is RxThresholdLevel, so writing it would corrupt an unrelated + * field. Guard with the chip macro and keep the SDK default elsewhere. + */ + +#ifdef AMEBA_ADC_HAS_CLKDIV + init.clkdiv = AMEBA_ADC_CLKDIV_24; +#endif + + for (i = 0; i < priv->nchan; i++) + { + init.cvlist[i] = priv->chanlist[i]; + } + + ADC_Init(&init); +} + +/**************************************************************************** + * Name: ameba_adc_bind + ****************************************************************************/ + +static int ameba_adc_bind(struct adc_dev_s *dev, + const struct adc_callback_s *callback) +{ + struct ameba_adc_dev_s *priv = (struct ameba_adc_dev_s *)dev->ad_priv; + + priv->cb = callback; + return OK; +} + +/**************************************************************************** + * Name: ameba_adc_reset + * + * Description: + * Reload the channel-switch list; called before setup() and on error + * recovery. The peripheral clock and pads are latched at registration. + * + ****************************************************************************/ + +static void ameba_adc_reset(struct adc_dev_s *dev) +{ + struct ameba_adc_dev_s *priv = (struct ameba_adc_dev_s *)dev->ad_priv; + + ameba_adc_hwinit(priv); +} + +/**************************************************************************** + * Name: ameba_adc_setup + * + * Description: + * Power the converter on when the device is first opened. + * + ****************************************************************************/ + +static int ameba_adc_setup(struct adc_dev_s *dev) +{ + struct ameba_adc_dev_s *priv = (struct ameba_adc_dev_s *)dev->ad_priv; + + if (!priv->enabled) + { + ADC_Cmd(AMEBA_ENABLE); + priv->enabled = true; + } + + return OK; +} + +/**************************************************************************** + * Name: ameba_adc_shutdown + * + * Description: + * Power the converter off when the device is closed. + * + ****************************************************************************/ + +static void ameba_adc_shutdown(struct adc_dev_s *dev) +{ + struct ameba_adc_dev_s *priv = (struct ameba_adc_dev_s *)dev->ad_priv; + + if (priv->enabled) + { + ADC_Cmd(AMEBA_DISABLE); + priv->enabled = false; + } +} + +/**************************************************************************** + * Name: ameba_adc_rxint + * + * Description: + * No-op: this driver reads by polling the auto channel-switch FIFO on + * demand, so there are no RX interrupts to enable or disable. + * + ****************************************************************************/ + +static void ameba_adc_rxint(struct adc_dev_s *dev, bool enable) +{ + UNUSED(dev); + UNUSED(enable); +} + +/**************************************************************************** + * Name: ameba_adc_trigger + * + * Description: + * Sample the whole channel list once and push each raw value to the upper + * half. ADC_ReceiveBuf() reads one word per listed channel, in list + * order, through the auto channel-switch FIFO; the channel number is taken + * from each word so the sample is tagged with the channel it came from. + * + ****************************************************************************/ + +static int ameba_adc_trigger(struct adc_dev_s *dev) +{ + struct ameba_adc_dev_s *priv = (struct ameba_adc_dev_s *)dev->ad_priv; + uint32_t buf[AMEBA_ADC_MAXLIST]; + int i; + + if (priv->cb == NULL || priv->cb->au_receive == NULL) + { + return -EINVAL; + } + + ADC_ReceiveBuf(buf, priv->nchan); + + for (i = 0; i < priv->nchan; i++) + { + uint8_t ch = (uint8_t)AMEBA_ADC_GET_CHNO(buf[i]); + int32_t data = (int32_t)AMEBA_ADC_GET_DATA(buf[i]); + + priv->cb->au_receive(dev, ch, data); + } + + return OK; +} + +/**************************************************************************** + * Name: ameba_adc_ioctl + ****************************************************************************/ + +static int ameba_adc_ioctl(struct adc_dev_s *dev, int cmd, + unsigned long arg) +{ + struct ameba_adc_dev_s *priv = (struct ameba_adc_dev_s *)dev->ad_priv; + int ret; + + switch (cmd) + { + case ANIOC_TRIGGER: + ret = ameba_adc_trigger(dev); + break; + + case ANIOC_GET_NCHANNELS: + ret = priv->nchan; + break; + + default: + ret = -ENOTTY; + break; + } + + return ret; +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: ameba_adc_register + * + * Description: + * See ameba_adc.h. + * + ****************************************************************************/ + +int ameba_adc_register(const char *path, const uint8_t *channels, + const uint8_t *pins, unsigned int nchan) +{ + struct ameba_adc_dev_s *priv; + struct adc_dev_s *dev; + unsigned int i; + int ret; + + if (nchan == 0) + { + return -EINVAL; + } + + if (nchan > AMEBA_ADC_MAXLIST) + { + nchan = AMEBA_ADC_MAXLIST; + } + + dev = kmm_zalloc(sizeof(struct adc_dev_s) + + sizeof(struct ameba_adc_dev_s)); + if (dev == NULL) + { + return -ENOMEM; + } + + priv = (struct ameba_adc_dev_s *)(dev + 1); + dev->ad_ops = &g_ameba_adc_ops; + dev->ad_priv = priv; + + priv->nchan = (uint8_t)nchan; + memset(priv->pins, AMEBA_ADC_PIN_NC, sizeof(priv->pins)); + + /* Gate the ADC peripheral clock (plus the cap-touch/CTC clock domain on + * the chips whose header defines it) and turn each external channel's pad + * into an analog input: route it to the ADC crossbar function, drop its + * pulls and disable its digital input buffer. Internal channels have no + * pad and are skipped. + */ + + RCC_PeriphClockCmd(AMEBA_ADC_APBPERIPH, AMEBA_ADC_APBPERIPH_CLK, + AMEBA_ENABLE); +#ifdef AMEBA_ADC_AUXCLK_PERIPH + RCC_PeriphClockCmd(AMEBA_ADC_AUXCLK_PERIPH, AMEBA_ADC_AUXCLK_CLK, + AMEBA_ENABLE); +#endif + + for (i = 0; i < nchan; i++) + { + priv->chanlist[i] = channels[i]; + priv->pins[i] = pins[i]; + + if (pins[i] != AMEBA_ADC_PIN_NC) + { + Pinmux_Config(pins[i], AMEBA_ADC_PINMUX_FID); + PAD_PullCtrl(pins[i], AMEBA_PAD_NOPULL); + PAD_SleepPullCtrl(pins[i], AMEBA_PAD_NOPULL); + PAD_InputCtrl(pins[i], AMEBA_DISABLE); + } + } + + ameba_adc_hwinit(priv); + + ret = adc_register(path, dev); + if (ret < 0) + { + aerr("ERROR: adc_register(%s) failed: %d\n", path, ret); + kmm_free(dev); + return ret; + } + + return OK; +} diff --git a/arch/arm/src/common/ameba/ameba_adc.h b/arch/arm/src/common/ameba/ameba_adc.h new file mode 100644 index 0000000000000..04352a13f5d90 --- /dev/null +++ b/arch/arm/src/common/ameba/ameba_adc.h @@ -0,0 +1,100 @@ +/**************************************************************************** + * arch/arm/src/common/ameba/ameba_adc.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_COMMON_AMEBA_AMEBA_ADC_H +#define __ARCH_ARM_SRC_COMMON_AMEBA_AMEBA_ADC_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* The Ameba ADC is a single converter with one channel-switch list: the + * board hands ameba_adc_register() a set of channels to sample and, for each + * external channel, the analog pad it is wired to. A single /dev/adc0 + * device then samples the whole list on every ANIOC_TRIGGER (the SDK does + * not enable the hardware software-trigger path on this chip, so the driver + * reads one sweep of the list through the auto channel-switch FIFO -- see + * ameba_adc.c). + * + * Channels the board wires to an external pad give that pad here (encoded + * with the AMEBA_PA()/AMEBA_PB() PinName codes the GPIO driver uses); the + * chip's internal channels (temperature, VBAT, ...) have no pad and carry + * AMEBA_ADC_PIN_NC. + */ + +/* Sentinel pad code for an internal ADC channel that has no analog pad. */ + +#define AMEBA_ADC_PIN_NC 0xff + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +#ifdef __cplusplus +#define EXTERN extern "C" +extern "C" +{ +#else +#define EXTERN extern +#endif + +/**************************************************************************** + * Name: ameba_adc_register + * + * Description: + * Configure the Ameba ADC for a list of channels and register it with the + * NuttX ADC character driver at the given path (typically "/dev/adc0"). + * Every channel in the list is sampled, in list order, on each + * ANIOC_TRIGGER; the raw conversion value of each is delivered to the + * upper half tagged with the hardware channel number. + * + * Input Parameters: + * path - The device path to register, e.g. "/dev/adc0". + * channels - Array of hardware ADC channel numbers to sample. + * pins - Array giving, for each channel, the analog pad it is wired to + * (encoded with AMEBA_PA()/AMEBA_PB()), or AMEBA_ADC_PIN_NC for + * an internal channel that has no pad. + * nchan - Number of entries in channels/pins (clamped to the + * converter's channel-list length). + * + * Returned Value: + * Zero (OK) on success; a negated errno value on failure. + * + ****************************************************************************/ + +int ameba_adc_register(const char *path, const uint8_t *channels, + const uint8_t *pins, unsigned int nchan); + +#undef EXTERN +#ifdef __cplusplus +} +#endif + +#endif /* __ARCH_ARM_SRC_COMMON_AMEBA_AMEBA_ADC_H */ diff --git a/arch/arm/src/rtl8720f/CMakeLists.txt b/arch/arm/src/rtl8720f/CMakeLists.txt index 7918bc09a10e7..a9bfd641aac9d 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 ba3dc354b8148..58a8959944d6b 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 0000000000000..a74b26d45c72e --- /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 9931c1fe31707..8384e73b29e22 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/arch/arm/src/rtl8721dx/CMakeLists.txt b/arch/arm/src/rtl8721dx/CMakeLists.txt index d480f2b107430..71b7f7203a9e9 100644 --- a/arch/arm/src/rtl8721dx/CMakeLists.txt +++ b/arch/arm/src/rtl8721dx/CMakeLists.txt @@ -60,6 +60,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}) diff --git a/arch/arm/src/rtl8721dx/Make.defs b/arch/arm/src/rtl8721dx/Make.defs index 64adf3980e4e7..60ebeface1d5c 100644 --- a/arch/arm/src/rtl8721dx/Make.defs +++ b/arch/arm/src/rtl8721dx/Make.defs @@ -70,6 +70,10 @@ ifeq ($(CONFIG_AMEBA_PWM),y) CHIP_CSRCS += ameba_pwm.c endif +ifeq ($(CONFIG_AMEBA_ADC),y) +CHIP_CSRCS += ameba_adc.c +endif + ############################################################################ # Realtek RTL8721Dx SDK integration # diff --git a/arch/arm/src/rtl8721dx/ameba_adc_chip.h b/arch/arm/src/rtl8721dx/ameba_adc_chip.h new file mode 100644 index 0000000000000..47a456f0d6435 --- /dev/null +++ b/arch/arm/src/rtl8721dx/ameba_adc_chip.h @@ -0,0 +1,103 @@ +/**************************************************************************** + * arch/arm/src/rtl8721dx/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_RTL8721DX_AMEBA_ADC_CHIP_H +#define __ARCH_ARM_SRC_RTL8721DX_AMEBA_ADC_CHIP_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* Per-chip ADC wiring for RTL8721DX (amebadplus). 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. + * + * What differs per chip, from the SDK fwlib headers and the vendor + * example_adc_ext.h (verified, not guessed): + * + * chip pad-mux code for analog in extra clock to gate + * ----------- ------------------------------ ------------------- + * amebadplus PINMUX_FUNCTION_ADC = 6 (none) + * amebalite PINMUX_FUNCTION_AUXIN APBPeriph_CTC + * amebasmart PINMUX_FUNCTION_CAPTOUCH APBPeriph_CTC + * amebagreen2 PINMUX_FUNCTION_ADC (none) + * RTL8720F PINMUX_FUNCTION_ADC (none) + * + * Both differences are expressed as macros so a new chip only edits this + * header: AMEBA_ADC_PINMUX_FID carries the pad-mux code, and a chip that + * needs a second clock domain (amebalite/amebasmart route the ADC through + * the cap-touch/CTC block) also defines AMEBA_ADC_AUXCLK_PERIPH / _CLK, + * which the driver gates only when present. amebadplus needs neither, so + * it leaves those two undefined -- see the SPI/I2C/PWM chip headers for the + * same data-driven, never-computed pattern. + * + * External channels CH0..CH6 map to pads PB19,PB18,PB17,PB16,PB15,PB14,PB13 + * (from ameba_adc.h ADC_CHx_PIN); CH7..CH10 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 11 /* ADC_CH_NUM: CH0..CH6 ext, 7..10 int */ +#define AMEBA_ADC_MAXLIST 16 /* Channel-switch list depth (Cvlist) */ +#define AMEBA_ADC_PINMUX_FID 6 /* PINMUX_FUNCTION_ADC */ +#define AMEBA_ADC_IRQ 47 /* ADC_IRQ (unused by this polling drv) */ + +/* sizeof(fwlib ADC_InitTypeDef): OpMode/CvlistLen/Cvlist[16] then ClkDiv/ + * RxThresholdLevel/SpecialCh/ChanInType(u32) -> 28 bytes. The shared driver + * sizes its stack mirror from this so ADC_StructInit() cannot overflow it. + */ + +#define AMEBA_ADC_INIT_SIZE 28 + +/* 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. + * amebadplus 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)) + +/* amebadplus ADC_InitTypeDef has a ClkDiv field at offset 18; the other + * Ameba chips (amebagreen2, RTL8720F) do not -- their offset 18 is + * RxThresholdLevel. The shared driver guards the ClkDiv write with this + * macro so it only runs on chips that actually have the field. + */ + +#define AMEBA_ADC_HAS_CLKDIV 1 + +#endif /* __ARCH_ARM_SRC_RTL8721DX_AMEBA_ADC_CHIP_H */ diff --git a/arch/arm/src/rtl8721f/CMakeLists.txt b/arch/arm/src/rtl8721f/CMakeLists.txt index b27e3b4a4e0be..97fd6cd291fc4 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 d415e3d7723b9..a110e7c0abebb 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 0000000000000..17749c7819abf --- /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 b4d0b7f5a0953..be40f9c9d3829 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/rtl8720f/rtl8720f_evb/configs/adc/defconfig b/boards/arm/rtl8720f/rtl8720f_evb/configs/adc/defconfig new file mode 100644 index 0000000000000..84cc266a5863d --- /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 e09dd0664574d..514f1b66d9641 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 08dd553040dfc..8e0f450801450 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 0000000000000..22175e6220c30 --- /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 aab22384188be..3f5667edd89d0 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 d025a111b9b21..e7fe186adbced 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 diff --git a/boards/arm/rtl8721dx/pke8721daf/configs/adc/defconfig b/boards/arm/rtl8721dx/pke8721daf/configs/adc/defconfig new file mode 100644 index 0000000000000..18b175ba638e5 --- /dev/null +++ b/boards/arm/rtl8721dx/pke8721daf/configs/adc/defconfig @@ -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_ADC=y +CONFIG_ARCH="arm" +CONFIG_ARCH_BOARD="pke8721daf" +CONFIG_ARCH_BOARD_PKE8721DAF=y +CONFIG_ARCH_CHIP="rtl8721dx" +CONFIG_ARCH_CHIP_RTL8721DX=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=294912 +CONFIG_RAM_START=0x20020000 +CONFIG_RR_INTERVAL=200 +CONFIG_RTL8721DX_FLASH_FS=y +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/rtl8721dx/pke8721daf/src/CMakeLists.txt b/boards/arm/rtl8721dx/pke8721daf/src/CMakeLists.txt index b4722787e6c60..44926ad4edb05 100644 --- a/boards/arm/rtl8721dx/pke8721daf/src/CMakeLists.txt +++ b/boards/arm/rtl8721dx/pke8721daf/src/CMakeLists.txt @@ -42,13 +42,18 @@ if(CONFIG_AMEBA_PWM) list(APPEND SRCS rtl8721dx_pwm.c) endif() +if(CONFIG_AMEBA_ADC) + list(APPEND SRCS rtl8721dx_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/UART tables pull in the shared driver's public headers from # arch/arm/src/common/ameba/, not on the default board include path. target_include_directories(board diff --git a/boards/arm/rtl8721dx/pke8721daf/src/Makefile b/boards/arm/rtl8721dx/pke8721daf/src/Makefile index 158e7fa644686..c841ac4da3d7b 100644 --- a/boards/arm/rtl8721dx/pke8721daf/src/Makefile +++ b/boards/arm/rtl8721dx/pke8721daf/src/Makefile @@ -69,4 +69,13 @@ CSRCS += rtl8721dx_pwm.c CFLAGS += ${INCDIR_PREFIX}$(TOPDIR)$(DELIM)arch$(DELIM)arm$(DELIM)src$(DELIM)common$(DELIM)ameba endif +ifeq ($(CONFIG_AMEBA_ADC),y) +CSRCS += rtl8721dx_adc.c + +# The board ADC table pulls in the shared driver's public header from +# arch/arm/src/common/ameba/, which is not on the default board include path. + +CFLAGS += ${INCDIR_PREFIX}$(TOPDIR)$(DELIM)arch$(DELIM)arm$(DELIM)src$(DELIM)common$(DELIM)ameba +endif + include $(TOPDIR)/boards/Board.mk diff --git a/boards/arm/rtl8721dx/pke8721daf/src/rtl8721dx_adc.c b/boards/arm/rtl8721dx/pke8721daf/src/rtl8721dx_adc.c new file mode 100644 index 0000000000000..81b3e0ddfd187 --- /dev/null +++ b/boards/arm/rtl8721dx/pke8721daf/src/rtl8721dx_adc.c @@ -0,0 +1,90 @@ +/**************************************************************************** + * boards/arm/rtl8721dx/pke8721daf/src/rtl8721dx_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 "rtl8721dx_pke8721daf.h" + +#ifdef CONFIG_AMEBA_ADC + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/* Channels sampled on /dev/adc0 and the analog pad each is wired to. The + * external channels CH0..CH6 map to pads PB19..PB13; this board exposes CH0 + * on PB19 and CH1 on PB18. Any external channel can be listed here; + * internal channels (CH7..CH10: temperature, VBAT) 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_PB(19), /* CH0 -> PB19 */ + AMEBA_PB(18), /* CH1 -> PB18 */ +}; + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: rtl8721dx_adc_initialize + * + * Description: + * Register the board's ADC channels at /dev/adc0. + * + ****************************************************************************/ + +int rtl8721dx_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/rtl8721dx/pke8721daf/src/rtl8721dx_bringup.c b/boards/arm/rtl8721dx/pke8721daf/src/rtl8721dx_bringup.c index bc4f3847d394a..69a45c44ccc92 100644 --- a/boards/arm/rtl8721dx/pke8721daf/src/rtl8721dx_bringup.c +++ b/boards/arm/rtl8721dx/pke8721daf/src/rtl8721dx_bringup.c @@ -158,6 +158,16 @@ int rtl8721dx_bringup(void) } #endif +#ifdef CONFIG_AMEBA_ADC + /* Register the board's ADC channels at /dev/adc0. */ + + ret = rtl8721dx_adc_initialize(); + if (ret < 0) + { + syslog(LOG_ERR, "ERROR: rtl8721dx_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/rtl8721dx/pke8721daf/src/rtl8721dx_pke8721daf.h b/boards/arm/rtl8721dx/pke8721daf/src/rtl8721dx_pke8721daf.h index f712e50da38d4..f185ef3ab9a8f 100644 --- a/boards/arm/rtl8721dx/pke8721daf/src/rtl8721dx_pke8721daf.h +++ b/boards/arm/rtl8721dx/pke8721daf/src/rtl8721dx_pke8721daf.h @@ -134,6 +134,19 @@ int rtl8721dx_spi_initialize(void); int rtl8721dx_pwm_initialize(void); #endif +#ifdef CONFIG_AMEBA_ADC +/**************************************************************************** + * Name: rtl8721dx_adc_initialize + * + * Description: + * Register the board's ADC channels at /dev/adc0 + * (boards/arm/rtl8721dx/pke8721daf/src/rtl8721dx_adc.c). + * + ****************************************************************************/ + +int rtl8721dx_adc_initialize(void); +#endif + #ifdef CONFIG_RTL8721DX_FLASH_FS /**************************************************************************** * Name: ameba_flash_fs_initialize 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 0000000000000..8e561d5ad4517 --- /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 0188e21f7e772..b0befd38ddb68 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 308df01fcd2b0..65d9785ecda80 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 0000000000000..c8bda33d67eed --- /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 ab3b5bdb5cf3c..d03f81737599b 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 04633cd2a4a89..bc4ea8f380f64 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