i.MX8 M4 Multiple Analogue Inputs in one Interrupt

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

i.MX8 M4 Multiple Analogue Inputs in one Interrupt

Jump to solution
694 Views
Cillex
Contributor I

Hello everyone,

I am currently trying to read two different analogue inputs at the same time using the M4 of a Toradex imx8dx system.

Right now i have one ADC channel in use reading on an interrupt.

The ideal solution would be to use the same interrupt to read a second channel (as far as I understand it the ADC chip reads all inputs at the same time, therefore they should already be ready at the same time).

Can someone help me to set the settings correctly?

 

Here are the useful bits of my code:

 

/*
* ADC IN 1 PIN: SODIMM 4 -> ADMA_ADC0_IN4
* ADC IN 2 PIN: SODIMM 2 -> ADMA_ADC0_IN5
*/
#define SENSOR_LPADC_BASE ADMA__ADC0
#define SENSOR_1_LPADC_USER_CHANNEL 4U
#define SENSOR_1_LPADC_USER_CMDID 1U 

#define SENSOR_2_LPADC_USER_CHANNEL 5U
#define SENSOR_2_LPADC_USER_CMDID 2U 

#define SENSOR_LPADC_IRQn ADMA_ADC0_INT_IRQn
#define SENSOR_LPADC_IRQ_HANDLER_FUNC ADMA_ADC0_INT_IRQHandler

 

/*
* ADC VARs
*/
volatile bool g_LpadcConversionCompletedFlag = false;
volatile uint32_t g_LpadcInterruptCounter = 0U;
lpadc_conv_result_t g_LpadcResultConfigStruct;
#if (defined(DEMO_LPADC_USE_HIGH_RESOLUTION) && DEMO_LPADC_USE_HIGH_RESOLUTION)
  const uint32_t g_LpadcFullRange = 65536U;
  const uint32_t g_LpadcResultShift = 0U;
#else
  const uint32_t g_LpadcFullRange = 4096U;
  const uint32_t g_LpadcResultShift = 3U;
#endif /* DEMO_LPADC_USE_HIGH_RESOLUTION */

 

/*
* IRQ_HANDLER OF ADC
*
*/
void SENSOR_LPADC_IRQ_HANDLER_FUNC(void)
{
  g_LpadcInterruptCounter++;

  if (LPADC_GetConvResult(SENSOR_LPADC_BASE, &g_LpadcResultConfigStruct))
  {
    //read value and write to picture
    picture_1[irq_count-1] = ((g_LpadcResultConfigStruct.convValue) >> g_LpadcResultShift);

    //read second value

    picture_2[irq_count-1] = 0; //get second value from ADC channel 5U

  }

  SDK_ISR_EXIT_BARRIER;
}

 

 

*!
 * @brief Main function
 */
