SAMV70 – How to Run ADC without Interrupts?

Go To Last Post
10 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I am trying to figure out how to run the ADC without interrupts on a SAMV70 using ASF4. My current code runs both ADC0 and ADC with all channels sampling at 20 msecs using interrupts. This is generating a lot of interrupts (1 for each channel or 2 x11 = 22).  These frequency of these interrupts are causing problems with some of the communications channels.

 

I would like to change the ADC code so it does not use interrupts at all.  I will have the main program check to see if all ADC channels are done and then transfer their data and start the next sampling period. (see code below)

 

I tried disabling the ADC interrupts by changing ADC_IMR so the interrupts are disabled. However, this appears to also disable the ADC channels so that  adc_async_start_conversion() does not start the conversion. 

 

So I tried using   NVIC_DisableIRQ(AFEC0_IRQn)) and  NVIC_DisableIRQ(AFEC1_IRQn) instead to disable the interrupts at the NVIC.  My ADC routine runs the first time, reads all the ADC channels without interrupts. But then the next and all following conversions trigger interrupts.

 

 How do I start the ADC conversions for all channels without getting interrupts?

 

Also I can’t find any register description (what the bits mean) for the NVIC in the SAMV70 datasheet.  Can someone point me to the NVIC register information?

 

bool AdcDriver::RunBackgroundAdc2()
{
    bool     bFlag = false;
    uint16_t ui16Time;

    ui16Time = m_AdcTimer.GetMsecs();                           
    if (AreAllChannelsDone2() == true)                          // Are all ADC channels done?
    {
        if (ui16Time >= m_ui16ChannelSampleRateMsecs)           // Is it time to Sample ADC?
        {
            m_AdcTimer.Reset();                                 // Reset Timer
            ReadAllChannels();                                  // Reads ADC data into FIFOs
            adc_async_start_conversion(m_pAdc);                 // Start next conversions    
        }
    }
    else
    {
        if (ui16Time >= (m_ui16ChannelSampleRateMsecs * 2))     // Has ADC timed out?
        {
            bFlag = true;                                       // Error, ADC Timeout
            m_AdcTimer.Reset();                                 // Reset Timer        
            adc_async_start_conversion(m_pAdc);                 // Start next conversions    
        }
    }
    return(bFlag);
}

 

This topic has a solution.
Last Edited: Tue. Jan 12, 2021 - 03:21 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

The cortex m3/4/7 cpus have a sophisticated priority interrupt scheme. Set your serial interrupt priority at a higher level than the adc. As for using the adc without interrupts, sorry, i’ve not read the user manual.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Kartman,

Thanks for your response.  I could change the interrupt priority but that will not solve the problem.  It is the amount of interrupts occurring during a short period that is the problem. Interrupt Service Routines are not interruptible by a higher priority interrupt. So if every 50 milliseconds there are 22 interrupts one after the other, this  creates a large block of time where other ISRs are blocked (actually delayed is more correct) because the ADC ISRs are running.  So even if a higher priority serial interrupt occurs during that time the ADC ISRs occur, it may not be serviced in time to prevent an USART overrun.

 

Since the ADC will internally buffer the data from all channels, there really is no need for me to handle the data in an interrupt.  I am not running the ADC continuously. I am sampling all the channels at a periodic rate. This can easily be handled without interrupts. This  firmware already uses a lot of interrupt driven IO and I would like to eliminate any unneeded interrupts to make the system more responsive.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 1

CpuDude wrote:
Interrupt Service Routines are not interruptible by a higher priority interrupt.

I'm not sure where you got that information.

 

Unless you've done something specific to stop it, the Cortex M3/4/7 will obey the interrupt priorities and will interrupt a low priority isr if there is a higher priority request. If in doubt, read up on the Cortex M3/4/7 interrupt system - as i said previously, it is quite sophisticated.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0


Kartman wrote:
read up on the Cortex M3/4/7 interrupt system 

For that - and other general Cortex stuff - I would recommend Joseph Yiu's Definitive Guide books; eg,

 

 

https://www.elsevier.com/books/the-definitive-guide-to-arm-cortex-m3-and-cortex-m4-processors/yiu/978-0-12-408082-9

Top Tips:

  1. How to properly post source code - see: https://www.avrfreaks.net/comment... - also how to properly include images/pictures
  2. "Garbage" characters on a serial terminal are (almost?) invariably due to wrong baud rate - see: https://learn.sparkfun.com/tutorials/serial-communication
  3. Wrong baud rate is usually due to not running at the speed you thought; check by blinking a LED to see if you get the speed you expected
  4. Difference between a crystal, and a crystal oscillatorhttps://www.avrfreaks.net/comment...
  5. When your question is resolved, mark the solution: https://www.avrfreaks.net/comment...
  6. Beginner's "Getting Started" tips: https://www.avrfreaks.net/comment...
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I'll add that if you're running the SAMV70 flat out at 300 MHz then it's quite capable of handling several hundred thousand interrupts per second. I doubt the ADC interrupts (around 1100/second) are the source of the problem.

 

Steve

Maverick Embedded Technologies Ltd. Home of Maven and wAVR.

Maven: WiFi ARM Cortex-M Debugger/Programmer

wAVR: WiFi AVR ISP/PDI/uPDI Programmer

https://www.maverick-embedded.co...

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 1

Thanks for the book suggestion. I will order a copy.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

@scdoubleu,  I have a lot of other interrupts in the system also. I have a timer generating 2K /per second. I have several other serial communications channels. I am also sending large data packets over a USB channel ever 20 msecs. And the are others also.

 

I can see that if I disable the ADCs, my communications problems go away.  With the ADCs running I am getting  a small, (0.4 %)  but noticeable error rate.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I may be mistaken about the ISR disable. I am using the ASF4 library and I thought I was seeing the ISRs disabled during the interrupt when looking with the debugger and tracing through the ISR handling. I may have been mistaken about that. 

This reply has been marked as the solution. 
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Ok, After reading the section in that book (Thanks @Kartman) about the Interrupt Controller, here is what I found.  By default, the processor sets all IRQs to the highest level with 1 priority group. Since they are all the same priority group, interrupts are not interruptible. However, when I configure the NVIC for 2 priority groups, I can make the ones in the lower Priority Group interruptible. By setting my ADCs and DAC to low priority interrupt, low priority group, leaving the communications IRQs in the high priority group, they seem to be running OK.

 

Thanks for all the helpful info.