arch/arm/rp2040: Support non-sequential ADC channels and standardize internal function names

Enabling a higher channel of the internal ADC had the effect of
initializing the lower ones as well. Now that happens only if
actively requested.

Also, the functions for handling the internal ADC did not follow
the typical naming used by comparable modules for the same arch
and were renamed for coherence. Informational logging calls were
also made slightly more useful and discernible in case of having
multiple ADCs.

Signed-off-by: Niccolò Maggioni <nicco.maggioni+nuttx@gmail.com>
This commit is contained in:
Niccolò Maggioni 2025-08-11 14:59:24 +02:00 committed by Xiang Xiao
parent fa9f771a0f
commit 7ea3f8e333
3 changed files with 78 additions and 69 deletions

View file

@ -108,20 +108,20 @@ static int interrupt_handler(int irq,
void *context,
void *arg);
static void get_next_channel(void);
static void add_device(struct adc_dev_s *dev);
static void remove_device(struct adc_dev_s *dev);
static void adc_get_next_channel(void);
static void adc_add_device(struct adc_dev_s *dev);
static void adc_remove_device(struct adc_dev_s *dev);
/* ADC methods */
static int my_bind(struct adc_dev_s *dev,
const struct adc_callback_s *callback);
static int adc_bind(struct adc_dev_s *dev,
const struct adc_callback_s *callback);
static void my_reset(struct adc_dev_s *dev);
static int my_setup(struct adc_dev_s *dev);
static void my_shutdown(struct adc_dev_s *dev);
static void my_rxint(struct adc_dev_s *dev, bool enable);
static int my_ioctl(struct adc_dev_s *dev, int cmd, unsigned long arg);
static void adc_reset(struct adc_dev_s *dev);
static int adc_setup(struct adc_dev_s *dev);
static void adc_shutdown(struct adc_dev_s *dev);
static void adc_rxint(struct adc_dev_s *dev, bool enable);
static int adc_ioctl(struct adc_dev_s *dev, int cmd, unsigned long arg);
/****************************************************************************
* Private Data
@ -129,12 +129,12 @@ static int my_ioctl(struct adc_dev_s *dev, int cmd, unsigned long arg);
static const struct adc_ops_s g_adcops =
{
.ao_bind = my_bind, /* Called first during initialization. */
.ao_reset = my_reset, /* Called second during initialization. */
.ao_setup = my_setup, /* Called during first open. */
.ao_shutdown = my_shutdown, /* Called during last close. */
.ao_rxint = my_rxint, /* Called to enable/disable interrupts. */
.ao_ioctl = my_ioctl, /* Called for custom ioctls. */
.ao_bind = adc_bind, /* Called first during initialization. */
.ao_reset = adc_reset, /* Called second during initialization. */
.ao_setup = adc_setup, /* Called during first open. */
.ao_shutdown = adc_shutdown, /* Called during last close. */
.ao_rxint = adc_rxint, /* Called to enable/disable interrupts. */
.ao_ioctl = adc_ioctl, /* Called for custom ioctls. */
};
static const int8_t g_gpio_map[ADC_CHANNEL_COUNT] =
@ -227,13 +227,13 @@ static int interrupt_handler(int irq, void *context, void *arg)
/* Start next channel read */
get_next_channel();
adc_get_next_channel();
return OK;
}
/****************************************************************************
* Name: get_next_channel
* Name: adc_get_next_channel
*
* Description:
* Update g_current_channel to point to next channel in use and start
@ -243,7 +243,7 @@ static int interrupt_handler(int irq, void *context, void *arg)
*
****************************************************************************/
static void get_next_channel(void)
static void adc_get_next_channel(void)
{
struct adc_dev_s *a_device;
uint8_t next = g_current_channel + 1;
@ -316,7 +316,7 @@ static void get_next_channel(void)
}
/****************************************************************************
* Name: add_device
* Name: adc_add_device
*
* Description:
* This function is called to link the device int the device list.
@ -326,7 +326,7 @@ static void get_next_channel(void)
*
****************************************************************************/
static void add_device(struct adc_dev_s *dev)
static void adc_add_device(struct adc_dev_s *dev)
{
uint32_t value;
@ -368,14 +368,14 @@ static void add_device(struct adc_dev_s *dev)
/* Start conversions on first required channel. */
get_next_channel();
adc_get_next_channel();
ainfo("new cur %d\n", g_current_channel);
}
}
/****************************************************************************
* Name: remove_device
* Name: adc_remove_device
*
* Description:
* This function is called to unlink the device from the device list.
@ -384,7 +384,7 @@ static void add_device(struct adc_dev_s *dev)
*
****************************************************************************/
void remove_device(struct adc_dev_s *dev)
void adc_remove_device(struct adc_dev_s *dev)
{
struct adc_dev_s *a_device;
@ -426,7 +426,7 @@ void remove_device(struct adc_dev_s *dev)
}
/****************************************************************************
* Name: my_bind
* Name: adc_bind
*
* Description:
* This function is called when a driver is registered. It give us a
@ -435,12 +435,12 @@ void remove_device(struct adc_dev_s *dev)
*
****************************************************************************/
static int my_bind(struct adc_dev_s *dev,
const struct adc_callback_s *callback)
static int adc_bind(struct adc_dev_s *dev,
const struct adc_callback_s *callback)
{
DEBUGASSERT(PRIV(dev) != NULL);
ainfo("entered\n");
ainfo("Binding: 0x%08lX\n", dev);
PRIV(dev)->callback = callback;
@ -448,7 +448,7 @@ static int my_bind(struct adc_dev_s *dev,
}
/****************************************************************************
* Name: my_reset
* Name: adc_reset
*
* Description:
* This is called by the upper-half as part of the driver registration
@ -459,27 +459,35 @@ static int my_bind(struct adc_dev_s *dev,
*
****************************************************************************/
static void my_reset(struct adc_dev_s *dev)
static void adc_reset(struct adc_dev_s *dev)
{
int a_gpio;
ainfo("entered\n");
ainfo("Resetting: 0x%08lX\n", dev);
for (int i = 0; i < ADC_CHANNEL_COUNT; ++i)
{
a_gpio = g_gpio_map[i];
if (a_gpio >= 0)
if (PRIV(dev)->has_channel[i])
{
rp2040_gpio_setdir(a_gpio, false);
rp2040_gpio_set_function(a_gpio, RP2040_GPIO_FUNC_NULL);
rp2040_gpio_set_pulls(a_gpio, false, false);
if (a_gpio >= 0)
{
ainfo("Attaching GPIO %d to ADC channel %d\n", a_gpio, i + 1);
rp2040_gpio_setdir(a_gpio, false);
rp2040_gpio_set_function(a_gpio, RP2040_GPIO_FUNC_NULL);
rp2040_gpio_set_pulls(a_gpio, false, false);
}
else
{
ainfo("ADC channel %d is internally connected\n", i + 1);
}
}
}
}
/****************************************************************************
* Name: my_setup
* Name: adc_setup
*
* Description:
* This is called when a particular ADC driver is first opened.
@ -490,11 +498,11 @@ static void my_reset(struct adc_dev_s *dev)
*
****************************************************************************/
static int my_setup(struct adc_dev_s *dev)
static int adc_setup(struct adc_dev_s *dev)
{
int ret;
ainfo("entered: 0x%08lX\n", dev);
ainfo("Setup: 0x%08lX\n", dev);
/* Note: We check g_active_count here so we can return an error
* in the, probably impossible, case we have too many.
@ -514,7 +522,7 @@ static int my_setup(struct adc_dev_s *dev)
}
/****************************************************************************
* Name: my_shutdown
* Name: adc_shutdown
*
* Description:
* This is called to shutdown an ADC device. It unlinks the
@ -525,17 +533,17 @@ static int my_setup(struct adc_dev_s *dev)
*
****************************************************************************/
static void my_shutdown(struct adc_dev_s *dev)
static void adc_shutdown(struct adc_dev_s *dev)
{
ainfo("entered: 0x%08lX\n", dev);
ainfo("Shutdown: 0x%08lX\n", dev);
/* Remove adc_dev_s structure from the list */
remove_device(dev);
adc_remove_device(dev);
}
/****************************************************************************
* Name: my_rxint
* Name: adc_rxint
*
* Description:
* Call to enable or disable ADC RX interrupts
@ -544,37 +552,37 @@ static void my_shutdown(struct adc_dev_s *dev)
*
****************************************************************************/
static void my_rxint(struct adc_dev_s *dev, bool enable)
static void adc_rxint(struct adc_dev_s *dev, bool enable)
{
if (enable)
{
ainfo("entered: enable: 0x%08lX\n", dev);
ainfo("Enabling: 0x%08lX\n", dev);
add_device(dev);
adc_add_device(dev);
}
else
{
ainfo("entered: disable: 0x%08lX\n", dev);
ainfo("Disabling: 0x%08lX\n", dev);
remove_device(dev);
adc_remove_device(dev);
}
}
/****************************************************************************
* Name: my_ioctl
* Name: adc_ioctl
*
* Description:
* All ioctl calls will be routed through this method
*
****************************************************************************/
static int my_ioctl(struct adc_dev_s *dev,
int cmd,
unsigned long arg)
static int adc_ioctl(struct adc_dev_s *dev,
int cmd,
unsigned long arg)
{
/* No ioctl commands supported */
ainfo("entered\n");
ainfo("ioctl: 0x%08lX\n", dev);
return -ENOTTY;
}
@ -586,7 +594,7 @@ static int my_ioctl(struct adc_dev_s *dev,
#ifdef CONFIG_ADC
/****************************************************************************
* Name: my_setup
* Name: rp2040_adc_initialize
*
* Description:
* Initialize and register the ADC driver.
@ -604,18 +612,18 @@ static int my_ioctl(struct adc_dev_s *dev,
* success or NULL (with errno set) on failure
****************************************************************************/
int rp2040_adc_setup(const char *path,
bool read_adc0,
bool read_adc1,
bool read_adc2,
bool read_adc3,
bool read_temp)
int rp2040_adc_initialize(const char *path,
bool read_adc0,
bool read_adc1,
bool read_adc2,
bool read_adc3,
bool read_temp)
{
struct adc_dev_s *dev;
struct private_s *priv;
int ret;
ainfo("entered\n");
ainfo("Initializing: 0x%08lX\n", dev);
if (!read_adc0 && !read_adc1 && !read_adc2 && !read_adc3 && !read_temp)
{

View file

@ -68,7 +68,7 @@ extern "C"
#ifdef CONFIG_ADC
/****************************************************************************
* Name: rp2040_adc_setup
* Name: rp2040_adc_initialize
*
* Description:
* Initialize and register the ADC driver.
@ -85,12 +85,12 @@ extern "C"
* OK on success or an ERROR on failure
****************************************************************************/
int rp2040_adc_setup(const char *path,
bool read_adc0,
bool read_adc1,
bool read_adc2,
bool read_adc3,
bool read_temp);
int rp2040_adc_initialize(const char *path,
bool read_adc0,
bool read_adc1,
bool read_adc2,
bool read_adc3,
bool read_temp);
#else /* CONFIG_ADC */

View file

@ -651,7 +651,8 @@ int rp2040_common_bringup(void)
# define ADC_TEMP false
# endif
ret = rp2040_adc_setup("/dev/adc0", ADC_0, ADC_1, ADC_2, ADC_3, ADC_TEMP);
ret = rp2040_adc_initialize("/dev/adc0",
ADC_0, ADC_1, ADC_2, ADC_3, ADC_TEMP);
if (ret != OK)
{
syslog(LOG_ERR, "Failed to initialize ADC Driver: %d\n", ret);