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 SOC triggered via ePWM, but data sent over SPI is sporadically shifted incorrectly

Part Number: TMS320F28027

Hello,

I am trying to implement an algorithm that calculates area under a curve and sends that result over SPI to a SPI slave.

ADC SOC is triggered by ePWM1, and gated by an external interrupt i.e. only when the interrupt is high, the ADC value is read and stored in an array. Once the interrupt is low, the values in the array are read and accumulated. Once the entire array has been read and processed, the sum is sent over SPI where F28027 is configured as a SPI Master.

However, I am running into a strange issue. I am spitting out right-justified data on the SPI slave end and it seems to be shifted by 4b/8b etc. every time I flash the same code. It seems very strange to me. As of now, I am simply throwing a value of 1 in the array and summing it before sending it over the SPI. Do you think it is an issue with left-justification?! How do I determine how many bits to shift by if the value is always changing?

Please find the code below:

uint16_t count = 1;

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 clocks
    CLK_enableAdcClock(myClk);
    //CLK_enableTbClockSync(myClk);
    //CLK_enableHrPwmClock(myClk);
    CLK_enablePwmClock(myClk, PWM_Number_1);
    (*Device_cal)();

    //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);

    //--- 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);
    // TODO ADC ePWM
    // Register interrupt handlers in the PIE vector table
    //PIE_registerPieIntHandler(myPie, PIE_GroupNumber_3, PIE_SubGroupNumber_1, (intVec_t)&epwm1_isr);

    // Initalize GPIO
    gpio_init();

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

    // Initialize the ADC
    adc_init();

    // Initialize the PWM
    // TODO ADC ePWM
    pwm_init();

    // Initialize SPI
    spi_init();

    // Initialize SPI FIFO
    spi_fifo_init();

    // Configure GPIO12 as XINT1 in Delta DSP
    #ifdef DELTADSP
        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);
    #endif

    // Enable PIE - XINT1
    PIE_enableInt(myPie, PIE_GroupNumber_1, PIE_InterruptSource_XINT_1);
    // Enable PIE - ADCINT1
    // TODO DEBUG
    PIE_enableInt(myPie, PIE_GroupNumber_10, PIE_InterruptSource_ADCINT_10_1);
    // Enable CPU - INT1
    CPU_enableInt(myCpu, CPU_IntNumber_1);
    // Enable CPU - INT10
    CPU_enableInt(myCpu, CPU_IntNumber_10);
    // Enable EPWM - INT1
    CPU_enableInt(myCpu, CPU_IntNumber_3);

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

    // Set the interrupt polarity
    PIE_setExtIntPolarity(myPie, CPU_ExtIntNumber_1, PIE_ExtIntPolarity_RisingAndFallingEdge);
    // Enable XINT1
    PIE_enableExtInt(myPie, CPU_ExtIntNumber_1);
    // TODO ADC ePWM
    PIE_enablePwmInt(myPie, PWM_Number_1);

    // 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);

    EALLOW;
    //AdcRegs.ADCCTL1.bit.ADCBGPWD = TRUE; // Enabled band gap in ADC
    AdcRegs.ADCCTL1.bit.INTPULSEPOS = TRUE; // EOC Interrupt triggers 1 cycle prior to completion

    AdcRegs.ADCSOC0CTL.bit.CHSEL = 4; //Set SOC0 to sample A4
    AdcRegs.ADCSOC1CTL.bit.CHSEL = 4; //Set SOC1 to sample A4
    AdcRegs.ADCSOC0CTL.bit.ACQPS = 6; //Set SOC0 ACQPS to 7 ADCCLK
    AdcRegs.ADCSOC1CTL.bit.ACQPS = 6; //Set SOC1 ACQPS to 7 ADCCLK
    // TODO DEBUG
    AdcRegs.ADCSOC0CTL.bit.TRIGSEL = 5; // 0: SW; 1: CPUTimer0; 5: PWM1. Trigger source set to EPWM1
    AdcRegs.ADCSOC1CTL.bit.TRIGSEL = 5; // 0: SW; 1: CPUTimer0; 5: PWM1. Trigger source set to EPWM1

    AdcRegs.INTSEL1N2.bit.INT1SEL = 1;   //Connect ADCINT1 to EOC1
    AdcRegs.INTSEL1N2.bit.INT1E = 1;     //Enable ADCINT1
    AdcRegs.INTSEL1N2.bit.INT1CONT = 0;  //Clear flag ADCINT1
    //AdcRegs.INTSEL1N2.bit.INT2SEL = 1;   //Connect ADCINT1 to EOC1
    //AdcRegs.INTSEL1N2.bit.INT2E = 1;     //Enable ADCINT1
    //AdcRegs.INTSEL1N2.bit.INT2CONT = 0;  //Clear flag ADCINT1

    //AdcRegs.ADCINTSOCSEL1.bit.SOC0 = 0; // 0: No ADCINT will trigger SOCx. TRIGSEL will trigger SOCx 1: ADCINT1
    EDIS;
}

