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.
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(;;) { } }
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