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.

TMS470M ADC FIFO triggers interrupt

I’m trying to get the ADC FIFO to take 16 samples, save them to the FIFO and then trigger an interrupt.  The code I have only works once and then I have to power cycle before it will trigger again.  Here is the ADC initialization settings:

At the start of main I initialize as follows:

adcInit();

adcResetFiFo(adcREG1, adcGROUP1);

adcEnableNotification(adcREG1, adcGROUP1);

adcStartConversion(adcREG1, adcGROUP1);

 

The interrupt handler is below:

 

void saveADCSamples(ADC_DATA_STRUCT* self)

{

    int i;

      for(i=0; i<16; i++){

            // copy the samples into our buffer

            self->samples[self->currentSampleCounter][i] = adcREG1->GxBUF[1].BUF0;

      }

    INCREMENT_SAMPLES_WITH_WRAP(self->currentSampleCounter);

}

 

#pragma INTERRUPT(adcGroup1Interrupt)

 

void adcGroup1Interrupt(void)

{

    adcREG1->GxINTFLG[1U] = 9U; // clear the interrupt flag

    saveADCSamples(&ADC_Struct); // save the data

    // G1IntCtrl is back to 0x10 and device should be ready to trigger again

    // I’ve tried adcResetFifo here but didn’t make a difference

    // Only way to enter this code again is to power cycle and apply trigger

}

 

My guess is that something with the DMA control is not getting set right.  Also, what is G1DMACtrl it’s not documented?

 

Thanks for the help,

 

