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.

C2000WARE: FOC Interrupt routine

Part Number: C2000WARE

Hello there,

I'm trying to implement and FOC on an F2837x or an F2838x µC and using some examples of Ti for it.

I found this code snippet (from tidm_02009_F2838x_cpu1 from the digitalPower SDK)  which I cannot really understand:

void configInterrupt(void)
{
//
// Setup EPWM1 INT to generate MotorControlISR
//
#if(SAMPLING_METHOD == SINGLE_SAMPLING)
//
// Select INT @ ctr = 0
//
EPWM_setInterruptSource(PHASE_U_PWM_BASE, EPWM_INT_TBCTR_PERIOD);
#elif(SAMPLING_METHOD == DOUBLE_SAMPLING)
//
// Select INT @ ctr = 0 or ctr = prd
//
EPWM_setInterruptSource(PHASE_U_PWM_BASE, EPWM_INT_TBCTR_ZERO_OR_PERIOD);
#endif

//
// 1 for INTFRC to work
//
EPWM_setInterruptEventCount(PHASE_U_PWM_BASE, 1);
//
// Enable INT from EPWM1
//
EPWM_enableInterrupt(PHASE_U_PWM_BASE);

//
// Enable AdcA-ADCINT1- to help verify EoC before result data read
//
ADC_setInterruptSource(ADCA_BASE, ADC_INT_NUMBER1, ADC_SOC_NUMBER0);
ADC_enableContinuousMode(ADCA_BASE, ADC_INT_NUMBER1);
ADC_enableInterrupt(ADCA_BASE, ADC_INT_NUMBER1);

//
// Enable AdcC-ADCINT1- ADCEoCINT to generate ResolverISR
//
ADC_setInterruptSource(ADCC_BASE, ADC_INT_NUMBER1, ADC_SOC_NUMBER1);
ADC_enableContinuousMode(ADCC_BASE, ADC_INT_NUMBER1);
//
// Enable INT1 from ADCC
//
ADC_enableInterrupt(ADCC_BASE, ADC_INT_NUMBER1);

//
// PWM Clocks Enable
//
SysCtl_enablePeripheral(SYSCTL_PERIPH_CLK_TBCLKSYNC);
}

Then in the ISR function is the following 

__interrupt void ISR1(void)
{
TRINV_focControlCode();

TRINV_debugCode();

TRINV_HAL_clearInterruptFlag();

TRINV_HAL_clearInterrupt(INTERRUPT_ACK_GROUP3 | INTERRUPT_ACK_GROUP11);

isrTicker++;

}

In my understanding the ePWM module triggers the focControlCode on every begin of the PWM Period and also the Satrt of conversion of the ADCs. I thought that actually the ADC End of Conversion should trigger the focControlCode and the PWM triggers the ADC Start of conversion. As comment it says in the configInterrupt: 

// Enable AdcA-ADCINT1- to help verify EoC before result data read

How you can actually verify that at the focControlCode really takes the new ADC results altough no interrupt routine is used from the ADCs?

  • Hi,

    The C2000 ADC takes a predictable time from receiving SOC trigger to having the ADC result ready in their result registers. As a result, if you make sure you have enough cycle in your ISR before reading the ADC result register, you can trigger the interrupt earlier via ePWM to win some additional cycles for your ISR. You can of course use ADC EOC signal to trigger your interrupt to make it safer. There is also an early-interrupt feature in ADC which you can have the ADC EOC interrupt to be triggered n (programmable) cycles before the result is ready. Thanks.

    Han

  • Hello Thanks for our answer!

    But then I don't know why they put the comment 

    //
    // Enable AdcA-ADCINT1- to help verify EoC before result data read
    //
    ADC_setInterruptSource(ADCA_BASE, ADC_INT_NUMBER1, ADC_SOC_NUMBER0);
    ADC_enableContinuousMode(ADCA_BASE, ADC_INT_NUMBER1);
    ADC_enableInterrupt(ADCA_BASE, ADC_INT_NUMBER1);

    Because that interrupt is never called in the example above...

  • Maximilian,

    This was put in during development time and never took out during release process. We can verify that ADC EOC was triggered by the time I am trying to read the ADC result by pulling the ADC interrupt flag. We will work to remove it from next revision release. Thanks for reporting it.

    Han

  • Thanks for your answer again! Do you have a nice way to check, if the ADCs done with the conversion? Would you do an interrupt and for example set a flag? I would be a little bit scared to be stuck in a loop if i would do it this way

  • Maximilian,

    The ADC interrupt generation was enabled at ADC peripheral, but this interrupt was not setup / enabled at SoC level at the PIE module. You can add the code below to pull the flag before reading ADC result.

    //wait on ADC EOC
    while(ADC_getInterruptStatus(ADCA_BASE, ADC_INT_NUMBER1) == 0);
    NOP; //1 cycle delay for ADC PPB result

    You also need to add the below code before end of ISR to clear ADC interrupt flag.

    // clear ADCINT1 INT and ack PIE INT
    ADC_clearInterruptStatus(ADCA_BASE, ADC_INT_NUMBER1);

    If you do not need to get these additional cycles, it will be simpler to use ADC EOC interrupt and avoid these complications.

    Han