LPC546xx Internal ADC locking up

cancel
Showing results for 
Search instead for 
Did you mean: 

LPC546xx Internal ADC locking up

1,192 Views
georgechancello
Contributor I

My ADC is setup to read 2 channels (channel 1 is sequence A, and channel 2 is sequence B).  Here is the setup code:

void ADC_ADCConfiguration(void)
{
   adc_config_t adcConfigStruct;
   adc_conv_seq_config_t adcConvSeqConfigStruct;

   /* Configure the converter. */
   adcConfigStruct.clockMode = kADC_ClockSynchronousMode; // Using sync clock source.
   adcConfigStruct.clockDividerNumber = 3; // Set ADC Clock to 60MHz = 180MHz / (3 + 1)
   adcConfigStruct.resolution = kADC_Resolution12bit; // Set ADC to 12 bit resolution
   adcConfigStruct.enableBypassCalibration = false; // We want to do a calibration
   adcConfigStruct.sampleTimeNumber = 0U; // Set 0 clock cycle before sampling starts   
   ADC_Init(ADC0, &adcConfigStruct); // Init ADC

   CLOCK_AttachClk(kSYS_PLL_to_ADC_CLK);

   

// Calibration after power up.
   if (!ADC_DoSelfCalibration(ADC0))
   {
      DebugMessages_WriteString("ADC Cal Failure\r\n");
      return;
   }

   // Enable conversion in Sequence A.
   adcConvSeqConfigStruct.channelMask = (1U << 0); // Include ADC 0
   adcConvSeqConfigStruct.triggerMask = 1U;
   adcConvSeqConfigStruct.triggerPolarity = kADC_TriggerPolarityNegativeEdge;
   adcConvSeqConfigStruct.enableSingleStep = false;
   adcConvSeqConfigStruct.enableSyncBypass = false;
   adcConvSeqConfigStruct.interruptMode = kADC_InterruptForEachConversion; // Enable the interrupt/DMA trigger.
   ADC_SetConvSeqAConfig(ADC0, &adcConvSeqConfigStruct);
   ADC_EnableConvSeqA(ADC0, true); // Enable the conversion sequence A.


   // Enable conversion in Sequence B.
   adcConvSeqConfigStruct.channelMask = (1U << 5); // Include ADC 5
   adcConvSeqConfigStruct.triggerMask = 2U;
   ADC_SetConvSeqBConfig(ADC0, &adcConvSeqConfigStruct);
   ADC_EnableConvSeqB(ADC0, true); // Enable the conversion sequence B.

   // Setup Seq B to override seq A
   ADC_SetConvSeqBHighPriority(ADC0);

}

If have high interrupts on the external hardware pins the ADC will lock up.  If I only enable sequence A or B it works perfectly at high interrupts.

When the lockup occurs it will not recover without a complete reboot.

Does anybody have any ideas on what could be causing the lockup?

Labels (1)
0 Kudos
13 Replies

593 Views
use
Contributor II

Hi, I am working on this with George. When this ADC issue occurs, PIN_INT0_DriverIRQHandler(void) and PIN_INT1_DriverIRQHandler(void) are still being called. The issue is that the conversions never starts and so ADC0_SEQB_IRQHandler(void) and ADC0_SEQA_IRQHandler(void) never get called. I modified the pin interrupt handler to call the adc handlers where we read the data but of course the data never changes because the conversions do not start. Do you know how the link between the pin interrupt and the start of the conversion could be broken without any changes to the ADC or PINT registers?

ADC Diagram_an.png

Thanks,

Micah

0 Kudos

593 Views
victorjimenez
NXP TechSupport
NXP TechSupport

Hello George and Micah, 

  

I will work on a demo using two ADC channels and two pin interrupts to see if I can reproduce the behavior you are facing. I will let you know my results.  

 

Regards,

Victor.

0 Kudos

593 Views
victorjimenez
NXP TechSupport
NXP TechSupport

Hello George and Micah, 

  

I just sent the project I made to George. Unfortunately, I wasn't able to reproduce the behavior you mentioned. In the project I use two different channels of the ADC0, channel 0 and 4. The sequence of the channel 0 is attached to PINT0 which corresponds to SW2 of the development board and the sequence of the channel 4 is PINT1 which is the SW3. You can use this project as a guide to see which configurations you are missing in your project. 

I made the project based on the OM13098 development board.  Let me know if you didn't receive the project. 

 

Regards,

Victor.

0 Kudos

593 Views
use
Contributor II

Hi Victor,

George is out of the office this week and the next. Could you please send me the project? I have been able to work around this issue by setting up pin interrupts and then manually calling a software ADC conversion in the handlers. There are no longer any lockups but I would still like to compare our ADC hardware trigger configuration to yours.

Thanks

593 Views
victorjimenez
NXP TechSupport
NXP TechSupport

Hello Micah,

I just sent to your email the project. 

Regards,

Victor.

0 Kudos

593 Views
victorjimenez
NXP TechSupport
NXP TechSupport

Hello George Chancellor,

Could you please send me your project so I can  reproduce this behavior on my side? 

