AnsweredAssumed Answered

ADC_ETC software trigger with sync for both ADC1 & ADC2?

Question asked by Jack King on Aug 5, 2018
Latest reply on Aug 12, 2018 by Jack King

I see in the SDK sample for software triggered ADC_ETC, it triggers the conversion for ADC1 only. 

 

The trigger also has a sync mode to trigger both ADC1 and ADC2 simultaneously that I would like to try. 

 

I am able to get the "done" interrupts triggered for both ADC1 and ADC2 from a single trigger once, but after that it doesn't trigger again. 

 

Also the results output isn't as expected for both converters.  I'm not sure how to set up the chain length and channels for the ADC_ETC as the SDK API reference manual seems to be missing quite a bit for ADC_ETC module.

Actually I don't even understand what a "chain" is, as it isn't documented well.  Do I need two chains when using "sync" mode?  I imagine my error is somewhere in the TriggerChainConfig sections.

 

Here is my modified sample code for both converters:

/*
* The Clear BSD License
* Copyright 2017 NXP
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted (subject to the limitations in the disclaimer below) provided
*  that the following conditions are met:
*
* o Redistributions of source code must retain the above copyright notice, this list
*   of conditions and the following disclaimer.
*
* o Redistributions in binary form must reproduce the above copyright notice, this
*   list of conditions and the following disclaimer in the documentation and/or
*   other materials provided with the distribution.
*
* o Neither the name of the copyright holder nor the names of its
*   contributors may be used to endorse or promote products derived from this
*   software without specific prior written permission.
*
* NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED BY THIS LICENSE.
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/


#include "fsl_debug_console.h"
#include "board.h"
#include "fsl_adc.h"
#include "fsl_adc_etc.h"
#include "fsl_common.h"

#include "pin_mux.h"
#include "clock_config.h"
/*******************************************************************************
* Definitions
******************************************************************************/

#define DEMO_ADC_BASE ADC1
#define DEMO_ADC_USER_CHANNEL 9U
#define DEMO_ADC_CHANNEL_GROUP 0U

#define DEMO_ADC2_BASE ADC2
#define DEMO_ADC2_USER_CHANNEL 10U
#define DEMO_ADC2_CHANNEL_GROUP 0U

#define DEMO_ADC_ETC_BASE ADC_ETC
#define DEMO_ADC_ETC_CHAIN_LENGTH 1U
#define DEMO_ADC_ETC_CHANNEL 15U
#define EXAMPLE_ADC_ETC_DONE0_Handler ADC_ETC_IRQ0_IRQHandler
#define EXAMPLE_ADC_ETC_DONE1_Handler ADC_ETC_IRQ1_IRQHandler

/*******************************************************************************
* Prototypes
******************************************************************************/

void ADC_Configuration(void);
/*******************************************************************************
* Variables
******************************************************************************/

volatile bool g_AdcConversionDoneFlag;
volatile bool g_AdcConversionDoneFlag2;
volatile uint32_t g_AdcConversionValue;
volatile uint32_t g_AdcConversionValue2;
/*******************************************************************************
* Code
******************************************************************************/

void EXAMPLE_ADC_ETC_DONE0_Handler(void)
{
    ADC_ETC_ClearInterruptStatusFlags(DEMO_ADC_ETC_BASE, kADC_ETC_Trg0TriggerSource, kADC_ETC_Done0StatusFlagMask);
    g_AdcConversionDoneFlag = true;
    g_AdcConversionValue = ADC_ETC_GetADCConversionValue(DEMO_ADC_ETC_BASE, 0U, 0U); /* Get trigger0 chain0 result. */
    //g_AdcConversionValue2 = ADC_ETC_GetADCConversionValue(DEMO_ADC_ETC_BASE, 1U, 0U); /* Get trigger0 chain0 result. */
}

void EXAMPLE_ADC_ETC_DONE1_Handler(void)
{
    ADC_ETC_ClearInterruptStatusFlags(DEMO_ADC_ETC_BASE, kADC_ETC_Trg0TriggerSource, kADC_ETC_Done1StatusFlagMask);
    g_AdcConversionDoneFlag2 = true;
    g_AdcConversionValue2 = ADC_ETC_GetADCConversionValue(DEMO_ADC_ETC_BASE, 0U, 1U); /* Get trigger0 chain1 result. */
}

/*!
* @brief Main function.
*/

