<?xml version="1.0" encoding="UTF-8" ?>
<?xml-stylesheet type="text/xsl" href="https://devzone.nordicsemi.com/cfs-file/__key/system/syndication/rss.xsl" media="screen"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Running SAADC in continuous mode without timer/ppi trigger</title><link>https://devzone.nordicsemi.com/f/nordic-q-a/83320/running-saadc-in-continuous-mode-without-timer-ppi-trigger</link><description>Hi All, 
 I have problem running nRF5340 in continuous mode without any external trigger (timer/ppi). I would like to setup SAADC so that last conversion triggered new set of conversions. 
 I&amp;#39;m using nrfx_saadc_advanced_mode_set function with internal_timer_cc</description><dc:language>en-US</dc:language><generator>Telligent Community 13</generator><lastBuildDate>Fri, 14 Jan 2022 11:54:31 GMT</lastBuildDate><atom:link rel="self" type="application/rss+xml" href="https://devzone.nordicsemi.com/f/nordic-q-a/83320/running-saadc-in-continuous-mode-without-timer-ppi-trigger" /><item><title>RE: Running SAADC in continuous mode without timer/ppi trigger</title><link>https://devzone.nordicsemi.com/thread/347751?ContentTypeID=1</link><pubDate>Fri, 14 Jan 2022 11:54:31 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:12739357-db73-46c9-acb7-d6abb6bf7055</guid><dc:creator>J&amp;#248;rgen Holmefjord</dc:creator><description>&lt;p&gt;Hi,&lt;/p&gt;
&lt;p&gt;You need to trigger the SAMPLE task once for each time the SAADC should sample each enabled channel once. If you set the buffer size to 2xnum_enabled_channels, you need to trigger the SAMPLE task twice for the buffer to be filled and the END event to be generated by the SAADC peripheral. The DONE event from the peripheral is only used when doing oversampling with burst. The&amp;nbsp;&lt;span&gt;NRFX_SAADC_EVT_DONE event from the driver is only triggered by the END event from the peripheral. The naming is maybe a bit confusing, as DONE from the driver does not correspond to the DONE event from the peripheral.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;You need to trigger the SAMPLE task twice, with a delay in between corresponding to num_enabled_channels x (configured acquisition time + conversion time).&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;Best regards,&lt;br /&gt;Jørgen&lt;/span&gt;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: Running SAADC in continuous mode without timer/ppi trigger</title><link>https://devzone.nordicsemi.com/thread/346817?ContentTypeID=1</link><pubDate>Sun, 09 Jan 2022 18:18:25 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:c12acf8e-61b6-493b-89bd-94d139dbe2ad</guid><dc:creator>pamo</dc:creator><description>&lt;p&gt;Hi,&lt;/p&gt;
&lt;p&gt;I have created sample code below with two channels setup. It works when ADC_BUFFER_SIZE is set to 2. This defines buffer size for samples. I get NRFX_SAADC_EVT_READY in first callback and then alternately NRFX_SAADC_EVT_DONE and NRFX_SAADC_EVT_BUF_REQ.&lt;/p&gt;
&lt;p&gt;However, when i changed ADC_BUFFER_SIZE to 4 (to fit 2 samples for each channel) I only get NRFX_SAADC_EVT_READY and don&amp;#39;t have any samples. I expected to get NRFX_SAADC_EVT_DONE twice and then one NRFX_SAADC_EVT_BUF_REQ. Can you tell me why buffer size can&amp;#39;t be bigger than number of channels?&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="c_cpp"&gt;#include &amp;lt;kernel.h&amp;gt;
#include &amp;lt;nrfx_saadc.h&amp;gt;

#define ADC_BUFFER_SIZE 2
static nrf_saadc_value_t adcBuffer[2][ADC_BUFFER_SIZE];

uint8_t currentBuffer = 0;

static void adcCallback( nrfx_saadc_evt_t const * p_event )
{
    nrfx_saadc_evt_type_t eventType = p_event-&amp;gt;type;

    switch( eventType )
    {
        case NRFX_SAADC_EVT_DONE:
        {
            nrf_saadc_task_trigger(NRF_SAADC, NRF_SAADC_TASK_SAMPLE);
        }
        break;

        case NRFX_SAADC_EVT_LIMIT:
        {
        }
        break;

        case NRFX_SAADC_EVT_CALIBRATEDONE:
        {
        }
        break;

        case NRFX_SAADC_EVT_BUF_REQ:
        {
            nrfx_saadc_buffer_set( adcBuffer[currentBuffer], ADC_BUFFER_SIZE );
            ++currentBuffer;
            currentBuffer = currentBuffer % 2;
        }
        break;

        case NRFX_SAADC_EVT_READY:
        {
            nrf_saadc_task_trigger(NRF_SAADC, NRF_SAADC_TASK_SAMPLE);
        }
        break;

        case NRFX_SAADC_EVT_FINISHED:
        {
        }
        break;
    }
}

