This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

TMS320F28069F: c28x Spurious ADC Interrupts with software triggered ADC

Part Number: TMS320F28069F
Other Parts Discussed in Thread: C2000WARE

Hello,

I am having an issue with software forced adc conversions. I have two adc interrupts. One is a fast interrupt that is EOC triggered on a simultaneous adc conversion on soc0 and soc1. The slower interrupt is EOC triggered on a simultaneous adc conversion on soc2 and soc3. the slower interrupt SOC is triggered from a down sample count in the fast interrupt. I have noticed that there are spurious interrupts in my code that appear to be the cause of the software forced interrupt call; the spurious fast interrupts dont occur with the software forced interrupt call commented out. Another factor in this problem is the fact that im using two interrupts in the PIE. My code works correctly when I change the slower interrupt to use PIEIER10. Please see the code below. I would post all my code but unfortunately it is large. An important thing to not is Im directly using whole register access and not the bit wise examples in the c2000ware code. Also a screenshot of what I am observing is below

with software forced interrupt commented out

working_high_speed_trace

with the software forced interrupt the interrupts keep triggering

spurious_interrupts

Here is the relevant excerpt of code. I believe the issue resides in `AdcRegs.ADCSOCFRC1 |= ADCSOC_SOC2;` inside of the fast isr. My debugger shows that the interrupt flags for PIEIFR1 and ADCINTFLG look correct aka only the ADCINT1 is pending. however right after the call to the software forced soc the ADCINTFLG goes to 0x0103, PIEIFR1 = 0x0022, and ADCINTOVF = 0x0003. I have checked the memory address of AdcRegs.ADCSOCFRC1 and it is correct.

Questions:

  • Is it not possible to call a software force soc from an isr context?
  • is a rmw operation and the ADCSOCFRC1 not correct?
  • Is it not possible to use more than one interrupt from a PIE group at a time?

static const PwmConfig resolver_pwm_config =
{
    .enable_center_aligned=true,
    .counts=937,//94,
    .adc_trigger={.enable=true, .event_scaler=ePwmSocPulseOnThirdEvent},
    .compliment={.enable=false, .edge_delay=0},
    .sync={.enable=false, .phase_counts=0, .sync_out=ePwmSyncOutSyncIn}
};

static const SampleConfig resolver_adc_config =
{
    .soc_index=0,
    .channel=eAdcInA0,
    .trigger_source=eAdcTriggerPwm1SocA,
    .sample_time=7,
    .enable_simultaneous_sample=true,
    .adc_interrupt={.enable=true, .interrupt_index=1}
};

static const SampleConfig current_adc_config =
{
    .soc_index=2,
    .channel=eAdcInA1,
    .trigger_source=eAdcTriggerSoftware,
    .sample_time=7,
    .enable_simultaneous_sample=true,
    .adc_interrupt={.enable=true, .interrupt_index=2}
};

__interrupt void adc_resolver_isr(void)
{
    static const unsigned down_count = 4;
    static unsigned isr_count = 0;

    hal_resolver_isr_pin_toggle();

    hal_resolver_sin = AdcResult.ADCRESULT0;
    hal_resolver_cos = AdcResult.ADCRESULT1;

    // start phase current adc sampling
    if (++isr_count >= down_count)
    {
        isr_count = 0;
        AdcRegs.ADCSOCFRC1 |= ADCSOC_SOC2;
    }

    AdcRegs.ADCINTFLGCLR |= ADCINT_BIT1;
    AdcRegs.ADCINTOVFCLR |= ADCINT_BIT1;
    PieCtrlRegs.PIEACK = PIEACK_GROUP1;
}

__interrupt void adc_current_isr(void)
{
    static unsigned down_count = 20;
    static unsigned isr_count = 0;

    hal_current_isr_pin_toggle();

    hal_current_a = AdcResult.ADCRESULT2;
    hal_current_b = AdcResult.ADCRESULT3;

    AdcRegs.ADCINTFLGCLR |= ADCINT_BIT2;
    AdcRegs.ADCINTOVFCLR |= ADCINT_BIT2;
    PieCtrlRegs.PIEACK = PIEACK_GROUP1;
}

