Skip to content

Commit bfd6185

Browse files
zhangkai25xiaoxiang781216
authored andcommitted
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 <[email protected]>
1 parent b584b38 commit bfd6185

File tree

2 files changed

+109
-19
lines changed

2 files changed

+109
-19
lines changed

drivers/analog/adc.c

Lines changed: 84 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424

2525
#include <nuttx/config.h>
2626

27+
#include <sys/param.h>
2728
#include <sys/types.h>
2829
#include <stdint.h>
2930
#include <stdbool.h>
@@ -54,6 +55,10 @@ static int adc_ioctl(FAR struct file *filep, int cmd, unsigned long arg);
5455
static int adc_reset(FAR struct adc_dev_s *dev);
5556
static int adc_receive(FAR struct adc_dev_s *dev, uint8_t ch,
5657
int32_t data);
58+
static int adc_receive_batch(FAR struct adc_dev_s *dev,
59+
FAR const uint8_t *channel,
60+
FAR const uint32_t *data,
61+
size_t count);
5762
static void adc_notify(FAR struct adc_dev_s *dev);
5863
static int adc_poll(FAR struct file *filep, FAR struct pollfd *fds,
5964
bool setup);
@@ -79,8 +84,9 @@ static const struct file_operations g_adc_fops =
7984

8085
static const struct adc_callback_s g_adc_callback =
8186
{
82-
adc_receive, /* au_receive */
83-
adc_reset /* au_reset */
87+
adc_receive, /* au_receive */
88+
adc_receive_batch, /* au_receive_batch */
89+
adc_reset /* au_reset */
8490
};
8591

8692
/****************************************************************************
@@ -301,8 +307,8 @@ static ssize_t adc_read(FAR struct file *filep, FAR char *buffer,
301307
nread = 0;
302308
do
303309
{
304-
FAR struct adc_msg_s *msg =
305-
&dev->ad_recv.af_buffer[dev->ad_recv.af_head];
310+
uint8_t channel = dev->ad_recv.af_channel[dev->ad_recv.af_head];
311+
int32_t data = dev->ad_recv.af_data[dev->ad_recv.af_head];
306312

307313
/* Will the next message in the FIFO fit into the user buffer? */
308314

@@ -317,22 +323,22 @@ static ssize_t adc_read(FAR struct file *filep, FAR char *buffer,
317323

318324
/* Feed ADC data to entropy pool */
319325

320-
add_sensor_randomness(msg->am_data);
326+
add_sensor_randomness(data);
321327

322328
/* Copy the message to the user buffer */
323329

324330
if (msglen == 1)
325331
{
326332
/* Only one channel, return MS 8-bits of the sample. */
327333

328-
buffer[nread] = msg->am_data >> 24;
334+
buffer[nread] = data >> 24;
329335
}
330336
else if (msglen == 2)
331337
{
332338
/* Only one channel, return only the MS 16-bits of the sample.
333339
*/
334340

335-
int16_t data16 = msg->am_data >> 16;
341+
int16_t data16 = data >> 16;
336342
memcpy(&buffer[nread], &data16, 2);
337343
}
338344
else if (msglen == 3)
@@ -341,8 +347,8 @@ static ssize_t adc_read(FAR struct file *filep, FAR char *buffer,
341347

342348
/* Return the channel and the MS 16-bits of the sample. */
343349

344-
buffer[nread] = msg->am_channel;
345-
data16 = msg->am_data >> 16;
350+
buffer[nread] = channel;
351+
data16 = data >> 16;
346352
memcpy(&buffer[nread + 1], &data16, 2);
347353
}
348354
else if (msglen == 4)
@@ -354,26 +360,26 @@ static ssize_t adc_read(FAR struct file *filep, FAR char *buffer,
354360
* which are indices: 0-2.
355361
*/
356362

357-
data24 = msg->am_data;
363+
data24 = data;
358364
#else
359365
/* In the little endian case, indices 0-2 correspond to the
360366
* the three LS bytes.
361367
*/
362368

363-
data24 = msg->am_data >> 8;
369+
data24 = data >> 8;
364370
#endif
365371

366372
/* Return the channel and the most significant 24-bits */
367373

368-
buffer[nread] = msg->am_channel;
374+
buffer[nread] = channel;
369375
memcpy(&buffer[nread + 1], &data24, 3);
370376
}
371377
else
372378
{
373379
/* Return the channel and all four bytes of the sample */
374380

375-
buffer[nread] = msg->am_channel;
376-
memcpy(&buffer[nread + 1], &msg->am_data, 4);
381+
buffer[nread] = channel;
382+
memcpy(&buffer[nread + 1], &data, 4);
377383
}
378384

379385
nread += msglen;
@@ -480,8 +486,8 @@ static int adc_receive(FAR struct adc_dev_s *dev, uint8_t ch, int32_t data)
480486
{
481487
/* Add the new, decoded ADC sample at the tail of the FIFO */
482488

483-
fifo->af_buffer[fifo->af_tail].am_channel = ch;
484-
fifo->af_buffer[fifo->af_tail].am_data = data;
489+
fifo->af_channel[fifo->af_tail] = ch;
490+
fifo->af_data[fifo->af_tail] = data;
485491

486492
/* Increment the tail of the circular buffer */
487493

@@ -495,6 +501,63 @@ static int adc_receive(FAR struct adc_dev_s *dev, uint8_t ch, int32_t data)
495501
return errcode;
496502
}
497503

504+
/****************************************************************************
505+
* Name: adc_receive_all
506+
****************************************************************************/
507+
508+
static int adc_receive_batch(FAR struct adc_dev_s *dev,
509+
FAR const uint8_t *channel,
510+
FAR const uint32_t *data,
511+
size_t count)
512+
{
513+
FAR struct adc_fifo_s *fifo = &dev->ad_recv;
514+
size_t used;
515+
size_t first;
516+
size_t second;
517+
518+
/* Check if adding this new message would over-run the drivers ability to
519+
* enqueue read data.
520+
*/
521+
522+
used = (fifo->af_tail - fifo->af_head + CONFIG_ADC_FIFOSIZE)
523+
% CONFIG_ADC_FIFOSIZE;
524+
525+
if (used + count >= CONFIG_ADC_FIFOSIZE)
526+
{
527+
return -ENOMEM;
528+
}
529+
530+
/* Check if flipping is required and memcopy */
531+
532+
first = MIN(count, CONFIG_ADC_FIFOSIZE - fifo->af_tail);
533+
second = count - first;
534+
535+
memcpy(&fifo->af_data[fifo->af_tail], data,
536+
first * sizeof(uint32_t));
537+
538+
if (channel != NULL)
539+
{
540+
memcpy(&fifo->af_channel[fifo->af_tail], channel, first);
541+
}
542+
543+
if (second > 0)
544+
{
545+
memcpy(&fifo->af_data[0], &data[first],
546+
second * sizeof(uint32_t));
547+
548+
if (channel != NULL)
549+
{
550+
memcpy(&fifo->af_channel[0], &channel[first], second);
551+
}
552+
}
553+
554+
fifo->af_tail = (fifo->af_tail + count) % CONFIG_ADC_FIFOSIZE;
555+
556+
adc_notify(dev);
557+
558+
return OK;
559+
}
560+
498561
/****************************************************************************
499562
* Name: adc_notify
500563
****************************************************************************/
@@ -655,6 +718,7 @@ static int adc_samples_on_read(FAR struct adc_dev_s *dev)
655718

656719
int adc_register(FAR const char *path, FAR struct adc_dev_s *dev)
657720
{
721+
FAR struct adc_fifo_s *fifo = &dev->ad_recv;
658722
int ret;
659723

660724
DEBUGASSERT(path != NULL && dev != NULL);
@@ -692,5 +756,9 @@ int adc_register(FAR const char *path, FAR struct adc_dev_s *dev)
692756
nxmutex_destroy(&dev->ad_closelock);
693757
}
694758

759+
/* Initialize the af_channale */
760+
761+
memset(&fifo->af_channel[fifo->af_tail], 0, CONFIG_ADC_FIFOSIZE);
762+
695763
return ret;
696764
}

