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.

TMS320F28027: ADC EPWM1 SOC interrupt not triggered

Part Number: TMS320F28027

Hello, 

We are trying to implement a algorithm where ADC is sampled periodically based on a EPWM1 trigger whenever XINT1 is triggered.
We want to achieve a PWM of 2MHz with 50% duty cycle for fast ADC sampling.

xint_isr is triggered but adc_isr which is mapped to trigger on a EPWM1 (count up/down) is not getting triggered.
Please advise based on the code below. Thanks!!

void system_init(void)
{
    volatile int status = FALSE;
    volatile FILE *fid;

    // Initialize all the handles needed for this application
    myAdc   = ADC_init((void *)ADC_BASE_ADDR, sizeof(ADC_Obj));
    myClk   = CLK_init((void *)CLK_BASE_ADDR, sizeof(CLK_Obj));
    myCpu   = CPU_init((void *)NULL, sizeof(CPU_Obj));
    myFlash = FLASH_init((void *)FLASH_BASE_ADDR, sizeof(FLASH_Obj));
    myGpio  = GPIO_init((void *)GPIO_BASE_ADDR, sizeof(GPIO_Obj));
    myPie   = PIE_init((void *)PIE_BASE_ADDR, sizeof(PIE_Obj));
    myPll   = PLL_init((void *)PLL_BASE_ADDR, sizeof(PLL_Obj));
    mySci   = SCI_init((void *)SCIA_BASE_ADDR, sizeof(SCI_Obj));
    myWDog  = WDOG_init((void *)WDOG_BASE_ADDR, sizeof(WDOG_Obj));
    mySpi   = SPI_init((void *)SPIA_BASE_ADDR, sizeof(SPI_Obj));
    myComp  = COMP_init((void *)COMP2_BASE_ADDR, sizeof(COMP_Obj));
    myCap   = CAP_init((void *)CAPA_BASE_ADDR, sizeof(CAP_Obj));
    myPwm = PWM_init((void *)PWM_ePWM1_BASE_ADDR, sizeof(PWM_Obj));

    // Perform basic system initialization
    WDOG_disable(myWDog);

    // Enable clock to ADC
    CLK_enableAdcClock(myClk);
    (*Device_cal)();

    CLK_enableHrPwmClock(myClk);
    // Enable PWM clock
    CLK_enablePwmClock(myClk, PWM_Number_1);

    //Select the internal oscillator 1 as the clock source
    CLK_setOscSrc(myClk, CLK_OscSrc_Internal);

    // Setup the PLL for x10 /2 which will yield 50Mhz = 10Mhz * 10 / 2
    PLL_setup(myPll, PLL_Multiplier_12, PLL_DivideSelect_ClkIn_by_2);

    DSP28x_usDelay(2000);

    //--- Enable clock to peripherals
    // Disable the PIE and all interrupts
    PIE_disable(myPie);
    PIE_disableAllInts(myPie);
    CPU_disableGlobalInts(myCpu);
    CPU_clearIntFlags(myCpu);

    // If running from flash copy RAM only functions to RAM
    #ifdef _FLASH
        memcpy(&RamfuncsRunStart, &RamfuncsLoadStart, (size_t)&RamfuncsLoadSize);
    #endif

    // Initalize GPIO
    // Enable XCLOCKOUT to allow monitoring of oscillator 1
    GPIO_setMode(myGpio, GPIO_Number_18, GPIO_18_Mode_XCLKOUT);
    CLK_setClkOutPreScaler(myClk, CLK_ClkOutPreScaler_SysClkOut_by_1);

    // Setup a debug vector table and enable the PIE
    PIE_setDebugIntVectorTable(myPie);
    PIE_enable(myPie);

    // GPI05 Interrupt (DSP_INTn)
    PIE_registerPieIntHandler(myPie, PIE_GroupNumber_1, PIE_SubGroupNumber_4, (intVec_t)&xint_isr);
    // TODO ADC ePWM
    PIE_registerPieIntHandler(myPie, PIE_GroupNumber_10, PIE_SubGroupNumber_1, (intVec_t)&adc_isr);

    // Initalize GPIO
    gpio_init();

    #ifdef LAUNCHPAD
        // Initialize SCIA
        scia_init();
    #endif

    EALLOW;
        GpioIntRegs.GPIOXINT1SEL.bit.GPIOSEL  = 12; // Configure GPIO as XINT1
    EDIS;

    // Initialize the ADC
    adc_init();

    // Initialize the PWM
    pwm_init();

    // Initialize SPI
    spi_init();

    // Initialize SPI FIFO
    spi_fifo_init();

    // Enable global interrupts and higher priority real-time debug events
    CPU_enableGlobalInts(myCpu);
    CPU_enableDebugInt(myCpu);

    // Configure GPIO12 as XINT1 in Delta DSP
        GPIO_setMode(myGpio, GPIO_Number_12, GPIO_12_Mode_GeneralPurpose);
        GPIO_setDirection(myGpio, GPIO_Number_12, GPIO_Direction_Input);
        GPIO_setPullUp(myGpio, GPIO_Number_12, GPIO_PullUp_Enable);
        GPIO_setExtInt(myGpio, GPIO_Number_12, CPU_ExtIntNumber_1);

    // Set the interrupt polarity
    PIE_setExtIntPolarity(myPie, CPU_ExtIntNumber_1, PIE_ExtIntPolarity_RisingAndFallingEdge);
    // Enable XINT1
    PIE_enableExtInt(myPie, CPU_ExtIntNumber_1);

    // Enable PIE - XINT1
    PIE_enableInt(myPie, PIE_GroupNumber_1, PIE_InterruptSource_XINT_1);
    // Enable SPI TX Interrupt
    PIE_enableInt(myPie, PIE_GroupNumber_6, PIE_InterruptSource_SPIATX);
    // Enable CPU - INT1
    CPU_enableInt(myCpu, CPU_IntNumber_1);
    // TODO ADC ePWM
    CPU_enableInt(myCpu, CPU_IntNumber_10);

    // Set the flash OTP wait-states to minimum. This is important
    // for the performance of the temperature conversion function.
    FLASH_setup(myFlash);

    //Redirect STDOUT to SCI
    status = add_device("scia", _SSA, SCI_open, SCI_close, SCI_read, SCI_write, SCI_lseek, SCI_unlink, SCI_rename);
    fid = fopen("scia","w");
    freopen("scia:", "w", stdout);
    setvbuf(stdout, NULL, _IONBF, 0);
}