Regards, 

Victor.

0 Kudos

593 Views
georgechancello
Contributor I

Victor,

I can send you my project, I have it compressed down to the bare minimum code.  I do not see a way to post a zip file to post, is there a way I can send you the file via email?

0 Kudos

593 Views
victorjimenez
NXP TechSupport
NXP TechSupport

Hello George, 

I sent you an email, please attach your project in the reply of that email.

Regards,

Victor.  

0 Kudos

593 Views
georgechancello
Contributor I

Victor, I have been trying to respond to the email you sent, but I keep getting an automatic reply from NXP that it will not accept my email.

Is there any way we can bypass the community and email direct?

pastedImage_1.png

0 Kudos

593 Views
victorjimenez
NXP TechSupport
NXP TechSupport

Hello George Chancellor,

The configuration and initialization look good. Just one detail, if you want to set the ADC clock to 60MHz, then you should have a 2 in the following assignment adcConfigStruct.clockDividerNumber = 3; with this at the moment you are currently setting the ADC clock to 45MHz.

According to your configuration you are currently using Group GPIO interrupt to initialize the conversion of the ADC for both sequences:

adcConvSeqConfigStruct.triggerMask = 1U; 

adcConvSeqConfigStruct.triggerMask = 2U;

pastedImage_2.png

Could you please share with me how are you setting/configuring this group interrupts? 

Regards,

Victor. 

0 Kudos

593 Views
georgechancello
Contributor I

Victor,

Thanks for the comment, I will look into the 45MHz you mentioned.

As for the interrupt initialization here is my code:

CLOCK_EnableClock(kCLOCK_InputMux);
INPUTMUX_AttachSignal(INPUTMUX, kPINT_PinInt0, kINPUTMUX_GpioPort1Pin3ToPintsel);
INPUTMUX_AttachSignal(INPUTMUX, kPINT_PinInt1, kINPUTMUX_GpioPort1Pin2ToPintsel);
PINT_Init(PINT);
PINT_PinInterruptConfig(PINT, kPINT_PinInt0, kPINT_PinIntEnableFallEdge, NULL);
PINT_PinInterruptConfig(PINT, kPINT_PinInt1, kPINT_PinIntEnableFallEdge, NULL);
PINT_EnableCallback(PINT);

0 Kudos

593 Views
victorjimenez
NXP TechSupport
NXP TechSupport

Hello George Chancellor,

With the following statements: 

adcConvSeqConfigStruct.triggerMask = 1U; 

adcConvSeqConfigStruct.triggerMask = 2U;

You are setting the Group GPIO interrupt to trigger the conversion of the ADC for both sequences (see image attached in my first reply). However, in the code you attached  you are setting Pin Interrupt instead of Group GPIO interrupt, these are two completely different things. You can refer chapter 14 of the User Manual to learn more about the Group GPIO interrupt. Also, in the SDK you can find an example on how to configure and run these interrupts. 

pastedImage_6.png

Also, you have to be sure that you are clearing the interrupt once you are in the handler of the corresponding Group GPIO interrupt. 

pastedImage_7.png

Link to the user manual

Hope it helps!

Victor.

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

Note: If this post answers your question, please click the Correct Answer button. Thank you!

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

0 Kudos

593 Views
georgechancello
Contributor I

Victor,

Thanks for the suggestion, but unfortunately it did not work.

I first tried to switch one of the interrupts to a different port, they were at PIO1_2 & PIO1_3 and I changed it to PIO1_2 & PIO0_7.  This had no effect, the ADC would still lock up eventually.

I then tried your suggestion of group interrupt via the following code:

GINT_Init(GINT0);
GINT_Init(GINT1);
GINT_SetCtrl(GINT0, kGINT_CombineAnd, kGINT_TrigEdge, NULL);

GINT_SetCtrl(GINT1, kGINT_CombineAnd, kGINT_TrigEdge, NULL);
GINT_ConfigPins(GINT0, kGINT_Port0, 1 << 7, 1 << 7);

GINT_ConfigPins(GINT1, kGINT_Port1, 1 << 2, 1 << 2);
GINT_EnableCallback(GINT0);
GINT_EnableCallback(GINT1);

I also removed the above interrupt initializtion code.

With the group interrupt, I did verify that it was going into the GINT0_DriverIRQHandler & GINT1_DriverIRQHandler, but the ADC was never getting an interrupt.

Looking at the manual the only reference in the ADC chapter of group interrupt is in the table you mentioned, but else were it mentions pin interrupts.

pastedImage_2.png

Then in the example section (43.8.2) it says to use PINT1 as the external trigger and references you to chapter 11 (Pin interrupt and pattern match (PINT)

pastedImage_3.png

The final thing I tried was having both the PINT and group interrupts enabled, and this still did not work.

So I am still not able to get the ADC to stop locking up.

Also when it does lock up the best method that I have found to recover from it is by stting the ADC_INIT bit in the STARTUP register:

ADC0->STARTUP |= ADC_STARTUP_ADC_INIT_MASK;

If I do this to many times though it will eventually stay locked up.

0 Kudos