/*!
 * @brief Application entry point.
 */
int main( int argc, char** argv )
{
    printk(&amp;quot;ADC example on %s\n&amp;quot;, CONFIG_BOARD);

    nrfx_saadc_channel_t channelConfig = {
        .channel_config =
            {
                .resistor_p = NRF_SAADC_RESISTOR_DISABLED,
                .resistor_n = NRF_SAADC_RESISTOR_DISABLED,
                .gain       = NRF_SAADC_GAIN1_4,
                .reference  = SAADC_CH_CONFIG_REFSEL_VDD1_4,
                .acq_time   = SAADC_CH_CONFIG_TACQ_40us,
                .mode       = NRF_SAADC_MODE_SINGLE_ENDED,
                .burst      = NRF_SAADC_BURST_DISABLED,
            },
            .pin_p          = NRF_SAADC_INPUT_AIN0,
            .pin_n          = NRF_SAADC_INPUT_DISABLED,
            .channel_index  = 0
    };

    nrfx_saadc_adv_config_t adcAdvancedConfig = NRFX_SAADC_DEFAULT_ADV_CONFIG;
    adcAdvancedConfig.start_on_end = true;

    nrfx_err_t nrfxError = nrfx_saadc_init( 0 );

    IRQ_DIRECT_CONNECT( SAADC_IRQn, 0, nrfx_saadc_irq_handler, IRQ_ZERO_LATENCY );

    // First channel.
    nrfxError = nrfx_saadc_channel_config( &amp;amp;channelConfig );

    // Second channel.
    channelConfig.pin_p = NRF_SAADC_INPUT_AIN1;
    channelConfig.channel_index = 1;

    nrfxError = nrfx_saadc_channel_config( &amp;amp;channelConfig );
    nrfxError = nrfx_saadc_advanced_mode_set( 0x03, NRF_SAADC_RESOLUTION_12BIT, &amp;amp;adcAdvancedConfig, adcCallback );

    // Set buffers.
    nrfxError = nrfx_saadc_buffer_set( adcBuffer[0], ADC_BUFFER_SIZE );
    nrfxError = nrfx_saadc_buffer_set( adcBuffer[1], ADC_BUFFER_SIZE );

    // Trigger conversion.
    nrfxError = nrfx_saadc_mode_trigger();

    while( 1 )
    {
        printk( &amp;quot;ADC1: p_buffer = %d\n&amp;quot;, adcBuffer[currentBuffer][0] );
        printk( &amp;quot;ADC2: p_buffer = %d\n&amp;quot;, adcBuffer[currentBuffer][1] );
        k_msleep( 1000 );
    };

    return 0;
}&lt;/pre&gt;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: Running SAADC in continuous mode without timer/ppi trigger</title><link>https://devzone.nordicsemi.com/thread/345960?ContentTypeID=1</link><pubDate>Tue, 04 Jan 2022 15:36:10 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:5f03c6fb-f6fa-446e-9a4e-1ed845fae5a4</guid><dc:creator>J&amp;#248;rgen Holmefjord</dc:creator><description>&lt;p&gt;You still need to trigger the SAMPLE task externally when internal_timer_cc is set to 0, even it you call nrfx_saadc_mode_trigger(). This is from the &lt;a href="https://infocenter.nordicsemi.com/topic/drivers_nrfx_v2.7.0/group__nrfx__saadc.html#ga0aef394cddf65e474f0d418fa2bc3c8f"&gt;SAADC driver API documentation&lt;/a&gt;:&lt;/p&gt;
&lt;p&gt;&lt;em&gt;&amp;quot;When performing conversions in the non-blocking manner and&amp;nbsp;&lt;a href="https://infocenter.nordicsemi.com/topic/drivers_nrfx_v2.7.0/structnrfx__saadc__adv__config__t.html#a4d08d3f8c0a1b4ca5d6dea339d665d1b"&gt;nrfx_saadc_adv_config_t::internal_timer_cc&lt;/a&gt;&amp;nbsp;is set to 0, sampling needs to be done by triggering&amp;nbsp;&lt;a href="https://infocenter.nordicsemi.com/topic/drivers_nrfx_v2.7.0/group__nrf__saadc__hal.html#ggacde3c3040c12e04f9edc2bc92c1b2276a53f835ed3f4b6e9ff24d1550ead3c941"&gt;NRF_SAADC_TASK_SAMPLE&lt;/a&gt;&amp;nbsp;externally (for example by using the TIMER and/or the PPI/DPPI).&amp;quot;&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;If you do not want to use PPI, you can trigger it in your application similar to how the driver does it for the blocking mode:&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="c_cpp"&gt;nrf_saadc_task_trigger(NRF_SAADC, NRF_SAADC_TASK_SAMPLE);&lt;/pre&gt;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: Running SAADC in continuous mode without timer/ppi trigger</title><link>https://devzone.nordicsemi.com/thread/345955?ContentTypeID=1</link><pubDate>Tue, 04 Jan 2022 15:15:02 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:6dfb012e-0956-4bd7-bede-ddc31a4c01d5</guid><dc:creator>pamo</dc:creator><description>&lt;p&gt;I&amp;#39;m using advanced mode because I need to fill buffer with couple of samples from each channel. As I understand in simple mode I&amp;#39;m going to get only one sample per each channel.&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;I&amp;#39;m using nrfx_saadc_mode_trigger to trigger conversion, I forgot to mention that in previous post. Attaching code snippet might be hard as I&amp;#39;m doing stuff in different places of code.&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: Running SAADC in continuous mode without timer/ppi trigger</title><link>https://devzone.nordicsemi.com/thread/345946?ContentTypeID=1</link><pubDate>Tue, 04 Jan 2022 14:35:23 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:3a01c0a0-84a8-4f2b-a7b0-24abec3c755b</guid><dc:creator>J&amp;#248;rgen Holmefjord</dc:creator><description>&lt;p&gt;Hi,&lt;/p&gt;
&lt;p&gt;It would help to determine exactly what the problem if you could post the exact code you used for configuring the SAADC, but it sounds like you are missing a trigger of the sampling.&lt;/p&gt;
&lt;p&gt;The advanced mode is mainly intended for use with PPI and external triggering of the sampling. Setting&amp;nbsp;&lt;span&gt;internal_timer_cc&amp;nbsp;to 0 will &lt;a href="https://github.com/NordicSemiconductor/nrfx/blob/v2.7.0/drivers/src/nrfx_saadc.c#L438"&gt;disable continuous mode&lt;/a&gt; (the internal sampling timer in the SAADC peripheral).In the interrupt handler, the SAMPLE task is only triggered on STARTED event &lt;a href="https://github.com/NordicSemiconductor/nrfx/blob/v2.7.0/drivers/src/nrfx_saadc.c#L756-L760"&gt;if continuous mode is enabled&lt;/a&gt;&amp;nbsp;(in advanced mode).&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;Setting start_on_end will only&amp;nbsp;cause the driver to &lt;a href="https://github.com/NordicSemiconductor/nrfx/blob/v2.7.0/drivers/src/nrfx_saadc.c#L822-L825"&gt;trigger the START task&lt;/a&gt;&amp;nbsp;in the interrupt handler when the END event is received, if this is not set, you need to do this in the application through PPI (this is done to mitigate &lt;a href="https://devzone.nordicsemi.com/f/nordic-q-a/20291/offset-in-saadc-samples-with-easy-dma-and-ble/79053#79053"&gt;this issue&lt;/a&gt;).&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;The SAMPLE task is triggered in the driver in simple mode, &lt;a href="https://github.com/NordicSemiconductor/nrfx/blob/v2.7.0/drivers/src/nrfx_saadc.c#L540"&gt;right away if no event handler is provided&lt;/a&gt;, or &lt;a href="https://github.com/NordicSemiconductor/nrfx/blob/v2.7.0/drivers/src/nrfx_saadc.c#L782"&gt;in the interrupt handler when the STARTED event is received&lt;/a&gt;. The SAMPLE task is also triggered in nrfx_saadc_mode_trigger() &lt;a href="https://github.com/NordicSemiconductor/nrfx/blob/v2.7.0/drivers/src/nrfx_saadc.c#L582-L591"&gt;in advanced mode if no event handler is provided&lt;/a&gt;.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;Do you require to use the advanced mode? Sounds like the simple mode may suit your requirements better.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;Best regards,&lt;br /&gt;Jørgen&lt;/span&gt;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item></channel></rss>