void adc_init()
{
    ADC_enableBandGap(myAdc);
    ADC_enableRefBuffers(myAdc);
    ADC_powerUp(myAdc);
    ADC_enable(myAdc);
    ADC_setVoltRefSrc(myAdc, ADC_VoltageRefSrc_Int);

    // Enable ADCINT1 in PIE
    PIE_enableAdcInt(myPie, ADC_IntNumber_1);
    // Enable CPU Interrupt 1
    CPU_enableInt(myCpu, CPU_IntNumber_10);

    // Configure ADC
    ADC_setIntPulseGenMode(myAdc, ADC_IntPulseGenMode_Prior);               //ADCINT1 trips after AdcResults latch
    ADC_enableInt(myAdc, ADC_IntNumber_1);                                  //Enabled ADCINT1
    ADC_setIntMode(myAdc, ADC_IntNumber_1, ADC_IntMode_EOC);                //Disable ADCINT1 Continuous mode
    ADC_setIntSrc(myAdc, ADC_IntNumber_1, ADC_IntSrc_EOC1);                 //setup EOC1 to trigger ADCINT1 to fire
    ADC_setSocChanNumber (myAdc, ADC_SocNumber_0, ADC_SocChanNumber_A4);    //set SOC0 channel select to ADCINA4
    ADC_setSocChanNumber (myAdc, ADC_SocNumber_1, ADC_SocChanNumber_A4);    //set SOC1 channel select to ADCINA4
    ADC_setSocTrigSrc(myAdc, ADC_SocNumber_0, ADC_SocTrigSrc_EPWM1_ADCSOCA);    //set SOC0 start trigger on EPWM1A, due to round-robin SOC0 converts first then SOC1
    ADC_setSocTrigSrc(myAdc, ADC_SocNumber_1, ADC_SocTrigSrc_EPWM1_ADCSOCB);    //set SOC1 start trigger on EPWM1A, due to round-robin SOC0 converts first then SOC1
    ADC_setSocSampleWindow(myAdc, ADC_SocNumber_0, ADC_SocSampleWindow_7_cycles);   //set SOC0 S/H Window to 7 ADC Clock Cycles, (6 ACQPS plus 1)
    ADC_setSocSampleWindow(myAdc, ADC_SocNumber_1, ADC_SocSampleWindow_7_cycles);   //set SOC1 S/H Window to 7 ADC Clock Cycles, (6 ACQPS plus 1)
}

void pwm_init()
{
    // Setup PWM
    PWM_enableSocAPulse(myPwm);                                         // Enable SOC on A group
    PWM_setSocAPulseSrc(myPwm, PWM_SocPulseSrc_CounterEqualCmpAIncr);   // Select SOC from from CPMA on upcount
    PWM_setSocAPeriod(myPwm, PWM_SocPeriod_FirstEvent);                 // Generate pulse on 1st event
    PWM_setCmpA(myPwm, 30);                                             // Set compare A value (30 TBCLK counts => 50% duty)
    PWM_setPeriod(myPwm, 60);                                           // Set period for ePWM1 (60 TBCLK counts => 2MHz)
    PWM_setCounterMode(myPwm, PWM_CounterMode_UpDown);                  // count up and start
}