Chris

  • Still looking for a response on this one!  I know it's the holidays but if it takes until January to get a response I think a 1 month turn around time is still a bit unreasonable.

    I looked into which register values are different before the first call of the interrupt and after and there were NO differences in the NVIC, M3VIM, and ADC except for these in the ADC buffer.

    Here are the relevant registers and their values:

    Before Int During After
    SetEn1 0x000000FF 0x000000FF 0x000000FF
    ClrEn1 0x000000FF 0x000000FF 0x000000FF
    SetPEn1 0x00000000 0x00000000 0x00000000
    ClrPEn1 0x00000000 0x00000000 0x00000000
    ActBit1 0x00000000 0x00000001 0x00000000
    ISCSR 0x00000000 0x00000810 0x00000000
    G1ModeCtrl 0x00000028 0x00000028 0x00000028
    G1Src 0x00000009 0x00000009 0x00000009
    G1IntEna 0x00000008 0x00000008 0x00000008
    G1IntFlg 0x00000004 0x00000009 0x00000004
    G1IntCtrl 0x00000010 0x00000000 0x00000010
    G1DmaCtrl 0x00100000 0x00000000 0x00100000
    G1Samp 0x00000000 0x00000000 0x00000000
    G1Sr 0x00000008 0x00000001 0x00000008
    G1Sel 0x0000FFFF 0x0000FFFF 0x0000FFFF
    G1FifoRstCtrl 0x00000000 0x00000000 0x00000000
    Nest_stat 0x00000002 0x00000102 0x00000102
  • Can you post your project? At least ADC.c and the code you do with HET.

    I did not see anything wrong here. But the register GxBuffer value looks like there are data that was not read out.

    Regards,

    Haixiao

  • The project is rather large and hard to extract the TMS470 portion but the code you're interested is shown above and adc.c is shown below:

    /** @file adc.c
    *   @brief ADC Driver Source File
    *   @date 15.March.2011
    *   @version 1.00.000
    *
    *   This file contains:
    *   - API Funcions
    *   - Interrupt Handlers
    *   .
    *   which are relevant for the ADC driver.
    */

    /* (c) Texas Instruments 2011, All rights reserved. */

    #if 1

    /* USER CODE BEGIN (0) */
    /* USER CODE END */


    /* Include Files */

    #include "adc.h"

    /* USER CODE BEGIN (1) */
    /* USER CODE END */


    /** @fn void adcInit(void)
    *   @brief Initializes ADC Driver
    *
    *   This function initializes the ADC driver.
    *
    */

    /* USER CODE BEGIN (2) */
    /* USER CODE END */

    void adcInit(void)
    {
    /* USER CODE BEGIN (3) */
    /* USER CODE END */
        /** @b Initialize @b ADC: */

        /** - Reset ADC module */
        adcREG1->RSTCR = 1U;
        adcREG1->RSTCR = 0U;
     
        /** - Setup prescaler */
        adcREG1->CLOCKCR = 7U;
     
        /** - Setup memory boundaries */
        adcREG1->BNDCR  = (8U << 16U) | (8U + 8U);
        adcREG1->BNDEND = 2U;
     
        /** - Setup event group conversion mode
        *     - Setup data format
        *     - Enable/Disable channel id in conversion result
        *     - Enable/Disable continuous conversion
        */
        adcREG1->GxMODECR[0U] = ADC_10_BIT
                              | 0x00000000U
                              | 0x00000000U;

        /** - Setup event group hardware trigger
        *     - Setup hardware trigger edge
        *     - Setup hardware trigger source
        */
        adcREG1->G0SRC = 0x00000000U
                       | ADC_EVENT;

        /** - Setup event group sample window */
        adcREG1->G0SAMP = 0U;

        /** - Setup event group sample discharge
        *     - Setup discharge prescaler
        *     - Enable/Disable discharge
        */
        adcREG1->G0SAMPDISEN = 0U << 8U
                             | 0x00000000U;

        /** - Setup group 1 conversion mode
        *     - Setup data format
        *     - Enable/Disable channel id in conversion result
        *     - Enable/Disable continuous conversion
        */
        adcREG1->GxMODECR[1U] = ADC_10_BIT
                              | 0x00000020U
                              | 0x00000008U
                              | 0x00000000U;

        /** - Setup group 1 hardware trigger
        *     - Setup hardware trigger edge
        *     - Setup hardware trigger source
        */
        adcREG1->G1SRC = 0x00000008U
                       | ADC_HET1;

        /** - Setup group 1 sample window */
        adcREG1->G1SAMP = 0U;

        /** - Setup group 1 sample discharge
        *     - Setup discharge prescaler
        *     - Enable/Disable discharge
        */
        adcREG1->G1SAMPDISEN = 0U << 8U
                             | 0x00000000U;

        /** - Setup group 2 conversion mode
        *     - Setup data format
        *     - Enable/Disable channel id in conversion result
        *     - Enable/Disable continuous conversion
        */
        adcREG1->GxMODECR[2U] = ADC_10_BIT
                              | 0x00000000U
                              | 0x00000000U
                              | 0x00000000U;

        /** - Setup group 2 hardware trigger
        *     - Setup hardware trigger edge
        *     - Setup hardware trigger source
        */
        adcREG1->G2SRC = 0x00000000U
                       | ADC_EVENT;

        /** - Setup group 2 sample window */
        adcREG1->G2SAMP = 0U;

        /** - Setup group 2 sample discharge
        *     - Setup discharge prescaler
        *     - Enable/Disable discharge
        */
        adcREG1->G2SAMPDISEN = 0U << 8U
                             | 0x00000000U;

        /** - Enable ADC module */
        adcREG1->OPMODECR = 0x00140001U;

        /** - Wait for buffer inialisation complete */
        while (adcREG1->BUFINIT) { /* Wait */ }
        
        /** - Setup parity */
        adcREG1->PARCR = 0x00000005U;

     

        /**   @note This function has to be called before the driver can be used.\n
        *           This function has to be executed in priviledged mode.\n
        */

    /* USER CODE BEGIN (4) */
    /* USER CODE END */
    }

    /* USER CODE BEGIN (5) */
    /* USER CODE END */


    /** @fn void adcStartConversion(adcBASE_t *adc, unsigned group)
    *   @brief Starts an ADC conversion
    *   @param[in] adc Pointer to ADC module:
    *              - adcREG1: ADC module pointer
    *   @param[in] group Hardware group of ADC module:
    *              - adcGROUP0: ADC event group
    *              - adcGROUP1: ADC group 1
    *              - adcGROUP2: ADC group 2
    *
    *   This function starts a convesion of the ADC hardware group.
    *
    */

    /** - s_adcSelect is used as constant table for channel selection */
    static const unsigned s_adcSelect[2U][3U] =
    {
        0x00000000U |
        0x00000000U |
        0x00000000U |
        0x00000000U |
        0x00000000U |
        0x00000000U |
        0x00000000U |
        0x00000000U |
        0x00000000U |
        0x00000000U |
        0x00000000U |
        0x00000000U |
        0x00000000U |
        0x00000000U |
        0x00000000U |
        0x00000000U,
        0x00000001U |
        0x00000002U |
        0x00000004U |
        0x00000008U |
        0x00000010U |
        0x00000020U |
        0x00000040U |
        0x00000080U |
        0x00000100U |
        0x00000200U |
        0x00000400U |
        0x00000800U |
        0x00001000U |
        0x00002000U |
        0x00004000U |
        0x00008000U,
        0x00000000U |
        0x00000000U |
        0x00000000U |
        0x00000000U |
        0x00000000U |
        0x00000000U |
        0x00000000U |
        0x00000000U |
        0x00000000U |
        0x00000000U |
        0x00000000U |
        0x00000000U |
        0x00000000U |
        0x00000000U |
        0x00000000U |
        0x00000000U,
    };

    /** - s_adcSelect is used as constant table for channel selection */
    static const int s_adcFiFoSize[2U][3U] =
    {
        16U,
        16U,
        16U,
    };

    /* USER CODE BEGIN (6) */
    /* USER CODE END */

    void adcStartConversion(adcBASE_t *adc, unsigned group)
    {
        unsigned index = adc == adcREG1 ? 0U : 1U;

    /* USER CODE BEGIN (7) */
    /* USER CODE END */

        /** - Setup FiFo size */
        adc->GxINTCR[group] = s_adcFiFoSize[index][group];

        /** - Start Conversion */
        adc->GxSEL[group] = s_adcSelect[index][group];

        /**   @note The function adcInit has to be called before this function can be used. */

    /* USER CODE BEGIN (8) */
    /* USER CODE END */
    }

    /* USER CODE BEGIN (9) */
    /* USER CODE END */


    /** @fn void adcStopConversion(adcBASE_t *adc, unsigned group)
    *   @brief Stops an ADC conversion
    *   @param[in] adc Pointer to ADC module:
    *              - adcREG1: ADC module pointer
    *   @param[in] group Hardware group of ADC module:
    *              - adcGROUP0: ADC event group
    *              - adcGROUP1: ADC group 1
    *              - adcGROUP2: ADC group 2
    *
    *   This function stops a convesion of the ADC hardware group.
    *
    */

    /* USER CODE BEGIN (10) */
    /* USER CODE END */

    void adcStopConversion(adcBASE_t *adc, unsigned group)
    {
    /* USER CODE BEGIN (11) */
    /* USER CODE END */

        /** - Stop Conversion */
        adc->GxSEL[group] = 0U;

        /**   @note The function adcInit has to be called before this function can be used. */

    /* USER CODE BEGIN (12) */
    /* USER CODE END */
    }

    /* USER CODE BEGIN (13) */
    /* USER CODE END */


    /** @fn void adcResetFiFo(adcBASE_t *adc, unsigned group)
    *   @brief Resets FiFo read and write pointer.
    *   @param[in] adc Pointer to ADC module:
    *              - adcREG1: ADC module pointer
    *   @param[in] group Hardware group of ADC module:
    *              - adcGROUP0: ADC event group
    *              - adcGROUP1: ADC group 1
    *              - adcGROUP2: ADC group 2
    *
    *   This function resets the FiFo read and write pointrs.
    *
    */

    /* USER CODE BEGIN (14) */
    /* USER CODE END */

    void adcResetFiFo(adcBASE_t *adc, unsigned group)
    {
    /* USER CODE BEGIN (15) */
    /* USER CODE END */

        /** - Reset FiFo */
        adc->GxFIFORESETCR[group] = 1U;

        /**   @note The function adcInit has to be called before this function can be used.\n
        *           the conversion should be stopped before calling this function.
        */

    /* USER CODE BEGIN (16) */
    /* USER CODE END */
    }

    /* USER CODE BEGIN (17) */
    /* USER CODE END */


    /** @fn int adcGetData(adcBASE_t *adc, unsigned group, adcData_t *data)
    *   @brief Gets converted a ADC values
    *   @param[in] adc Pointer to ADC module:
    *              - adcREG1: ADC module pointer
    *   @param[in] group Hardware group of ADC module:
    *              - adcGROUP0: ADC event group
    *              - adcGROUP1: ADC group 1
    *              - adcGROUP2: ADC group 2
    *   @param[out] data Pointer to store ADC converted data
    *   @return The function will return the number of converted values copied into data buffer:
    *
    *   This function writes a ADC message into a ADC message box.
    *
    */


    /* USER CODE BEGIN (18) */
    /* USER CODE END */

    int adcGetData(adcBASE_t *adc, unsigned group, adcData_t *data)
    {
        int       i;
        unsigned  buf;
        unsigned  index = adc == adcREG1 ? 0U : 1U;
        int       count = adc->GxINTCR[group] >= 256U ? s_adcFiFoSize[index][group] : s_adcFiFoSize[index][group] - (int)(adc->GxINTCR[group] & 0xFF);
        adcData_t *ptr = data;

    /* USER CODE BEGIN (19) */
    /* USER CODE END */

        /** -  Get conversion data and channel/pin id */
        for (i = 0; i < count; i++)
        {
            buf        = adc->GxBUF[group].BUF0;
            ptr->value = (unsigned short)(buf & 0x3FFU);
            ptr->id    = (int)((buf >> 10U) & 0x1FU);
            ptr++;
        }

        adc->GxINTFLG[group] = 9U;

        /**   @note The function adcInit has to be called before this function can be used.\n
        *           The user is responsible to initialize the message box.
        */

    /* USER CODE BEGIN (20) */
    /* USER CODE END */

        return count;
    }

    /* USER CODE BEGIN (21) */
    /* USER CODE END */


    /** @fn int adcIsFifoFull(adcBASE_t *adc, unsigned group)
    *   @brief Checks if FiFo buffer is full
    *   @param[in] adc Pointer to ADC module:
    *              - adcREG1: ADC module pointer
    *   @param[in] group Hardware group of ADC module:
    *              - adcGROUP0: ADC event group
    *              - adcGROUP1: ADC group 1
    *              - adcGROUP2: ADC group 2
    *   @return The function will return:
    *           - 0: When FiFo buffer is not full   
    *           - 1: When FiFo buffer is full   
    *           - 3: When FiFo buffer overflow occured    
    *
    *   This function checks FiFo buffer status.
    *
    */


    /* USER CODE BEGIN (22) */
    /* USER CODE END */

    int adcIsFifoFull(adcBASE_t *adc, unsigned group)
    {
        int flags;

    /* USER CODE BEGIN (23) */
    /* USER CODE END */

        /** - Read FiFo flags */
        flags = adc->GxINTFLG[group] & 3U;

        /**   @note The function adcInit has to be called before this function can be used. */

    /* USER CODE BEGIN (24) */
    /* USER CODE END */

        return flags;
    }

    /* USER CODE BEGIN (25) */
    /* USER CODE END */


    /** @fn int adcIsConversionComplete(adcBASE_t *adc, unsigned group)
    *   @brief Checks if Conversion is complete
    *   @param[in] adc Pointer to ADC module:
    *              - adcREG1: ADC module pointer
    *   @param[in] group Hardware group of ADC module:
    *              - adcGROUP0: ADC event group
    *              - adcGROUP1: ADC group 1
    *              - adcGROUP2: ADC group 2
    *   @return The function will return:
    *           - 0: When is not finished   
    *           - 8: When conversion is complete   
    *
    *   This function checks if conversion is complete.
    *
    */


    /* USER CODE BEGIN (26) */
    /* USER CODE END */

    int adcIsConversionComplete(adcBASE_t *adc, unsigned group)
    {
        int flags;

    /* USER CODE BEGIN (27) */
    /* USER CODE END */

        /** - Read conversion flags */
        flags = adc->GxINTFLG[group] & 8U;

        /**   @note The function adcInit has to be called before this function can be used. */

    /* USER CODE BEGIN (28) */
    /* USER CODE END */

        return flags;
    }

    /* USER CODE BEGIN (29) */
    /* USER CODE END */


    /** @fn void adcEnableNotification(adcBASE_t *adc, unsigned group)
    *   @brief Enable notification
    *   @param[in] adc Pointer to ADC module:
    *              - adcREG1: ADC module pointer
    *   @param[in] group Hardware group of ADC module:
    *              - adcGROUP0: ADC event group
    *              - adcGROUP1: ADC group 1
    *              - adcGROUP2: ADC group 2
    *
    *   This function will enable the notification of a conversion.
    *   In single conversion mode for conversion complete and
    *   in continuous conversion mode when the FiFo buffer is full.
    *
    */

    /* USER CODE BEGIN (30) */
    /* USER CODE END */

    void adcEnableNotification(adcBASE_t *adc, unsigned group)
    {
        unsigned notif = adc->GxMODECR[group] & 2U ? 1U : 8U;

    /* USER CODE BEGIN (31) */
    /* USER CODE END */

        adc->GxINTENA[group] = notif;

        /**   @note The function adcInit has to be called before this function can be used.\n
        *           This function should be called before the conversion is started
        */

    /* USER CODE BEGIN (32) */
    /* USER CODE END */
    }

    /* USER CODE BEGIN (33) */
    /* USER CODE END */


    /** @fn void adcDisableNotification(adcBASE_t *adc, unsigned group)
    *   @brief Disable notification
    *   @param[in] adc Pointer to ADC module:
    *              - adcREG1: ADC module pointer
    *   @param[in] group Hardware group of ADC module:
    *              - adcGROUP0: ADC event group
    *              - adcGROUP1: ADC group 1
    *              - adcGROUP2: ADC group 2
    *
    *   This function will disable the notification of a conversion.
    */

    /* USER CODE BEGIN (34) */
    /* USER CODE END */

    void adcDisableNotification(adcBASE_t *adc, unsigned group)
    {
    /* USER CODE BEGIN (35) */
    /* USER CODE END */

        adc->GxINTENA[group] = 0U;

        /**   @note The function adcInit has to be called before this function can be used. */

    /* USER CODE BEGIN (36) */
    /* USER CODE END */
    }

    /* USER CODE BEGIN (37) */
    /* USER CODE END */


    /** @fn void adcGroup0Interrupt(void)
    *   @brief ADC Event Group Interrupt Handler
    */

    /* USER CODE BEGIN (38) */
    /* USER CODE END */

    #if 1
        #pragma INTERRUPT(adcGroup0Interrupt)
    #endif

    void adcGroup0Interrupt(void)
    {
    /* USER CODE BEGIN (39) */
    /* USER CODE END */
        
        adcREG1->GxINTFLG[0U] = 9U;

        adcNotification(adcREG1, adcGROUP0);

    /* USER CODE BEGIN (40) */
    /* USER CODE END */
    }

    /* USER CODE BEGIN (41) */
    /* USER CODE END */


    /** @fn void adcGroup1Interrupt(void)
    *   @brief ADC Group 1 Interrupt Handler
    */

    /* USER CODE BEGIN (42) */
    /* USER CODE END */

    // Commented out because redefined in our adc470m.c
    //#if 1
    //    #pragma INTERRUPT(adcGroup1Interrupt)
    //#endif
    //
    //void adcGroup1Interrupt(void)
    //{
    ///* USER CODE BEGIN (43) */
    ///* USER CODE END */
    //
    //    adcREG1->GxINTFLG[1U] = 9U;
    //
    //    adcNotification(adcREG1, adcGROUP1);
    //
    ///* USER CODE BEGIN (44) */
    ///* USER CODE END */
    //}

    /* USER CODE BEGIN (45) */
    /* USER CODE END */


    /** @fn void adcGroup2Interrupt(void)
    *   @brief ADC Group 2 Interrupt Handler
    */

    /* USER CODE BEGIN (46) */
    /* USER CODE END */

    #if 1
        #pragma INTERRUPT(adcGroup2Interrupt)
    #endif

    void adcGroup2Interrupt(void)
    {
    /* USER CODE BEGIN (47) */
    /* USER CODE END */
        
        adcREG1->GxINTFLG[2U] = 9U;

        adcNotification(adcREG1, adcGROUP2);

    /* USER CODE BEGIN (48) */
    /* USER CODE END */
    }

    /* USER CODE BEGIN (49) */
    /* USER CODE END */


    #endif


  • So far, I did not see anything wrong.

    Could you please send me your adc.c and adc.h? Then I insert your code into my project to see if it works as expected.

    My email address: haixiao.weng@ti.com

    Regards,

    Haixiao

  • The ADC code you sent to me works perfert on my bench.

    I am going to send back my project.

    TO play my project, please configure the UART to:

    9600, 2 stop bit, no parity,

    I use the USB stick. Press 0 and 1 alternatively and observe the change on the LET lights. Whenever there is interrupt, the HET0 status changes (from 0->1 or 1->0)

    Regards,H

    aixiao

  • Could you please check your Junk email box?

    I sent it out yesterday around 3:30PM. And I re-sent it 5 miniutes ago.

    If you approve, I can post the zip project in this forum. (It contains your code so I need your approval.)

    Regards,

    Haixiao

  • Yeah, the IT dept didn't like the zip file, but I have got it now.  I'll let you know what I find for any differences between your project and mine.

    Thanks,

    Chris

  • Looks like problem may have been an electrical issue all along and nothing to do with software.  I was touching the LED on HET1 to 3.3V and then expecting it and it's resistor to act as a pull down to zero.  When I touched 3.3V again it looks like it was not triggering because the input hadn't gone all the way back to zero.  I suppose the diode drop was enough not to take it all the way to ground.  When I hooked up HET3 as an output driving HET1 it all started to work. 

    Thanks for your help.