This discussion has been locked.
You can no longer post new replies to this discussion. If you have a question you can start a new discussion

ADC and EOP interrupt levels

I use the PEC to transfer data from the ADC and the EOP interrupt to reset the PEC pointers. As i understand you still need to have an end of conversion interrupt from the ADC to use the PEC EOP interrupt.
Does anyone know which of the two interrupts should have greater priority or should they be the same?

Parents
  • Sorry for the confusion and I need to clarify what I am saying, so I would add to Sauli comments.

    Concerning the interrupt level, I used the term too loosely, I meant to say the combined entry for the bits GPX, ILVL and GLVL must be unique (no two enabled interrupt nodes written with the same value).

    The point of the EOP from the Infineon manual...

    When the selected number of PEC transfers has been executed, the respective PEC channel is disabled and a standard interrupt service routine is activated instead. Each PEC channel can either activate the associated channel-specific interrupt node, or activate its associated PEC subnode request flag in register PECISNC, which then activates the common node request flag in register.

    I assumed you were running an auto scan single conversion. If you are running auto scan continuous conversions then you need to service the EOP before the next conversion otherwise as Sauli has pointed out given the PEC count is zero the ADC interrupt will occur not the EOP interrupt. This is clearly defined behavior.

    If you could provide a snippet of code that demonstrates this issue then I would be glad to look at it and comment.

    Here is an example that does an auto-scan single conversion of all the ADC channels and uses the PEC to move them to an array in memory. T3 launches the auto-scan every 10 milliseconds (20MHz cpu clock). Both interrupts are enabled the ADC end of conversion and the EOP. The ADC end of conversion interrupt is on PEC0 (GLVL = 14, ILVL = 0) and the EOP interrupt (GLVL = 13, ILVL = 0). The EOP resets the pointers and PEC0 control. Only the EOP is ever vectored to by the CPU.

    #include <XC167.h>  /* Special Function Registers XC167 */
    #include <intrins.h>
    
    unsigned int results[16];
    unsigned int adcCnt;
    unsigned int eopCnt;
    
    void GPT1_Tmr3_ISR(void) interrupt 0x23 {
      ADC_CON_ADST = 1;
    }
    
    void ADC_Conv_ISR(void) interrupt 0x28 {
      adcCnt++;
    }
    
    void INT_EOP_ISR(void) interrupt 0x4C {
    
      if(PECISNC_C0IR) { /* PEC channel 0 */
        PECISNC_C0IR = 0;
        eopCnt++;
        DSTP0 = _sof_(&results[0]);
        PECC0 = 0x4210;
      }
    }
    
    void main (void) {
      /* setup ADC, autoscan single conversion of all 16 channels */
      ADC_CON = 0x022F;
      ADC_CON1 = 0x8000;
      PECC0 = 0x4210;
      SRCP0 = _sof_(&ADC_DAT);
      DSTP0 = _sof_(&results[0]);
      PECSEG0 = 0;
      P5DIDIS = 0xFCFF;
      ADC_CIC = 0x0078; /* ADC Conv: (ILVL) = 14, (GLVL) = 0, (GPX) = 0 */
    
      /* setup End Of PEC */
      PECISNC = 0x0001;
      EOPIC = 0x0074;  /* EOP: (ILVL) = 13, (GLVL) = 0, (GPX) = 0   */
    
      /* use T3 to launch autoscan every 10 msec */
      GPT12E_T3CON = 0x0080;
      GPT12E_T3    = 0x61A8;
      GPT12E_T2CON = 0x0025;
      GPT12E_T2    = 0x61A8;
      GPT12E_T3IC = 0x006C; /* Timer 3: (ILVL) = 11, (GLVL) = 0, (GPX) = 0 */
      GPT12E_T3CON_T3R = 1;
    
      PSW_IEN = 1;  /* globally enable interrupts */
    
      for(;;);
    }
    