include/nuttx/analog/adc.h

Lines changed: 25 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -44,8 +44,8 @@
4444
****************************************************************************/
4545

4646
/* Default configuration settings that may be overridden in the NuttX
47-
* configuration file. The configured size is limited to 255 to fit into a
48-
* uint8_t.
47+
* configuration file. The configured size is limited to 65535 to fit into
48+
* a uint16_t.
4949
*/
5050

5151
#if !defined(CONFIG_ADC_FIFOSIZE)
@@ -90,6 +90,26 @@ struct adc_callback_s
9090
CODE int (*au_receive)(FAR struct adc_dev_s *dev, uint8_t ch,
9191
int32_t data);
9292

93+
/* This method is called from the lower half, platform-specific ADC logic
94+
* when new ADC sample data is available,
95+
* enable transfer all data at once .
96+
*
97+
* Input Parameters:
98+
* dev - The ADC device structure that was previously registered by
99+
* adc_register()
100+
* channel - Pointer to the channel lists buffer
101+
* data - Pointer to the DMA buffer.
102+
* count - Number of data elements in the channelbuffer and databuffer.
103+
*
104+
* Returned Value:
105+
* Zero on success; a negated errno value on failure.
106+
*/
107+
108+
CODE int (*au_receive_batch)(FAR struct adc_dev_s *dev,
109+
FAR const uint8_t *channel,
110+
FAR const uint32_t *data,
111+
size_t count);
112+
93113
/* This method is called from the lower half, platform-specific ADC logic
94114
* when an overrun appeared to free / reset upper half.
95115
*
@@ -119,7 +139,9 @@ struct adc_fifo_s
119139
sem_t af_sem; /* Counting semaphore */
120140
uint16_t af_head; /* Index to the head [IN] index in the circular buffer */
121141
uint16_t af_tail; /* Index to the tail [OUT] index in the circular buffer */
122-
/* Circular buffer of CAN messages */
142+
/* Circular buffer of ADC messages */
143+
uint8_t af_channel[CONFIG_ADC_FIFOSIZE];
144+
int32_t af_data[CONFIG_ADC_FIFOSIZE];
123145
struct adc_msg_s af_buffer[CONFIG_ADC_FIFOSIZE];
124146
};
125147

0 commit comments

Comments
 (0)