forked from nuttx/nuttx-update
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 <zhangkai25@xiaomi.com>
This commit is contained in:
parent
b584b38983
commit
bfd6185f4a
2 changed files with 109 additions and 19 deletions
|
@ -24,6 +24,7 @@
|
|||
|
||||
#include <nuttx/config.h>
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/types.h>
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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];
|
||||
};
|
||||
|
||||
|
|
Loading…
Reference in a new issue