Reply
  • Sorry for the confusion and I need to clarify what I am saying, so I would add to Sauli comments.

    Concerning the interrupt level, I used the term too loosely, I meant to say the combined entry for the bits GPX, ILVL and GLVL must be unique (no two enabled interrupt nodes written with the same value).

    The point of the EOP from the Infineon manual...

    When the selected number of PEC transfers has been executed, the respective PEC channel is disabled and a standard interrupt service routine is activated instead. Each PEC channel can either activate the associated channel-specific interrupt node, or activate its associated PEC subnode request flag in register PECISNC, which then activates the common node request flag in register.

    I assumed you were running an auto scan single conversion. If you are running auto scan continuous conversions then you need to service the EOP before the next conversion otherwise as Sauli has pointed out given the PEC count is zero the ADC interrupt will occur not the EOP interrupt. This is clearly defined behavior.

    If you could provide a snippet of code that demonstrates this issue then I would be glad to look at it and comment.

    Here is an example that does an auto-scan single conversion of all the ADC channels and uses the PEC to move them to an array in memory. T3 launches the auto-scan every 10 milliseconds (20MHz cpu clock). Both interrupts are enabled the ADC end of conversion and the EOP. The ADC end of conversion interrupt is on PEC0 (GLVL = 14, ILVL = 0) and the EOP interrupt (GLVL = 13, ILVL = 0). The EOP resets the pointers and PEC0 control. Only the EOP is ever vectored to by the CPU.

    #include <XC167.h>  /* Special Function Registers XC167 */
    #include <intrins.h>
    
    unsigned int results[16];
    unsigned int adcCnt;
    unsigned int eopCnt;
    
    void GPT1_Tmr3_ISR(void) interrupt 0x23 {
      ADC_CON_ADST = 1;
    }
    
    void ADC_Conv_ISR(void) interrupt 0x28 {
      adcCnt++;
    }
    
    void INT_EOP_ISR(void) interrupt 0x4C {
    
      if(PECISNC_C0IR) { /* PEC channel 0 */
        PECISNC_C0IR = 0;
        eopCnt++;
        DSTP0 = _sof_(&results[0]);
        PECC0 = 0x4210;
      }
    }
    
    void main (void) {
      /* setup ADC, autoscan single conversion of all 16 channels */
      ADC_CON = 0x022F;
      ADC_CON1 = 0x8000;
      PECC0 = 0x4210;
      SRCP0 = _sof_(&ADC_DAT);
      DSTP0 = _sof_(&results[0]);
      PECSEG0 = 0;
      P5DIDIS = 0xFCFF;
      ADC_CIC = 0x0078; /* ADC Conv: (ILVL) = 14, (GLVL) = 0, (GPX) = 0 */
    
      /* setup End Of PEC */
      PECISNC = 0x0001;
      EOPIC = 0x0074;  /* EOP: (ILVL) = 13, (GLVL) = 0, (GPX) = 0   */
    
      /* use T3 to launch autoscan every 10 msec */
      GPT12E_T3CON = 0x0080;
      GPT12E_T3    = 0x61A8;
      GPT12E_T2CON = 0x0025;
      GPT12E_T2    = 0x61A8;
      GPT12E_T3IC = 0x006C; /* Timer 3: (ILVL) = 11, (GLVL) = 0, (GPX) = 0 */
      GPT12E_T3CON_T3R = 1;
    
      PSW_IEN = 1;  /* globally enable interrupts */
    
      for(;;);
    }
    

Children
  • HI, thanks for the clarification, my ADC code is pratically as yours is except my EOP is ILVL = 10 & GLVL = 0, my ADC Conv is ILVL = 10 & GLVL = 1. In your example you have the EOP at a lower ILVL than the ADC Conv, is this the best way round if its the EOP that actually does something. I only ask as one of my previous questions was which should have higher priority? Just to clarify also, i run in Auto Scan Continuous mode, which leads me to ask when i service the EOP to reset the PEC & DESTP1 should i stop conversion before doing so then restart after?

    Thanks for all your help.

  • I will start with the point of the EOP is to have a considerable lower priority than the interrupt level used by the PEC. Given your question I would recommend that the EOP should be lower (not in the same group) that the ADC conversion complete interrupt is. The second thing to remember is any interrupt in a group will NOT interrupt another if another within that group is already active. If two or more interrupts within a group become active at the same time then the highest wins. However, if a lower priority within the group is active and a higher interrupt now becomes ready it is held off until the lower one has finished.

    In your situation given you are using continuous auto scan and planning to have both interrupts in the same group it makes no sense to me to use the EOP. Instead I would just use the ADC conversion complete to reset the PEC registers. So I wouldn't stop the ADC, just don't use the EOP.

    Some comments to the interrupts with the PEC.
    1) When the PEC count is greater than 1 you only get the PEC transfer
    2) When the PEC count decrements to zero the PEC transfer will occur and then you can either have the EOP or ADC conversion complete (depending on your configuration).
    3) When the PEC count is zero you will only get the ADC conversion complete interrupt no matter what you configured for the EOP.

    Hope this helps.

    #include <XC167.h>            /* Special Function Registers XC167 */
    #include <intrins.h>
    
    unsigned int results[16];
    unsigned int adcCnt;
    
    void ADC_Conv_ISR(void) interrupt 0x28 {
      DSTP0 = _sof_(&results[0]);
      PECC0 = 0x0210;
      adcCnt++;
      P2 ^= 0x100;  /* toggle port pin */
    }
    
    void main (void) {
    
      /* setup ADC, autoscan signle conversion of all 16 channels */
      ADC_CON = 0x023F;
      ADC_CON1 = 0x8000;
      PECC0 = 0x0210;
      SRCP0 = _sof_(&ADC_DAT);
      DSTP0 = _sof_(&results[0]);
      PECSEG0 = 0;
      P5DIDIS = 0xFCFF;
      ADC_CIC = 0x0078; /* ADC Conv: (ILVL) = 14, (GLVL) = 0, (GPX) = 0 */
      DP2 |= 0x100;     /* use P2.8 to indicate an ADC service */
      PSW_IEN = 1;      /* globally enable interrupts */
    
      ADC_CON_ADST = 1;     /* begin the ADC conversions */
    
      for(;;);
    }