4
4
* SPDX-License-Identifier: Apache-2.0
5
5
*/
6
6
7
- #define ADC_CONTEXT_USES_KERNEL_TIMER
8
7
#include "adc_context.h"
9
8
#include <nrfx_saadc.h>
10
9
#include <zephyr/dt-bindings/adc/nrf-saadc-v3.h>
@@ -104,15 +103,20 @@ struct driver_data {
104
103
uint8_t active_channel_cnt ;
105
104
void * mem_reg ;
106
105
void * user_buffer ;
106
+ struct k_timer timer ;
107
+ bool internal_timer_enabled ;
107
108
};
108
109
109
110
static struct driver_data m_data = {
110
- ADC_CONTEXT_INIT_TIMER (m_data , ctx ),
111
111
ADC_CONTEXT_INIT_LOCK (m_data , ctx ),
112
112
ADC_CONTEXT_INIT_SYNC (m_data , ctx ),
113
113
.mem_reg = DMM_DEV_TO_REG (DT_NODELABEL (adc )),
114
+ .internal_timer_enabled = false,
114
115
};
115
116
117
+ /* Maximum value of the internal timer interval in microseconds. */
118
+ #define ADC_INTERNAL_TIMER_INTERVAL_MAX_US 128U
119
+
116
120
/* Forward declaration */
117
121
static void event_handler (const nrfx_saadc_evt_t * event );
118
122
@@ -362,7 +366,7 @@ static int adc_nrfx_channel_setup(const struct device *dev,
362
366
nrfx_err_t ret = nrfx_saadc_channel_config (& cfg );
363
367
364
368
if (ret != NRFX_SUCCESS ) {
365
- LOG_ERR ("Cannot configure channel %d: %d " , channel_cfg -> channel_id , ret );
369
+ LOG_ERR ("Cannot configure channel %d: 0x%08x " , channel_cfg -> channel_id , ret );
366
370
return - EINVAL ;
367
371
}
368
372
@@ -385,22 +389,58 @@ static void adc_context_start_sampling(struct adc_context *ctx)
385
389
386
390
static void adc_context_update_buffer_pointer (struct adc_context * ctx , bool repeat )
387
391
{
388
- void * samples_buffer ;
392
+ if (!m_data .internal_timer_enabled ) {
393
+ void * samples_buffer ;
394
+
395
+ if (!repeat ) {
396
+ m_data .user_buffer =
397
+ (uint16_t * )m_data .user_buffer + m_data .active_channel_cnt ;
398
+ }
399
+
400
+ int error = dmm_buffer_in_prepare (
401
+ m_data .mem_reg , m_data .user_buffer ,
402
+ NRFX_SAADC_SAMPLES_TO_BYTES (m_data .active_channel_cnt ), & samples_buffer );
403
+ if (error != 0 ) {
404
+ LOG_ERR ("DMM buffer allocation failed err=%d" , error );
405
+ adc_context_complete (ctx , - EIO );
406
+ return ;
407
+ }
389
408
390
- if (!repeat ) {
391
- m_data .user_buffer = (uint16_t * )m_data .user_buffer + m_data .active_channel_cnt ;
409
+ nrfx_err_t nrfx_err =
410
+ nrfx_saadc_buffer_set (samples_buffer , m_data .active_channel_cnt );
411
+ if (nrfx_err != NRFX_SUCCESS ) {
412
+ LOG_ERR ("Failed to set buffer: 0x%08x" , nrfx_err );
413
+ adc_context_complete (ctx , - EIO );
414
+ }
392
415
}
416
+ }
393
417
394
- int error = dmm_buffer_in_prepare (
395
- m_data .mem_reg , m_data .user_buffer ,
396
- NRFX_SAADC_SAMPLES_TO_BYTES (m_data .active_channel_cnt ),
397
- & samples_buffer );
398
- if (error != 0 ) {
399
- LOG_ERR ("DMM buffer allocation failed err=%d" , error );
400
- adc_context_complete (ctx , - EIO );
418
+ static inline void adc_context_enable_timer (struct adc_context * ctx )
419
+ {
420
+ if (!m_data .internal_timer_enabled ) {
421
+ k_timer_start (& m_data .timer , K_NO_WAIT , K_USEC (ctx -> options .interval_us ));
422
+ } else {
423
+ nrfx_err_t ret = nrfx_saadc_mode_trigger ();
424
+
425
+ if (ret != NRFX_SUCCESS ) {
426
+ LOG_ERR ("Cannot start sampling: 0x%08x" , ret );
427
+ adc_context_complete (& m_data .ctx , - EIO );
428
+ }
401
429
}
430
+ }
431
+
432
+ static inline void adc_context_disable_timer (struct adc_context * ctx )
433
+ {
434
+ if (!m_data .internal_timer_enabled ) {
435
+ k_timer_stop (& m_data .timer );
436
+ }
437
+ }
402
438
403
- nrfx_saadc_buffer_set (samples_buffer , m_data .active_channel_cnt );
439
+ static void external_timer_expired_handler (struct k_timer * timer_id )
440
+ {
441
+ ARG_UNUSED (timer_id );
442
+
443
+ adc_context_request_next_sampling (& m_data .ctx );
404
444
}
405
445
406
446
static int get_resolution (const struct adc_sequence * sequence , nrf_saadc_resolution_t * resolution )
@@ -495,26 +535,48 @@ static bool has_single_ended(const struct adc_sequence *sequence)
495
535
return sequence -> channels & m_data .single_ended_channels ;
496
536
}
497
537
498
- static void correct_single_ended (const struct adc_sequence * sequence , nrf_saadc_value_t * buffer )
538
+ static void correct_single_ended (const struct adc_sequence * sequence , nrf_saadc_value_t * buffer ,
539
+ uint16_t num_samples )
499
540
{
500
- uint16_t channel_bit = BIT (0 );
501
- uint8_t selected_channels = sequence -> channels ;
502
- uint8_t single_ended_channels = m_data .single_ended_channels ;
503
541
int16_t * sample = (int16_t * )buffer ;
504
542
505
- while ( channel_bit <= single_ended_channels ) {
506
- if ( channel_bit & selected_channels ) {
507
- if (( channel_bit & single_ended_channels ) && ( * sample < 0 ) ) {
508
- * sample = 0 ;
543
+ if ( m_data . internal_timer_enabled ) {
544
+ for ( int i = 0 ; i < num_samples ; i ++ ) {
545
+ if (sample [ i ] < 0 ) {
546
+ sample [ i ] = 0 ;
509
547
}
548
+ }
549
+ } else {
550
+ uint8_t selected_channels = sequence -> channels ;
551
+ uint8_t single_ended_channels = m_data .single_ended_channels ;
510
552
553
+ for (uint16_t channel_bit = BIT (0 ); channel_bit <= single_ended_channels ;
554
+ channel_bit <<= 1 ) {
555
+ if ((channel_bit & selected_channels & single_ended_channels ) &&
556
+ (* sample < 0 )) {
557
+ * sample = 0 ;
558
+ }
511
559
sample ++ ;
512
560
}
513
-
514
- channel_bit <<= 1 ;
515
561
}
516
562
}
517
563
564
+ /* The internal timer runs at 16 MHz, so to convert the interval in microseconds
565
+ * to the internal timer CC value, we can use the formula:
566
+ * interval_cc = interval_us * 16 MHz
567
+ * where 16 MHz is the frequency of the internal timer.
568
+ *
569
+ * The maximum value for interval_cc is 2047, which corresponds to
570
+ * approximately 7816 Hz ~ 128us.
571
+ * The minimum value for interval_cc is depends on the SoC.
572
+ */
573
+ static inline uint16_t interval_to_cc (uint16_t interval_us )
574
+ {
575
+ NRFX_ASSERT ((interval_us <= ADC_INTERNAL_TIMER_INTERVAL_MAX_US ) && (interval_us > 0 ));
576
+
577
+ return (interval_us * 16 ) - 1 ;
578
+ }
579
+
518
580
static int start_read (const struct device * dev ,
519
581
const struct adc_sequence * sequence )
520
582
{
@@ -562,10 +624,29 @@ static int start_read(const struct device *dev,
562
624
return error ;
563
625
}
564
626
565
- nrfx_err = nrfx_saadc_simple_mode_set (selected_channels ,
566
- resolution ,
567
- oversampling ,
568
- event_handler );
627
+ if ((active_channel_cnt == 1 ) && (sequence -> options != NULL ) &&
628
+ (sequence -> options -> callback == NULL ) &&
629
+ (sequence -> options -> interval_us <= ADC_INTERNAL_TIMER_INTERVAL_MAX_US ) &&
630
+ (sequence -> options -> interval_us > 0 )) {
631
+
632
+ nrfx_saadc_adv_config_t adv_config = {
633
+ .oversampling = oversampling ,
634
+ .burst = NRF_SAADC_BURST_DISABLED ,
635
+ .internal_timer_cc = interval_to_cc (sequence -> options -> interval_us ),
636
+ .start_on_end = true,
637
+ };
638
+
639
+ m_data .internal_timer_enabled = true;
640
+
641
+ nrfx_err = nrfx_saadc_advanced_mode_set (selected_channels , resolution , & adv_config ,
642
+ event_handler );
643
+ } else {
644
+ m_data .internal_timer_enabled = false;
645
+
646
+ nrfx_err = nrfx_saadc_simple_mode_set (selected_channels , resolution , oversampling ,
647
+ event_handler );
648
+ }
649
+
569
650
if (nrfx_err != NRFX_SUCCESS ) {
570
651
return - EINVAL ;
571
652
}
@@ -578,10 +659,12 @@ static int start_read(const struct device *dev,
578
659
m_data .active_channel_cnt = active_channel_cnt ;
579
660
m_data .user_buffer = sequence -> buffer ;
580
661
581
- error = dmm_buffer_in_prepare (m_data .mem_reg ,
582
- m_data .user_buffer ,
583
- NRFX_SAADC_SAMPLES_TO_BYTES (active_channel_cnt ),
584
- & samples_buffer );
662
+ error = dmm_buffer_in_prepare (
663
+ m_data .mem_reg , m_data .user_buffer ,
664
+ (m_data .internal_timer_enabled
665
+ ? NRFX_SAADC_SAMPLES_TO_BYTES (1 + sequence -> options -> extra_samplings )
666
+ : NRFX_SAADC_SAMPLES_TO_BYTES (active_channel_cnt )),
667
+ & samples_buffer );
585
668
if (error != 0 ) {
586
669
LOG_ERR ("DMM buffer allocation failed err=%d" , error );
587
670
return error ;
@@ -590,7 +673,15 @@ static int start_read(const struct device *dev,
590
673
/* Buffer is filled in chunks, each chunk composed of number of samples equal to number
591
674
* of active channels. Buffer pointer is advanced and reloaded after each chunk.
592
675
*/
593
- nrfx_saadc_buffer_set (samples_buffer , active_channel_cnt );
676
+ nrfx_err = nrfx_saadc_buffer_set (
677
+ samples_buffer ,
678
+ (m_data .internal_timer_enabled
679
+ ? (1 + sequence -> options -> extra_samplings )
680
+ : active_channel_cnt ));
681
+ if (nrfx_err != NRFX_SUCCESS ) {
682
+ LOG_ERR ("Failed to set buffer: 0x%08x" , nrfx_err );
683
+ return - EINVAL ;
684
+ }
594
685
595
686
adc_context_start_read (& m_data .ctx , sequence );
596
687
@@ -633,11 +724,15 @@ static void event_handler(const nrfx_saadc_evt_t *event)
633
724
if (event -> type == NRFX_SAADC_EVT_DONE ) {
634
725
dmm_buffer_in_release (
635
726
m_data .mem_reg , m_data .user_buffer ,
636
- NRFX_SAADC_SAMPLES_TO_BYTES (m_data .active_channel_cnt ),
727
+ (m_data .internal_timer_enabled
728
+ ? NRFX_SAADC_SAMPLES_TO_BYTES (
729
+ 1 + m_data .ctx .sequence .options -> extra_samplings )
730
+ : NRFX_SAADC_SAMPLES_TO_BYTES (m_data .active_channel_cnt )),
637
731
event -> data .done .p_buffer );
638
732
639
733
if (has_single_ended (& m_data .ctx .sequence )) {
640
- correct_single_ended (& m_data .ctx .sequence , m_data .user_buffer );
734
+ correct_single_ended (& m_data .ctx .sequence , m_data .user_buffer ,
735
+ event -> data .done .size );
641
736
}
642
737
nrfy_saadc_disable (NRF_SAADC );
643
738
adc_context_on_sampling_done (& m_data .ctx , DEVICE_DT_INST_GET (0 ));
@@ -647,13 +742,17 @@ static void event_handler(const nrfx_saadc_evt_t *event)
647
742
LOG_ERR ("Cannot start sampling: 0x%08x" , err );
648
743
adc_context_complete (& m_data .ctx , - EIO );
649
744
}
745
+ } else if (event -> type == NRFX_SAADC_EVT_FINISHED ) {
746
+ adc_context_complete (& m_data .ctx , 0 );
650
747
}
651
748
}
652
749
653
750
static int init_saadc (const struct device * dev )
654
751
{
655
752
nrfx_err_t err ;
656
753
754
+ k_timer_init (& m_data .timer , external_timer_expired_handler , NULL );
755
+
657
756
/* The priority value passed here is ignored (see nrfx_glue.h). */
658
757
err = nrfx_saadc_init (0 );
659
758
if (err != NRFX_SUCCESS ) {
0 commit comments