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.

[参考译文] AM2432:AM2432:ADC 中断突然无法触发

Guru**** 2387080 points
请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

https://e2e.ti.com/support/microcontrollers/arm-based-microcontrollers-group/arm-based-microcontrollers/f/arm-based-microcontrollers-forum/1427209/am2432-am2432-adc-interrupt-suddenly-fail-to-trigger

器件型号:AM2432

工具与软件:

您好:

使用 ADC 时、偶尔会出现中断丢失的问题。 请帮助我们检查:

1. 我们在 PWM 中断中触发 ADC (单次触发模式)、PWM 优先级为7、ADC 优先级为1。 ;中有定时器中断和 GPIO 中断、它们的中断优先级为7 μ s

2. ADC 中断可在启动时正常触发、但在随后的运行中、ADC 中断会丢失、无法恢复;

3、在我们的测试中,运行30分钟、2小时、8小时等时会出现此问题;

4. 出现问题时:

a.计时器、PWM、GPIO 和其他中断可正常触发;

b. FreeRTOS 只能运行空闲任务;

c. 可以更新 ADC_FIFO0WC、因此 ADC 仍应正常采样、但尚未触发中断;

d. 即使调用 Hwip_enableInt ()来重新启用 ADC 中断,中断也无法恢复。

我的程序如下:

uint16_t adc_original_buff[APP_ADC_NUM_CH];
int32_t adc_buff[APP_ADC_NUM_CH];
float curr_result[3];
static HwiP_Object gAdcHwiObject;
HwiP_Params hwiPrms;
volatile uint32_t adc_start_ns = 0;
volatile uint32_t adc_interval_ns = 0;

void App_adcGetData(void)
{
    uint32_t voltageLvl;
    uint32_t id;
    uint32_t baseAddr = CONFIG_ADC0_BASE_ADDR;
    uint32_t i = 0;
    uint32_t fifoData = 0;
    uint32_t fifoWordCnt;

    if(is_float_zero(gUserParams_float.adc_gain) == MT_TRUE)
    {
        gUserParams_float.adc_gain = 0.15f;
    }

    /* Get FIFO data */
    fifoWordCnt = ADCGetFIFOWordCount(baseAddr, ADC_FIFO_NUM_0);
    for (i = 0U; i < fifoWordCnt; i++)
    {
        fifoData = ADCGetFIFOData(baseAddr, ADC_FIFO_NUM_0);
        id  = ((fifoData & ADC_FIFODATA_ADCCHNLID_MASK) >>
                    ADC_FIFODATA_ADCCHNLID_SHIFT);
        fifoData = ((fifoData & ADC_FIFODATA_ADCDATA_MASK) >>
                    ADC_FIFODATA_ADCDATA_SHIFT);
        adc_original_buff[id] = (uint16_t)fifoData;

        if((id > 2) && (id < 6))
        {
            voltageLvl  = fifoData * (uint32_t) (V_ADC_REF * 1000);
            voltageLvl /= (uint32_t) ADC_GET_RANGE(CONFIG_ADC0_NUM_BITS);
            if(Old_m_state == MC_STATE_CALIBRATION)
            {
                //1650 = 3.3V * 1000 / 2
                adc_buff[id] = voltageLvl - 1650;
            }
            else
            {
                adc_buff[id] = voltageLvl - 1650 - hal_hwParams_u32_t.PhaseCurrOffset[id - 3];
            }
            curr_result[id - 3] = (adc_buff[id] * 1.0f / 1000.0f) / gUserParams_float.adc_gain;
        }
        else
        {
            adc_buff[id] = fifoData;
        }
    }
    adc_interval_ns = clock_cal_interval(adc_start_ns, clock_get_ns());
}

void App_adcISR(void *handle)
{
    uint32_t status;
    uint32_t baseAddr = CONFIG_ADC0_BASE_ADDR;

    /* Get interrupt status and clear */
    status = ADCGetIntrStatus(baseAddr);
    ADCClearIntrStatus(baseAddr, status);

    App_adcGetData();

    /* Set EOI to generate next interrupt if any */
    ADCWriteEOI(baseAddr);
}