interrupt void adc_isr(void)
{
    //Force start of conversion on SOC0 and SOC1
    ADC_forceConversion(myAdc, ADC_SocNumber_0);
    ADC_forceConversion(myAdc, ADC_SocNumber_1);

    //if(!IS_FULL)
    //    write_buffer(ADC_readResult(myAdc, ADC_ResultNumber_1));

    pulse_ampl = ADC_readResult(myAdc, ADC_ResultNumber_1);

    SPI_write(mySpi, 10);

    // Clear ADCINT1
    ADC_clearIntFlag(myAdc, ADC_IntNumber_1);
    // Acknowledge the interrupt to PIE
    PIE_clearInt(myPie, PIE_GroupNumber_10);
}

interrupt void xint_isr(void)
{
    if(GpioDataRegs.GPADAT.bit.GPIO12 == TRUE)
    {
        // TODO AREA
        sum_adc_16b_val     = FALSE;
        sum_adc_pulse_val   = FALSE;
        // Set above threshold flag
        is_above_thrsh = TRUE;

        // Clear PIE - XINT1 Interrupt
        PIE_clearInt(myPie, PIE_GroupNumber_1);
    }

    if(GpioDataRegs.GPADAT.bit.GPIO12 == FALSE)
    {
        // Un-set above threshold flag
        is_above_thrsh = FALSE;
        // Clear PIE - XINT1 Interrupt
        PIE_clearInt(myPie, PIE_GroupNumber_1);
    }

    // Clear PIE - XINT1 Interrupt
    PIE_clearInt(myPie, PIE_GroupNumber_1);
}

void main()
{
    int i = 0;
    // System init
    system_init();
    
    #ifdef LAUNCHPAD
        printf("\n\r Initialized DSP system\n\n\r");
    #endif

    // Light up the binary display with a median value (0x08)
    GPIO_setPortData(myGpio, GPIO_Port_A, (~0x08) & 0x0F);

    #ifdef LAUNCHPAD
        EALLOW;
        compsts = Comp2Regs.COMPSTS.bit.COMPSTS;
        gpbdat  = GpioDataRegs.GPBDAT.bit.GPIO34;
        EDIS;
        printf("Comparator Status: %d ", compsts);
        printf("GPIO 34/COMP2OUT Status: %d ", gpbdat);
    #endif

    // Initialize ADC buffer
    adc_buffer_init();

    //Main program loop - continually sample temperature
    for(;;) {
    }
}

  • Just following up to see if anyone has any ideas on this issue. I am yet to get it to work.
  • Hello,

    You need to call CLK_enableTbClockSync() somewhere to start the PWM time base clock. Also, when you call ADC_setSocTrigSrc() to set up SOC1, you chose it to be triggered by ADCSOCB. I suspect you meant ADCSOCA, correct?

    Whitney
  • Hi Whitney, 

    Yes, I managed to get the ADC SOC to be triggered via ePWM after fixing both of those and cleaning the code further. 

    However, I am now onto the next challenge: The idea behind this algorithm is to sample a pulse at 1MHz ePWM. One of the ways I implemented was to use a circular FIFO to dump each sample into within the adc_isr, and read and post-process it in the main() before sending it over SPI.

    However, it looks like anytime I either write into the circular queue OR write into an array within the adc_isr(), the routine seems to hang. Any idea why this could be happening? I have included the code snippet for reference. 

    #define ISR_PULSE_BUFFER_LEN 64
    
    interrupt void adc_isr(void)
    {
        pulse_ampl_wr               = ADC_readResult(myAdc, ADC_ResultNumber_0);
        pulse_ampl[no_of_samples]   = ADC_readResult(myAdc, ADC_ResultNumber_1);
    
        if(no_of_samples < ISR_PULSE_BUFFER_LEN)
            no_of_samples++;
        else
            no_of_samples = FALSE;
    
        // Clear ADCINT1
        ADC_clearIntFlag(myAdc, ADC_IntNumber_1);
        // Acknowledge the interrupt to PIE
        PIE_clearInt(myPie, PIE_GroupNumber_10);
    }
    
    void main()
    {
        int i = 0;
        // System init
        system_init();
    
        // Initialize ADC buffer
        adc_buffer_init();
    
        // Delay system
        DSP28x_usDelay(1000);
    
        //Main program loop - continually sample temperature
        for(;;) {
            // Main loop
    
            if(is_above_thrsh == FALSE || no_of_samples >= ISR_PULSE_BUFFER_LEN)
                is_fifo_processed = TRUE;
    
            if(is_fifo_processed == TRUE)
            {
                for(i = no_of_samples; i > 0; i--)
                {
                    sum_adc_pulse_val = sum_adc_pulse_val + pulse_ampl[i];
                    pulse_ampl[i] = FALSE;
                }
    
                GPIO_setLow(myGpio, GPIO_Number_19);
                pulse_ampl_rd = SPI_read(mySpi);
                SPI_write(mySpi, pulse_ampl_wr << 4);
                GPIO_setHigh(myGpio, GPIO_Number_19);
                sum_adc_pulse_val = FALSE;
                is_fifo_processed = FALSE;
                no_of_samples = FALSE;
            }
        }

    Thanks!
    Mansi