int main(void)
{
    uint32_t time = timestamp_simple;
 
    sc_ipc_t ipc;
    ipc = BOARD_InitRpc();
    BOARD_InitPins(ipc);
    BOARD_BootClockRUN();
    BOARD_InitMemory();
    BOARD_InitDebugConsole();
 
/*
* ADC INIT
*     LEVEL_SENSOR_1
*     LEVEL_SENSOR_2
*/
    lpadc_config_t mLpadcConfigStruct;
    lpadc_conv_trigger_config_t mLpadcTriggerConfigStruct;
    lpadc_conv_command_config_t mLpadcCommandConfigStruct;
 
    if (sc_pm_set_resource_power_mode(ipc, SC_R_ADC_0, SC_PM_PW_MODE_ON) != SC_ERR_NONE)
    {
        PRINTF("Error: Failed to power on ADC\r\n");
    }
    
    IRQSTEER_EnableInterrupt(IRQSTEER, ADMA_ADC0_INT_IRQn);
 
    LPADC_GetDefaultConfig(&mLpadcConfigStruct);
    mLpadcConfigStruct.enableAnalogPreliminary = true;
 
    LPADC_Init(SENSOR_LPADC_BASE, &mLpadcConfigStruct);
    
 
 
// CHECK FOR SECOND CHANNEL
    LPADC_GetDefaultConvCommandConfig(&mLpadcCommandConfigStruct);
    mLpadcCommandConfigStruct.channelNumber = SENSOR_1_LPADC_USER_CHANNEL;
    //mLpadcCommandConfigStruct.chainedNextCommandNumber = SENSOR_2_LPADC_USER_CMDID; //ADDED FOR 2.
    LPADC_SetConvCommandConfig(SENSOR_LPADC_BASE, SENSOR_1_LPADC_USER_CMDID, &mLpadcCommandConfigStruct);
 
    LPADC_GetDefaultConvCommandConfig(&mLpadcCommandConfigStruct);
 
    LPADC_GetDefaultConvTriggerConfig(&mLpadcTriggerConfigStruct);
// CHECK FOR SECOND CHANNEL
    //1. CHAN
    mLpadcTriggerConfigStruct.targetCommandId       = SENSOR_1_LPADC_USER_CMDID;
    //2. CHAN
    //mLpadcTriggerConfigStruct.
    mLpadcTriggerConfigStruct.enableHardwareTrigger = false;
    LPADC_SetConvTriggerConfig(SENSOR_LPADC_BASE, 0U, &mLpadcTriggerConfigStruct); 
 
    LPADC_EnableInterrupts(SENSOR_LPADC_BASE, kLPADC_FIFOWatermarkInterruptEnable);
    EnableIRQ(SENSOR_LPADC_IRQn);
 
/*
* MAIN LOOP
*     leave empty when finished
*     only used for debugging
*/
    while (true)
    {
      SDK_DelayAtLeastUs(1000000, SDK_DEVICE_MAXIMUM_CPU_CLOCK_FREQUENCY);
      LPADC_DoSoftwareTrigger(SENSOR_LPADC_BASE, 1U); //get ADC values
    }
 
}

 

 

 

 

 

 

0 Kudos
Reply
1 Solution
670 Views
Sanket_Parekh
NXP TechSupport
NXP TechSupport

Hi @Cillex ,

I hope you are doing well.

One can use separate command for multiple ADC channels.

Please refer to example given at boards/mekmimx8qm/driver_examples/lpadc/interrupt/cm4_core0 in SDK

e.g.

LPADC_GetDefaultConvCommandConfig(&mLpadcCommandConfigStruct1);
mLpadcCommandConfigStruct1.channelNumber = DEMO_LPADC_USER_CHANNEL1;
mLpadcCommandConfigStruct1.conversionResolutionMode = kLPADC_ConversionResolutionHigh;
LPADC_SetConvCommandConfig(DEMO_LPADC_BASE, DEMO_LPADC_USER_CMDID1, &mLpadcCommandConfigStruct1);

LPADC_GetDefaultConvCommandConfig(&mLpadcCommandConfigStruct2);
mLpadcCommandConfigStruct2.channelNumber = DEMO_LPADC_USER_CHANNEL2;
mLpadcCommandConfigStruct2.conversionResolutionMode = kLPADC_ConversionResolutionHigh;
LPADC_SetConvCommandConfig(DEMO_LPADC_BASE, DEMO_LPADC_USER_CMDID2, &mLpadcCommandConfigStruct2);

/* Set trigger configuration. */

LPADC_GetDefaultConvTriggerConfig(&mLpadcTriggerConfigStruct1);
mLpadcTriggerConfigStruct1.targetCommandId = DEMO_LPADC_USER_CMDID1;
mLpadcTriggerConfigStruct1.enableHardwareTrigger = false;
LPADC_SetConvTriggerConfig(DEMO_LPADC_BASE, 0U, &mLpadcTriggerConfigStruct1); /* Configurate the trigger0. */


LPADC_GetDefaultConvTriggerConfig(&mLpadcTriggerConfigStruct2);
mLpadcTriggerConfigStruct2.targetCommandId = DEMO_LPADC_USER_CMDID2;
mLpadcTriggerConfigStruct2.enableHardwareTrigger = false;
LPADC_SetConvTriggerConfig(DEMO_LPADC_BASE, 1U, &mLpadcTriggerConfigStruct2);

