1
0
Fork 0
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:
zhangkai25 2024-07-16 16:48:08 +08:00 committed by Xiang Xiao
parent b584b38983
commit bfd6185f4a
2 changed files with 109 additions and 19 deletions

View file

@ -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;
}

View file

@ -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];
};