Skip to content

Commit

Permalink
add adc_receive_all just for adc_dma
Browse files Browse the repository at this point in the history
Description: No longer transmitting data to fifo in a loop, complete transmission in one go

Signed-off-by: zhangkai25 <[email protected]>
  • Loading branch information
zhangkai25 authored and xiaoxiang781216 committed Sep 27, 2024
1 parent b584b38 commit bfd6185
Show file tree
Hide file tree
Showing 2 changed files with 109 additions and 19 deletions.
100 changes: 84 additions & 16 deletions drivers/analog/adc.c
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@

#include <nuttx/config.h>

#include <sys/param.h>
#include <sys/types.h>
#include <stdint.h>
#include <stdbool.h>
Expand Down Expand Up @@ -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);
Expand All @@ -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 */
};

/****************************************************************************
Expand Down Expand Up @@ -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? */

Expand All @@ -317,22 +323,22 @@ 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 */

if (msglen == 1)
{
/* 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)
Expand All @@ -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)
Expand All @@ -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;
Expand Down Expand Up @@ -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 */

Expand All @@ -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
****************************************************************************/
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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;
}
28 changes: 25 additions & 3 deletions include/nuttx/analog/adc.h
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down Expand Up @@ -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.
*
Expand Down Expand Up @@ -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];
};

Expand Down

0 comments on commit bfd6185

Please sign in to comment.