void hal_boot_init(void)
{
    f28_setup_system_control(&system_config);
    DINT; // Disable CPU interrupts
    f28_setup_peripheral_interrupt_control();

    // Disable CPU interrupts and clear all CPU interrupt flags
    IER = 0x0000;
    IFR = 0x0000;

    f28_setup_peripheral_interrupt_table();

    // map isrs
    EALLOW;
    PieVectTable.ADCINT1 = &adc_resolver_isr;
    PieVectTable.ADCINT2 = &adc_current_isr;
    PieVectTable.ADCINT9 = &adc_1kHz_isr;
    PieVectTable.TINT2 = &cpu_timer2_isr;
    PieVectTable.SPIRXINTA = &sci_rxa_isr;
    EDIS;

    hal_gpio_init();

    f28_adc_init();
    f28_adc_soc_setup(&adc_1khz_config);
    f28_adc_soc_setup(&current_adc_config);
    f28_adc_soc_setup(&resolver_adc_config);

    f28_timer_init(&CpuTimer2Regs, &msec_timer_config);

    f28_sci_init(&SciaRegs, &sci_a_config, LSPCLK_SPEED);
    f28_can_init(&can_node, &can_bitrate, &can_mask_filter);
    f28_pwm_init(&EPwm1Regs, &resolver_pwm_config);

    // Enable ADCINT1,2,9
     PieCtrlRegs.PIEIER1 = (PIEIxR_INTx1 | PIEIxR_INTx2 | PIEIxR_INTx6);
    // Enable SCIRXA
     PieCtrlRegs.PIEIER9 = (PIEIxR_INTx1);

    // Enable Int1=Adc; Int9=sci; Int14=timer2 interrupt
    IER = (IxR_INT1 | IxR_INT9 | IxR_INT14);

    // Enable global Interrupts and higher priority real-time debug events
    EINT;   // Enable Global interrupt INTM
    ERTM;   // Enable Global realtime interrupt DBGM
}

Lastly here is a trace with using ADCINT3 and PIEIER10. This is what I expect to occur. Code changes are below; this code does not produce the odd ADCINTFLG = 0x0103 after the software soc start. However it produces the ADCINTFLG = 0x0005, PIEIF1 = 0x0002, PIEIF10 = 0x0007, and ADCINTOVF = 0x0000. The odd thing here is why is ADCINTFLG = 0x0005 and not 0x0001?

working with adcint3

static const SampleConfig current_adc_config =
{
    .soc_index=2,
    .channel=eAdcInA1,
    .trigger_source=eAdcTriggerSoftware,
    .sample_time=7,
    .enable_simultaneous_sample=true,
    .adc_interrupt={.enable=true, .interrupt_index=3}
};

__interrupt void adc_current_isr(void)
{
    static unsigned down_count = 20;
    static unsigned isr_count = 0;

    hal_current_isr_pin_toggle();

    hal_current_a = AdcResult.ADCRESULT2;
    hal_current_b = AdcResult.ADCRESULT3;

    AdcRegs.ADCINTFLGCLR |= ADCINT_BIT3;
    AdcRegs.ADCINTOVFCLR |= ADCINT_BIT3;
    PieCtrlRegs.PIEACK = PIEACK_GROUP10;
}