void pwm_init()
{
    CLK_disableTbClockSync(myClk);

    // Setup PWM
    PWM_setSyncMode(myPwm, PWM_SyncMode_CounterEqualZero);
    PWM_setPeriod(myPwm, EPWM_PRD);                                     // Set period for ePWM1
    PWM_setCounterMode(myPwm, PWM_CounterMode_Up);                      // count up and start
    PWM_setCmpA(myPwm, EPWM_PRD/2);                                     // Set compare A value
    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_enableInt(myPwm);

    CLK_enableTbClockSync(myClk);
}

void spi_init()
{
    CLK_enableSpiaClock(myClk);

    // Reset on, rising edge, 16-bit char bits
    // TODO AREA
    SPI_setCharLength(mySpi, SPI_CharLength_16_Bits);

    // Enable master mode, normal phase,
    // enable talk, and SPI int disabled.
    // SPI_setMode(mySpi, SPI_Mode_Slave);
    // TODO DSP SPI MASTER
    SPI_setMode(mySpi, SPI_Mode_Master);
    SPI_enableTx(mySpi);

    // Rising edge without delay:   POL = 0; PHA = 0
    // Rising edge with delay:      POL = 0; PHA = 1
    // Falling edge without delay:  POL = 1; PHA = 0
    // Falling edge with delay:     POL = 1; PHA = 1
    SPI_setClkPolarity(mySpi, 0);
    SPI_setClkPhase(mySpi, 0);
    SPI_setBaudRate(mySpi, SPI_BaudRate_1_MBaud);
    SPI_setSteInv(mySpi, SPI_SteInv_ActiveLow);
    SPI_setTriWire(mySpi, SPI_TriWire_NormalFourWire);

    // Relinquish SPI from Reset
    SPI_disableLoopBack(mySpi);
    SPI_enableInt(mySpi);
    SPI_enable(mySpi);

    // Set so breakpoints don't disturb xmission
    SPI_setPriority(mySpi, SPI_Priority_FreeRun);
}

void spi_fifo_init()
{
    // Initialize SPI FIFO registers
    SPI_enableChannels(mySpi);
    SPI_enableFifoEnh(mySpi);

    SPI_resetTxFifo(mySpi);
    SPI_clearTxFifoInt(mySpi);
    SPI_setTxFifoIntLevel(mySpi, SPI_FifoLevel_1_Word);
    SPI_enableTxFifoInt(mySpi);

    SPI_resetRxFifo(mySpi);
    SPI_clearRxFifoInt(mySpi);
    //SPI_setRxFifoIntLevel(mySpi, SPI_FifoLevel_1_Word);
    //SPI_enableRxFifoInt(mySpi);
}

interrupt void xint_isr(void)
{
    if(GpioDataRegs.GPADAT.bit.GPIO12 == TRUE)
    {
        // Set above threshold flag
        is_above_thrsh = TRUE;
        // Increment above_thrsh counter
        count_above_thrsh++;
    }

    if(GpioDataRegs.GPADAT.bit.GPIO12 == FALSE)
    {
        // Un-set above threshold flag
        is_above_thrsh = FALSE;
        // Increment below thrsh counter
        count_below_thrsh++;
    }

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

interrupt void adc_isr(void)
{
    if(is_above_thrsh == TRUE)
    {
        pulse_ampl_wr               = ADC_readResult(myAdc, ADC_ResultNumber_0);
        pulse_ampl_wr               = ADC_readResult(myAdc, ADC_ResultNumber_1);

        if(no_of_samples < ISR_PULSE_BUFFER_LEN)
        {
            pulse_ampl[no_of_samples]   = count;
            no_of_samples++;
        }
    }

    if(is_above_thrsh == FALSE)
        is_fifo_processed   = TRUE;

    // 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_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;
            }

            // SPI Transfer
            //GPIO_setLow(myGpio, GPIO_Number_19);
            //pulse_ampl_rd = SPI_read(mySpi);
            sum_adc_16b_val = sum_adc_pulse_val;
            SPI_write(mySpi, sum_adc_16b_val << 4);
            //GPIO_setHigh(myGpio, GPIO_Number_19);

            // Reset all the state flags
            sum_adc_pulse_val = FALSE;
            is_fifo_processed = FALSE;
            no_of_samples = FALSE;
            is_above_thrsh = -1;
        }
    }
}