void App_adcConfig(uint32_t baseAddr)
{
    adcStepConfig_t adcConfig;
    uint32_t        chCnt, adcStep;

    /* Enable interrupts */
    ADCEnableIntr(baseAddr, ADC_INTR_SRC_FIFO0_THRESHOLD);

    /*
     * Configure all ADC Steps
     */
    /* Initialize ADC configuration params */
    adcConfig.mode             = ADC_OPERATION_MODE_SINGLE_SHOT;
    adcConfig.openDelay        = 0x0U;
    adcConfig.sampleDelay      = 0U;
    adcConfig.rangeCheckEnable = 0U;
    adcConfig.averaging        = ADC_AVERAGING_NONE;
    adcConfig.fifoNum          = ADC_FIFO_NUM_0;

    /* Configure all required steps - Step 1 to N mapped to Channel 1 to N */
    for(chCnt = 0U; chCnt < APP_ADC_NUM_CH; chCnt++)
    {
        adcConfig.channel = ADC_CHANNEL_1 + chCnt;
        adcStep = ADC_STEP_1 + chCnt;   /* Step -> Channel one to one mapped */
        ADCSetStepParams(baseAddr, adcStep, &adcConfig);
    }

    ADCStepIdTagEnable(baseAddr, TRUE);
    ADCSetCPUFIFOThresholdLevel(baseAddr, ADC_FIFO_NUM_0, APP_ADC_NUM_CH * 2);

    /* Step enable */
    for(chCnt = 0U; chCnt < APP_ADC_NUM_CH; chCnt++)
    {
        adcStep = ADC_STEP_1 + chCnt;   /* Step -> Channel one to one mapped */
        ADCStepEnable(baseAddr, adcStep, TRUE);
    }
}

static void App_adcInit(uint32_t baseAddr)
{
    /* Clear All interrupt status */
    ADCClearIntrStatus(baseAddr, ADC_INTR_STATUS_ALL);

    /* Register & enable interrupt */
    HwiP_Params_init(&hwiPrms);
    hwiPrms.intNum = CONFIG_ADC0_INTR;
    hwiPrms.callback = &App_adcISR;
    hwiPrms.priority = 1U;
    HwiP_construct(&gAdcHwiObject, &hwiPrms);

    /* Power up AFE */
    ADCPowerUp(baseAddr, TRUE);

    /* Wait for 4us at least */
    ClockP_usleep(5U);

    /* Do the internal calibration */
    ADCInit(baseAddr, FALSE, 0U, 0U);
}

static void App_adcStart(uint32_t baseAddr)
{
    adcSequencerStatus_t status;

    /* Check if FSM is idle */
    ADCGetSequencerStatus(baseAddr, &status);
    while ((ADC_ADCSTAT_FSM_BUSY_IDLE != status.fsmBusy) &&
           ADC_ADCSTAT_STEP_ID_IDLE != status.stepId)
    {
        ADCGetSequencerStatus(baseAddr, &status);
    }
    /* Start ADC conversion */
    ADCStart(baseAddr, TRUE);
}

int32_t hal_adc_init(void)
{
    uint32_t baseAddr = CONFIG_ADC0_BASE_ADDR;

    App_adcInit(baseAddr);
    App_adcConfig(baseAddr);
    /* Set EOI to generate next interrupt if any */
    ADCWriteEOI(baseAddr);
    App_adcStart(baseAddr);

    return MT_OK;
}

void hal_adc_trigger(void)
{
    uint32_t baseAddr = CONFIG_ADC0_BASE_ADDR;
    uint32_t                chCnt, adcStep;

    /* Step enable */
    for(chCnt = 0U; chCnt < APP_ADC_NUM_CH; chCnt++)
    {
        adcStep = ADC_STEP_1 + chCnt;   /* Step -> Channel one to one mapped */
        ADCStepEnable(baseAddr, adcStep, TRUE);
    }

    adc_start_ns = clock_get_ns();
    App_adcStart(baseAddr);
}

请帮助我们确认:

1. ADC 的配置和使用是否有问题;

2.在 ADC 正常中断处理过程中,我们将暂停并启动定时器,不管是否存在中断嵌套问题;

3.是否有其他因素会导致 ADC 的中断异常。

谢谢。

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    您好、Walker:

    感谢您的提问。

     指定的专家不在办公室。 对该线程的响应将被延迟。  

    感谢您的耐心。

    此致、

    Tushar

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    您好、Walker:

    您能检查一下吗 R5FSS_VIM_PRIIRQ 来请求挂起中断。

    您能在中看到 ADC 中断号吗 R5FSS_VIM_PRIIRQ 在问题发生时注册?

    此外、检查以下寄存器及其值、以了解发生问题时的中断状态?

    请参阅下图。

    此致、

    Tushar

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    尊敬的 Walker。

    请您查看 Tushar 的回复并提供您的状态吗?

    非常感谢!

    Yong