void hal_boot_init(void)
{
    f28_setup_system_control(&system_config);
    DINT; // Disable CPU interrupts
    f28_setup_peripheral_interrupt_control();

    // Disable CPU interrupts and clear all CPU interrupt flags
    IER = 0x0000;
    IFR = 0x0000;

    f28_setup_peripheral_interrupt_table();

    // map isrs
    EALLOW;
    PieVectTable.ADCINT1 = &adc_resolver_isr;
    PieVectTable.ADCINT3 = &adc_current_isr;
    PieVectTable.ADCINT9 = &adc_1kHz_isr;
    PieVectTable.TINT2 = &cpu_timer2_isr;
    PieVectTable.SPIRXINTA = &sci_rxa_isr;
    EDIS;

    hal_gpio_init();

    f28_adc_init();
    f28_adc_soc_setup(&adc_1khz_config);
    f28_adc_soc_setup(&current_adc_config);
    f28_adc_soc_setup(&resolver_adc_config);

    f28_timer_init(&CpuTimer2Regs, &msec_timer_config);

    f28_sci_init(&SciaRegs, &sci_a_config, LSPCLK_SPEED);
    f28_can_init(&can_node, &can_bitrate, &can_mask_filter);
    f28_pwm_init(&EPwm1Regs, &resolver_pwm_config);

    // Enable ADCINT1,2,9
    PieCtrlRegs.PIEIER1 = (PIEIxR_INTx1 | PIEIxR_INTx6);
    PieCtrlRegs.PIEIER10 = PIEIxR_INTx3;

    // Enable SCIRXA
    PieCtrlRegs.PIEIER9 = (PIEIxR_INTx1);

    // Enable Int1=Adc; Int9=sci; Int14=timer2 interrupt
    IER = (IxR_INT1 | IxR_INT9 | IxR_INT10 | IxR_INT14);

    // Enable global Interrupts and higher priority real-time debug events
    EINT;   // Enable Global interrupt INTM
    ERTM;   // Enable Global realtime interrupt DBGM
}

  • Nick,

    Sorry for the late reply, can you post the value of the INTSEL1N2 and INTSEL3N4 for both sets of example code after the ADC regs have been initialized? 

    If you just want to post the 16-bit registers at offsets of 0x8 and 0x9 from the ADC base address that will be good.  With simultaneous mode I believe that both EOCs will fire in the group, so theoretically you could have 2 INTs for the same group of 2 samples.

    Also, can you comment on the state of PIEIE10 in the first example?  Reason I'd like to see that is that ADCINT1 and ADCINT2 are duplicated in both PIE group 1 and PIE group10.  The group1 is to have the ADC ISRs in the highest priority group, the group 10 is so that all the ADCISRs are in a similar group for consistent priority if more than 2 are used.  I'm wondering if both INT1/INT2 are enabled across PIE groups what would happen(although you would have had to cast the ISR in both places for the code to execute)

    Best,

    Matthew

  • Thanks Matt for the response. No worries about the delay. I realize I was quite verbose.

    I placed a breakpoint at the end of hal_boot_init(). I inspected the core registers for the ADC

    The registers are below for using ADCINT1,2,9 all on PIEIER1 (the setup that cause re-occurring interrupts)

    INTSEL1N2    0x2321    ADC Interrupt 1 and 2 Selection [Memory Mapped]    
    INTSEL3N4    0x0000    ADC Interrupt 3 and 4 Selection [Memory Mapped]    
    INTSEL5N6    0x0000    ADC Interrupt 5 and 6 Selection [Memory Mapped]    
    INTSEL7N8    0x0000    ADC Interrupt 7 and 8 Selection [Memory Mapped]    
    INTSEL9N10    0x0024    ADC Interrupt 9 and 10 Selection [Memory Mapped]
    
    PIEIER1    0x0023    PIE, INT1 Group Enable Register [Memory Mapped]    
    PIEIFR1    0x0000    PIE, INT1 Group Flag Register [Memory Mapped]    
    PIEIER2    0x0000    PIE, INT2 Group Enable Register [Memory Mapped]    
    PIEIFR2    0x0000    PIE, INT2 Group Flag Register [Memory Mapped]    
    PIEIER3    0x0000    PIE, INT3 Group Enable Register [Memory Mapped]    
    PIEIFR3    0x0000    PIE, INT3 Group Flag Register [Memory Mapped]    
    PIEIER4    0x0000    PIE, INT4 Group Enable Register [Memory Mapped]    
    PIEIFR4    0x0000    PIE, INT4 Group Flag Register [Memory Mapped]    
    PIEIER5    0x0000    PIE, INT5 Group Enable Register [Memory Mapped]    
    PIEIFR5    0x0000    PIE, INT5 Group Flag Register [Memory Mapped]    
    PIEIER6    0x0000    PIE, INT6 Group Enable Register [Memory Mapped]    
    PIEIFR6    0x0000    PIE, INT6 Group Flag Register [Memory Mapped]    
    PIEIER7    0x0000    PIE, INT7 Group Enable Register [Memory Mapped]    
    PIEIFR7    0x0000    PIE, INT7 Group Flag Register [Memory Mapped]    
    PIEIER8    0x0000    PIE, INT8 Group Enable Register [Memory Mapped]    
    PIEIFR8    0x0000    PIE, INT8 Group Flag Register [Memory Mapped]    
    PIEIER9    0x0001    PIE, INT9 Group Enable Register [Memory Mapped]    
    PIEIFR9    0x0000    PIE, INT9 Group Flag Register [Memory Mapped]    
    PIEIER10    0x0000    PIE, INT10 Group Enable Register [Memory Mapped]    
    PIEIFR10    0x0003    PIE, INT10 Group Flag Register [Memory Mapped]    
    PIEIER11    0x0000    PIE, INT11 Group Enable Register [Memory Mapped]    
    PIEIFR11    0x0000    PIE, INT11 Group Flag Register [Memory Mapped]    
    PIEIER12    0x0000    PIE, INT12 Group Enable Register [Memory Mapped]    
    PIEIFR12    0x0000    PIE, INT12 Group Flag Register [Memory Mapped]    

    These are the registers for using ADCINT1 with PIEIER1 and ADC3,4 for PIEIER10

    INTSEL1N2    0x0E21    ADC Interrupt 1 and 2 Selection [Memory Mapped]    
    INTSEL3N4    0x2423    ADC Interrupt 3 and 4 Selection [Memory Mapped]    
    INTSEL5N6    0x0000    ADC Interrupt 5 and 6 Selection [Memory Mapped]    
    INTSEL7N8    0x0000    ADC Interrupt 7 and 8 Selection [Memory Mapped]    
    INTSEL9N10    0x0000    ADC Interrupt 9 and 10 Selection [Memory Mapped]    
    
    PIEIER1    0x0001    PIE, INT1 Group Enable Register [Memory Mapped]    
    PIEIFR1    0x0003    PIE, INT1 Group Flag Register [Memory Mapped]    
    PIEIER2    0x0000    PIE, INT2 Group Enable Register [Memory Mapped]    
    PIEIFR2    0x0000    PIE, INT2 Group Flag Register [Memory Mapped]    
    PIEIER3    0x0000    PIE, INT3 Group Enable Register [Memory Mapped]    
    PIEIFR3    0x0000    PIE, INT3 Group Flag Register [Memory Mapped]    
    PIEIER4    0x0000    PIE, INT4 Group Enable Register [Memory Mapped]    
    PIEIFR4    0x0000    PIE, INT4 Group Flag Register [Memory Mapped]    
    PIEIER5    0x0000    PIE, INT5 Group Enable Register [Memory Mapped]    
    PIEIFR5    0x0000    PIE, INT5 Group Flag Register [Memory Mapped]    
    PIEIER6    0x0000    PIE, INT6 Group Enable Register [Memory Mapped]    
    PIEIFR6    0x0000    PIE, INT6 Group Flag Register [Memory Mapped]    
    PIEIER7    0x0000    PIE, INT7 Group Enable Register [Memory Mapped]    
    PIEIFR7    0x0000    PIE, INT7 Group Flag Register [Memory Mapped]    
    PIEIER8    0x0000    PIE, INT8 Group Enable Register [Memory Mapped]    
    PIEIFR8    0x0000    PIE, INT8 Group Flag Register [Memory Mapped]    
    PIEIER9    0x0001    PIE, INT9 Group Enable Register [Memory Mapped]    
    PIEIFR9    0x0000    PIE, INT9 Group Flag Register [Memory Mapped]    
    PIEIER10    0x000C    PIE, INT10 Group Enable Register [Memory Mapped]    
    PIEIFR10    0x0003    PIE, INT10 Group Flag Register [Memory Mapped]    
    PIEIER11    0x0000    PIE, INT11 Group Enable Register [Memory Mapped]    
    PIEIFR11    0x0000    PIE, INT11 Group Flag Register [Memory Mapped]    
    PIEIER12    0x0000    PIE, INT12 Group Enable Register [Memory Mapped]    
    PIEIFR12    0x0000    PIE, INT12 Group Flag Register [Memory Mapped]    


    Let me know if I misread or missed an answer to your questions

  • Additionally I setup my PIE_VECT_TABLE to disallow using the ADCINT1 and ADCINT2 in PIEIER10 duplication that you were alluding to

        // Group 10 PIE Peripheral Vectors
        PINT rsvd10_1; // Can be ADCINT1, but must make ADCINT1 in Group 1 space "reserved".
        PINT rsvd10_2; // Can be ADCINT2, but must make ADCINT2 in Group 1 space "reserved".
        PINT ADCINT3;
        PINT ADCINT4;
        PINT ADCINT5;
        PINT ADCINT6;
        PINT ADCINT7;
        PINT ADCINT8;

  • Nick,

    Can you also check on the ADCINTSOCSELn register values? They should be all zeros unless you intend to self-trigger ADC conversions.

    -Tommy

  • For both the non working and working adc? Do you want those registers just after I finish init or after a breakpoint right after I start the software forced adc in the fastest isr?

  • Nick,

    I did not see these registers being configured in your code snippet. If true, they can be be captured any time after a mid-execution breakpoint for either working or not-working scenario. The goal is to confirm that there are no carry-over settings from code reuse.

    -Tommy

  • I think you found the issue Tommy. The adc offset mean function from c2000ware was making those registers enable the soc.

    ADCINTSOCSEL1    0xAAAA    ADC Interrupt SOC Selection 1 [Memory Mapped]    
    ADCINTSOCSEL2    0x5555    ADC Interrupt SOC Selection 2 [Memory Mapped]    

    The reson for this is I didnt read the warning when I copied this function from c2000ware F2806x_Adc.c

    // AdcConversion - This function initiates several ADC conversions and returns 
    // the average. It uses ADCINT1 and ADCINT2 to "ping-pong" between SOC0-7 
    // and SOC8-15 and is referred to as "ping-pong" sampling.
    // * IMPORTANT *
    // This function will overwrite previous ADC settings. Recommend saving 
    // previous settings.
    //
    Uint16
    AdcConversion(void)

    I added lines to clear out those registers and it looks functional. Thanks!

  • Nick,

    I'm happy to hear that you have it working now!

    -Tommy

  • Thanks again for the help this issue was quite frustrating. I was almost thinking something in the silicon was wrong, but of course it was the mistake of the programmer!