@@ -223,11 +223,12 @@ static int adc_close(FAR struct file *filep)
223
223
static ssize_t adc_read (FAR struct file * filep , FAR char * buffer ,
224
224
size_t buflen )
225
225
{
226
- FAR struct inode * inode = filep -> f_inode ;
227
- FAR struct adc_dev_s * dev = inode -> i_private ;
226
+ FAR struct inode * inode = filep -> f_inode ;
227
+ FAR struct adc_dev_s * dev = inode -> i_private ;
228
+ FAR struct adc_fifo_s * fifo = & dev -> ad_recv ;
228
229
size_t nread ;
229
230
irqstate_t flags ;
230
- int ret = 0 ;
231
+ int ret = 0 ;
231
232
int msglen ;
232
233
233
234
ainfo ("buflen: %d\n" , (int )buflen );
@@ -267,10 +268,10 @@ static ssize_t adc_read(FAR struct file *filep, FAR char *buffer,
267
268
268
269
if (buflen >= msglen )
269
270
{
270
- /* Interrupts must be disabled while accessing the ad_recv FIFO */
271
+ /* Interrupts must be disabled while accessing the fifo FIFO */
271
272
272
273
flags = enter_critical_section ();
273
- while (dev -> ad_recv . af_head == dev -> ad_recv . af_tail )
274
+ while (fifo -> af_head == fifo -> af_tail )
274
275
{
275
276
/* Check if there was an overrun, if set we need to return EIO */
276
277
@@ -292,106 +293,114 @@ static ssize_t adc_read(FAR struct file *filep, FAR char *buffer,
292
293
/* Wait for a message to be received */
293
294
294
295
dev -> ad_nrxwaiters ++ ;
295
- ret = nxsem_wait (& dev -> ad_recv . af_sem );
296
+ ret = nxsem_wait (& fifo -> af_sem );
296
297
dev -> ad_nrxwaiters -- ;
297
298
if (ret < 0 )
298
299
{
299
300
goto return_with_irqdisabled ;
300
301
}
301
302
}
302
303
303
- /* The ad_recv FIFO is not empty. Copy all buffered data that will fit
304
+ /* The FIFO is not empty. Copy all buffered data that will fit
304
305
* in the user buffer.
305
306
*/
306
307
307
- nread = 0 ;
308
- do
308
+ if (msglen == 4 )
309
309
{
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 ];
312
-
313
- /* Will the next message in the FIFO fit into the user buffer? */
314
-
315
- if (nread + msglen > buflen )
316
- {
317
- /* No.. break out of the loop now with nread equal to the
318
- * actual number of bytes transferred.
319
- */
310
+ size_t first ;
311
+ size_t second ;
312
+ size_t count ;
313
+ size_t used ;
320
314
321
- break ;
322
- }
315
+ used = (fifo -> af_tail - fifo -> af_head + CONFIG_ADC_FIFOSIZE )
316
+ % CONFIG_ADC_FIFOSIZE ;
317
+ count = MIN (used , buflen / msglen );
323
318
324
- /* Feed ADC data to entropy pool */
319
+ /* Check if flipping is required and memcopy */
325
320
326
- add_sensor_randomness (data );
321
+ first = MIN (CONFIG_ADC_FIFOSIZE - fifo -> af_head , count );
322
+ second = count - first ;
323
+ memcpy (buffer , & fifo -> af_data [fifo -> af_head ], first * 4 );
327
324
328
- /* Copy the message to the user buffer */
329
-
330
- if (msglen == 1 )
325
+ if (second > 0 )
331
326
{
332
- /* Only one channel, return MS 8-bits of the sample. */
333
-
334
- buffer [nread ] = data >> 24 ;
327
+ memcpy (& buffer [4 * first ], & fifo -> af_data [0 ], second * 4 );
335
328
}
336
- else if (msglen == 2 )
329
+
330
+ fifo -> af_head = (fifo -> af_head + count ) % CONFIG_ADC_FIFOSIZE ;
331
+ nread = count * msglen ;
332
+ }
333
+ else
334
+ {
335
+ nread = 0 ;
336
+ do
337
337
{
338
- /* Only one channel, return only the MS 16-bits of the sample.
338
+ uint8_t channel = fifo -> af_channel [fifo -> af_head ];
339
+ int32_t data = fifo -> af_data [fifo -> af_head ];
340
+
341
+ /* Will the next message in the FIFO fit into
342
+ * the user buffer?
339
343
*/
340
344
341
- int16_t data16 = data >> 16 ;
342
- memcpy (& buffer [nread ], & data16 , 2 );
343
- }
344
- else if (msglen == 3 )
345
- {
346
- int16_t data16 ;
345
+ if (nread + msglen > buflen )
346
+ {
347
+ /* No.. break out of the loop now with nread equal to the
348
+ * actual number of bytes transferred.
349
+ */
347
350
348
- /* Return the channel and the MS 16-bits of the sample. */
351
+ break ;
352
+ }
349
353
350
- buffer [nread ] = channel ;
351
- data16 = data >> 16 ;
352
- memcpy (& buffer [nread + 1 ], & data16 , 2 );
353
- }
354
- else if (msglen == 4 )
355
- {
356
- int32_t data24 ;
354
+ /* Feed ADC data to entropy pool */
357
355
358
- #ifdef CONFIG_ENDIAN_BIG
359
- /* In the big endian case, we simply copy the MS three bytes
360
- * which are indices: 0-2.
361
- */
356
+ add_sensor_randomness (data );
362
357
363
- data24 = data ;
364
- #else
365
- /* In the little endian case, indices 0-2 correspond to the
366
- * the three LS bytes.
367
- */
358
+ /* Copy the message to the user buffer */
368
359
369
- data24 = data >> 8 ;
370
- #endif
360
+ if (msglen == 1 )
361
+ {
362
+ /* Only one channel, return MS 8-bits of the sample. */
371
363
372
- /* Return the channel and the most significant 24-bits */
364
+ buffer [nread ] = data >> 24 ;
365
+ }
366
+ else if (msglen == 2 )
367
+ {
368
+ /* Only one channel, return only the
369
+ * MS 16-bits of the sample.
370
+ */
373
371
374
- buffer [ nread ] = channel ;
375
- memcpy (& buffer [nread + 1 ], & data24 , 3 );
376
- }
377
- else
378
- {
379
- /* Return the channel and all four bytes of the sample */
372
+ int16_t data16 = data >> 16 ;
373
+ memcpy (& buffer [nread ], & data16 , 2 );
374
+ }
375
+ else if ( msglen == 3 )
376
+ {
377
+ int16_t data16 ;
380
378
381
- buffer [nread ] = channel ;
382
- memcpy (& buffer [nread + 1 ], & data , 4 );
383
- }
379
+ /* Return the channel and the MS 16-bits of the sample. */
384
380
385
- nread += msglen ;
381
+ buffer [nread ] = channel ;
382
+ data16 = data >> 16 ;
383
+ memcpy (& buffer [nread + 1 ], & data16 , 2 );
384
+ }
385
+ else
386
+ {
387
+ /* Return the channel and all four bytes of the sample */
386
388
387
- /* Increment the head of the circular message buffer */
389
+ buffer [nread ] = channel ;
390
+ memcpy (& buffer [nread + 1 ], & data , 4 );
391
+ }
388
392
389
- if (++ dev -> ad_recv .af_head >= CONFIG_ADC_FIFOSIZE )
390
- {
391
- dev -> ad_recv .af_head = 0 ;
393
+ nread += msglen ;
394
+
395
+ /* Increment the head of the circular message buffer */
396
+
397
+ if (++ fifo -> af_head >= CONFIG_ADC_FIFOSIZE )
398
+ {
399
+ fifo -> af_head = 0 ;
400
+ }
392
401
}
402
+ while (fifo -> af_head != fifo -> af_tail );
393
403
}
394
- while (dev -> ad_recv .af_head != dev -> ad_recv .af_tail );
395
404
396
405
/* All of the messages have been transferred. Return the number of
397
406
* bytes that were read.
0 commit comments