int main(void)
{
    adc_etc_config_t adcEtcConfig;
    adc_etc_trigger_config_t adcEtcTriggerConfig;
    adc_etc_trigger_chain_config_t adcEtcTriggerChainConfig;

    BOARD_ConfigMPU();
    BOARD_InitPins();
    BOARD_BootClockRUN();
    BOARD_InitDebugConsole();

    PRINTF("ADC_ETC_Software_Trigger_Conv Example Start!\r\n");

    ADC_Configuration();

    /* Initialize the ADC_ETC. */
    ADC_ETC_GetDefaultConfig(&adcEtcConfig);
    adcEtcConfig.XBARtriggerMask = 1U; /* Enable the external XBAR trigger0. */
    ADC_ETC_Init(DEMO_ADC_ETC_BASE, &adcEtcConfig);

    /* Set the external XBAR trigger0 configuration. */
    adcEtcTriggerConfig.enableSyncMode = true;
    adcEtcTriggerConfig.enableSWTriggerMode = true;
    adcEtcTriggerConfig.triggerChainLength = DEMO_ADC_ETC_CHAIN_LENGTH; /* Chain length is 1. */
    adcEtcTriggerConfig.triggerPriority = 0U;
    adcEtcTriggerConfig.sampleIntervalDelay = 0U;
    adcEtcTriggerConfig.initialDelay = 0U;
    ADC_ETC_SetTriggerConfig(DEMO_ADC_ETC_BASE, 0U, &adcEtcTriggerConfig);

    /* Set the external XBAR trigger0 chain0 configuration. */
    adcEtcTriggerChainConfig.enableB2BMode = false;
    adcEtcTriggerChainConfig.ADCHCRegisterSelect = 1U
                                                   << DEMO_ADC_CHANNEL_GROUP; /* Select ADC_HC0 register to trigger. */
    adcEtcTriggerChainConfig.ADCChannelSelect =
        DEMO_ADC_ETC_CHANNEL; /* ADC_HC0 will be triggered to sample Corresponding channel. */
    adcEtcTriggerChainConfig.InterruptEnable = kADC_ETC_Done0InterruptEnable; /* Enable the Done0 interrupt. */
    ADC_ETC_SetTriggerChainConfig(DEMO_ADC_ETC_BASE, 0U, 0U,
                                  &adcEtcTriggerChainConfig); /* Configure the trigger0 chain0. */

    /* Set the external XBAR trigger0 chain1 configuration. */
    adcEtcTriggerChainConfig.enableB2BMode = false;
    adcEtcTriggerChainConfig.ADCHCRegisterSelect = 1U
                                                   << DEMO_ADC_CHANNEL_GROUP; /* Select ADC_HC0 register to trigger. */
    adcEtcTriggerChainConfig.ADCChannelSelect =
        DEMO_ADC_ETC_CHANNEL; /* ADC_HC0 will be triggered to sample Corresponding channel. */
    adcEtcTriggerChainConfig.InterruptEnable = kADC_ETC_Done1InterruptEnable; /* Enable the Done1 interrupt. */
    ADC_ETC_SetTriggerChainConfig(DEMO_ADC_ETC_BASE, 0U, 1U,
                                  &adcEtcTriggerChainConfig); /* Configure the trigger0 chain1. */

    /* Enable the NVIC. */
    EnableIRQ(ADC_ETC_IRQ0_IRQn);
    EnableIRQ(ADC_ETC_IRQ1_IRQn);

    while (1)
    {
        g_AdcConversionDoneFlag = false;
        g_AdcConversionDoneFlag2 = false;
        PRINTF("Press any key to get user channel's ADC value.\r\n");
        GETCHAR();
        ADC_ETC_DoSoftwareTrigger(DEMO_ADC_ETC_BASE, 0U); /* Do software XBAR trigger0. */
        while (!g_AdcConversionDoneFlag && !g_AdcConversionDoneFlag2)
        {
        }
        PRINTF("ADC conversion val1 is %d\r\n", g_AdcConversionValue);
        PRINTF("ADC conversion val2 is %d\r\n", g_AdcConversionValue2);
    }
}

/*!
* @brief Configure ADC to working with ADC_ETC.
*/

void ADC_Configuration(void)
{
    adc_config_t adcConfig;
    adc_channel_config_t adcChannelConfigStruct;

    /* Initialize the ADC module. */
    ADC_GetDefaultConfig(&adcConfig);
    ADC_Init(DEMO_ADC_BASE, &adcConfig);
    ADC_Init(DEMO_ADC2_BASE, &adcConfig);
    ADC_EnableHardwareTrigger(DEMO_ADC_BASE, true);
    ADC_EnableHardwareTrigger(DEMO_ADC2_BASE, true);

    adcChannelConfigStruct.channelNumber = DEMO_ADC_USER_CHANNEL; /* External channel selection from ADC_ETC. */
    adcChannelConfigStruct.enableInterruptOnConversionCompleted = false;
    ADC_SetChannelConfig(DEMO_ADC_BASE, DEMO_ADC_CHANNEL_GROUP, &adcChannelConfigStruct);


    /* Do auto hardware calibration. */
    if (kStatus_Success == ADC_DoAutoCalibration(DEMO_ADC_BASE))
    {
        PRINTF("ADC_DoAutoCalibration() Done.\r\n");
    }
    else
    {
        PRINTF("ADC_DoAutoCalibration() Failed.\r\n");
    }

    adcChannelConfigStruct.channelNumber = DEMO_ADC2_USER_CHANNEL; /* External channel selection from ADC_ETC. */
    adcChannelConfigStruct.enableInterruptOnConversionCompleted = false;
    ADC_SetChannelConfig(DEMO_ADC2_BASE, DEMO_ADC2_CHANNEL_GROUP, &adcChannelConfigStruct);

    /* Do auto hardware calibration. */
    if (kStatus_Success == ADC_DoAutoCalibration(DEMO_ADC2_BASE))
    {
        PRINTF("ADC2_DoAutoCalibration() Done.\r\n");
    }
    else
    {
        PRINTF("ADC2_DoAutoCalibration() Failed.\r\n");
    }
}

Outcomes