From bfd6185f4ae5f32d3e24aca04a5fd33eb12ee156 Mon Sep 17 00:00:00 2001 From: zhangkai25 Date: Tue, 16 Jul 2024 16:48:08 +0800 Subject: [PATCH] add adc_receive_all just for adc_dma Description: No longer transmitting data to fifo in a loop, complete transmission in one go Signed-off-by: zhangkai25 --- drivers/analog/adc.c | 100 +++++++++++++++++++++++++++++++------ include/nuttx/analog/adc.h | 28 +++++++++-- 2 files changed, 109 insertions(+), 19 deletions(-) diff --git a/drivers/analog/adc.c b/drivers/analog/adc.c index 78405fdc78348..0a677043c38ae 100644 --- a/drivers/analog/adc.c +++ b/drivers/analog/adc.c @@ -24,6 +24,7 @@ #include +#include #include #include #include @@ -54,6 +55,10 @@ static int adc_ioctl(FAR struct file *filep, int cmd, unsigned long arg); static int adc_reset(FAR struct adc_dev_s *dev); static int adc_receive(FAR struct adc_dev_s *dev, uint8_t ch, int32_t data); +static int adc_receive_batch(FAR struct adc_dev_s *dev, + FAR const uint8_t *channel, + FAR const uint32_t *data, + size_t count); static void adc_notify(FAR struct adc_dev_s *dev); static int adc_poll(FAR struct file *filep, FAR struct pollfd *fds, bool setup); @@ -79,8 +84,9 @@ static const struct file_operations g_adc_fops = static const struct adc_callback_s g_adc_callback = { - adc_receive, /* au_receive */ - adc_reset /* au_reset */ + adc_receive, /* au_receive */ + adc_receive_batch, /* au_receive_batch */ + adc_reset /* au_reset */ }; /**************************************************************************** @@ -301,8 +307,8 @@ static ssize_t adc_read(FAR struct file *filep, FAR char *buffer, nread = 0; do { - FAR struct adc_msg_s *msg = - &dev->ad_recv.af_buffer[dev->ad_recv.af_head]; + uint8_t channel = dev->ad_recv.af_channel[dev->ad_recv.af_head]; + int32_t data = dev->ad_recv.af_data[dev->ad_recv.af_head]; /* Will the next message in the FIFO fit into the user buffer? */ @@ -317,7 +323,7 @@ static ssize_t adc_read(FAR struct file *filep, FAR char *buffer, /* Feed ADC data to entropy pool */ - add_sensor_randomness(msg->am_data); + add_sensor_randomness(data); /* Copy the message to the user buffer */ @@ -325,14 +331,14 @@ static ssize_t adc_read(FAR struct file *filep, FAR char *buffer, { /* Only one channel, return MS 8-bits of the sample. */ - buffer[nread] = msg->am_data >> 24; + buffer[nread] = data >> 24; } else if (msglen == 2) { /* Only one channel, return only the MS 16-bits of the sample. */ - int16_t data16 = msg->am_data >> 16; + int16_t data16 = data >> 16; memcpy(&buffer[nread], &data16, 2); } else if (msglen == 3) @@ -341,8 +347,8 @@ static ssize_t adc_read(FAR struct file *filep, FAR char *buffer, /* Return the channel and the MS 16-bits of the sample. */ - buffer[nread] = msg->am_channel; - data16 = msg->am_data >> 16; + buffer[nread] = channel; + data16 = data >> 16; memcpy(&buffer[nread + 1], &data16, 2); } else if (msglen == 4) @@ -354,26 +360,26 @@ static ssize_t adc_read(FAR struct file *filep, FAR char *buffer, * which are indices: 0-2. */ - data24 = msg->am_data; + data24 = data; #else /* In the little endian case, indices 0-2 correspond to the * the three LS bytes. */ - data24 = msg->am_data >> 8; + data24 = data >> 8; #endif /* Return the channel and the most significant 24-bits */ - buffer[nread] = msg->am_channel; + buffer[nread] = channel; memcpy(&buffer[nread + 1], &data24, 3); } else { /* Return the channel and all four bytes of the sample */ - buffer[nread] = msg->am_channel; - memcpy(&buffer[nread + 1], &msg->am_data, 4); + buffer[nread] = channel; + memcpy(&buffer[nread + 1], &data, 4); } nread += msglen; @@ -480,8 +486,8 @@ static int adc_receive(FAR struct adc_dev_s *dev, uint8_t ch, int32_t data) { /* Add the new, decoded ADC sample at the tail of the FIFO */ - fifo->af_buffer[fifo->af_tail].am_channel = ch; - fifo->af_buffer[fifo->af_tail].am_data = data; + fifo->af_channel[fifo->af_tail] = ch; + fifo->af_data[fifo->af_tail] = data; /* Increment the tail of the circular buffer */ @@ -495,6 +501,63 @@ static int adc_receive(FAR struct adc_dev_s *dev, uint8_t ch, int32_t data) return errcode; } +/**************************************************************************** + * Name: adc_receive_all + ****************************************************************************/ + +static int adc_receive_batch(FAR struct adc_dev_s *dev, + FAR const uint8_t *channel, + FAR const uint32_t *data, + size_t count) +{ + FAR struct adc_fifo_s *fifo = &dev->ad_recv; + size_t used; + size_t first; + size_t second; + + /* Check if adding this new message would over-run the drivers ability to + * enqueue read data. + */ + + used = (fifo->af_tail - fifo->af_head + CONFIG_ADC_FIFOSIZE) + % CONFIG_ADC_FIFOSIZE; + + if (used + count >= CONFIG_ADC_FIFOSIZE) + { + return -ENOMEM; + } + + /* Check if flipping is required and memcopy */ + + first = MIN(count, CONFIG_ADC_FIFOSIZE - fifo->af_tail); + second = count - first; + + memcpy(&fifo->af_data[fifo->af_tail], data, + first * sizeof(uint32_t)); + + if (channel != NULL) + { + memcpy(&fifo->af_channel[fifo->af_tail], channel, first); + } + + if (second > 0) + { + memcpy(&fifo->af_data[0], &data[first], + second * sizeof(uint32_t)); + + if (channel != NULL) + { + memcpy(&fifo->af_channel[0], &channel[first], second); + } + } + + fifo->af_tail = (fifo->af_tail + count) % CONFIG_ADC_FIFOSIZE; + + adc_notify(dev); + + return OK; +} + /**************************************************************************** * Name: adc_notify ****************************************************************************/ @@ -655,6 +718,7 @@ static int adc_samples_on_read(FAR struct adc_dev_s *dev) int adc_register(FAR const char *path, FAR struct adc_dev_s *dev) { + FAR struct adc_fifo_s *fifo = &dev->ad_recv; int ret; DEBUGASSERT(path != NULL && dev != NULL); @@ -692,5 +756,9 @@ int adc_register(FAR const char *path, FAR struct adc_dev_s *dev) nxmutex_destroy(&dev->ad_closelock); } + /* Initialize the af_channale */ + + memset(&fifo->af_channel[fifo->af_tail], 0, CONFIG_ADC_FIFOSIZE); + return ret; } diff --git a/include/nuttx/analog/adc.h b/include/nuttx/analog/adc.h index 39db6c318d4f2..92833ce911027 100644 --- a/include/nuttx/analog/adc.h +++ b/include/nuttx/analog/adc.h @@ -44,8 +44,8 @@ ****************************************************************************/ /* Default configuration settings that may be overridden in the NuttX - * configuration file. The configured size is limited to 255 to fit into a - * uint8_t. + * configuration file. The configured size is limited to 65535 to fit into + * a uint16_t. */ #if !defined(CONFIG_ADC_FIFOSIZE) @@ -90,6 +90,26 @@ struct adc_callback_s CODE int (*au_receive)(FAR struct adc_dev_s *dev, uint8_t ch, int32_t data); + /* This method is called from the lower half, platform-specific ADC logic + * when new ADC sample data is available, + * enable transfer all data at once . + * + * Input Parameters: + * dev - The ADC device structure that was previously registered by + * adc_register() + * channel - Pointer to the channel lists buffer + * data - Pointer to the DMA buffer. + * count - Number of data elements in the channelbuffer and databuffer. + * + * Returned Value: + * Zero on success; a negated errno value on failure. + */ + + CODE int (*au_receive_batch)(FAR struct adc_dev_s *dev, + FAR const uint8_t *channel, + FAR const uint32_t *data, + size_t count); + /* This method is called from the lower half, platform-specific ADC logic * when an overrun appeared to free / reset upper half. * @@ -119,7 +139,9 @@ struct adc_fifo_s sem_t af_sem; /* Counting semaphore */ uint16_t af_head; /* Index to the head [IN] index in the circular buffer */ uint16_t af_tail; /* Index to the tail [OUT] index in the circular buffer */ - /* Circular buffer of CAN messages */ + /* Circular buffer of ADC messages */ + uint8_t af_channel[CONFIG_ADC_FIFOSIZE]; + int32_t af_data[CONFIG_ADC_FIFOSIZE]; struct adc_msg_s af_buffer[CONFIG_ADC_FIFOSIZE]; };