-----------------------------------------------------------------------------------------------------------------------------

Then one can use LPADC_DoSoftwareTrigger to trigger software.

LPADC_DoSoftwareTrigger(DEMO_LPADC_BASE, 1U<<0); // trigger 0

LPADC_DoSoftwareTrigger(DEMO_LPADC_BASE, 1U<<1)); // trigger 1.

One can determine which channel reading are available using g_LpadcResultConfigStruct in ISR.

g_LpadcResultConfigStruct.commandIdSource // One can determine the channel using command ID.

Please refer to 17.2 Analog-to-Digital Converter (ADC) in RM for more information.

I hope it helps!

Thanks & Regards,
Sanket Parekh

View solution in original post

0 Kudos
Reply
2 Replies
653 Views
Cillex
Contributor I

Dear Sanket Parekh,

Thank you very much for the quick response.

It worked perfectly and exactly as intended.

 

Best Regards,

Cillex

 

0 Kudos
Reply
671 Views
Sanket_Parekh
NXP TechSupport
NXP TechSupport

Hi @Cillex ,

I hope you are doing well.

One can use separate command for multiple ADC channels.

Please refer to example given at boards/mekmimx8qm/driver_examples/lpadc/interrupt/cm4_core0 in SDK

e.g.

LPADC_GetDefaultConvCommandConfig(&mLpadcCommandConfigStruct1);
mLpadcCommandConfigStruct1.channelNumber = DEMO_LPADC_USER_CHANNEL1;
mLpadcCommandConfigStruct1.conversionResolutionMode = kLPADC_ConversionResolutionHigh;
LPADC_SetConvCommandConfig(DEMO_LPADC_BASE, DEMO_LPADC_USER_CMDID1, &mLpadcCommandConfigStruct1);

LPADC_GetDefaultConvCommandConfig(&mLpadcCommandConfigStruct2);
mLpadcCommandConfigStruct2.channelNumber = DEMO_LPADC_USER_CHANNEL2;
mLpadcCommandConfigStruct2.conversionResolutionMode = kLPADC_ConversionResolutionHigh;
LPADC_SetConvCommandConfig(DEMO_LPADC_BASE, DEMO_LPADC_USER_CMDID2, &mLpadcCommandConfigStruct2);

/* Set trigger configuration. */

LPADC_GetDefaultConvTriggerConfig(&mLpadcTriggerConfigStruct1);
mLpadcTriggerConfigStruct1.targetCommandId = DEMO_LPADC_USER_CMDID1;
mLpadcTriggerConfigStruct1.enableHardwareTrigger = false;
LPADC_SetConvTriggerConfig(DEMO_LPADC_BASE, 0U, &mLpadcTriggerConfigStruct1); /* Configurate the trigger0. */


LPADC_GetDefaultConvTriggerConfig(&mLpadcTriggerConfigStruct2);
mLpadcTriggerConfigStruct2.targetCommandId = DEMO_LPADC_USER_CMDID2;
mLpadcTriggerConfigStruct2.enableHardwareTrigger = false;
LPADC_SetConvTriggerConfig(DEMO_LPADC_BASE, 1U, &mLpadcTriggerConfigStruct2);

-----------------------------------------------------------------------------------------------------------------------------

Then one can use LPADC_DoSoftwareTrigger to trigger software.

LPADC_DoSoftwareTrigger(DEMO_LPADC_BASE, 1U<<0); // trigger 0

LPADC_DoSoftwareTrigger(DEMO_LPADC_BASE, 1U<<1)); // trigger 1.

One can determine which channel reading are available using g_LpadcResultConfigStruct in ISR.

g_LpadcResultConfigStruct.commandIdSource // One can determine the channel using command ID.

Please refer to 17.2 Analog-to-Digital Converter (ADC) in RM for more information.

I hope it helps!

Thanks & Regards,
Sanket Parekh

0 Kudos
Reply