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.

MSPM0L1306: ADC Repeat Sequence Conversion when total channel >4 using FIFO and DMA, reference manual errata needed

Part Number: MSPM0L1306

Hi,

We want to use the ADC Repeat Sequence Conversion feature. However, when implement this, we encounter serval issues:

We recognize that in MSPM0L chip, total conversion register is 4 (MEMRES0:3)

Does it mean that in non-FIFO mode, the max configurable channel is 4 and must use MEMCTL0:3 to configure them, then get results from MEMRES0:3 ?

Later, if we use FIFO with DMA, we see that in 9.2.12.2 DMA and FIFO Operation: ADC-DMA/CPU Operation in FIFO Mode (FIFOEN=1), 

"SAMPCNT must be programmed by SW to a suitable value based on threshold setting for DMA operation" What is the "suitable" value?

Do you have equation to calculate it if total channel number is N, we want M samples per channel (does not count hardware averaging oversample here, just assume MEMRESx will be actually written M times per channel) and either MEMRESIFG1 or MEMRESIFG3 is selected. What are the function parameters should be use for DL_ADC12_setDMASamplesCnt() and DL_DMA_setTransferSize() ?

It seems that if I configure the MEMCTL0:7 (total 8 channels), and set DMA trigger to MEMRESIFG1, sample count to 1, transfer size to M*N/2, the ADC raised OVERFLOW interrupt.

If I set DMA trigger to MEMRESIFG3, sample count to 2, when channel count is not 4, results are incorrect. (root of cause: DMA always fill ch0, ch1, ch2, ch3, ch0, ch1, ... and cycle)

I attached our code in this context.

Also, some typos and/or unclear things in the current reference manual slau847c:

  1. Multiple occurrence of "ASC", e.g, ASCRES register, ASCDONE / ASCVRSELASCACT / ... bitfield(s). Are they actually mean "ADC"?
  2. Multiple register that can configure the reference buffer: ADC0->REFCFG and VREF->CTL0
    1. follow-up question: Sometime, the ADC0->STATUS.REFBUFRDY flag doesn't work when polling it
  3. If we are cycling channels including the mix of using VDDA and Internal Reference, will CONVCLK automatically switch to satisfy the 4MHz max clock if internal ref is used?
    1. Is it controlled by ASCVRSEL bits globally , or channel specific MEMCTL[y].VRSEL bits?

Bests,

static bool gCheckADC;
static uint32_t gADCError;
__attribute__((aligned(4)))
static uint16_t gADCSamples[256];

/* ADC12_0 Initialization */
static const DL_ADC12_ClockConfig gADC12_0ClockConfig = {
    .clockSel       = DL_ADC12_CLOCK_SYSOSC,
    .divideRatio    = DL_ADC12_CLOCK_DIVIDE_8, //Select suitable clock divide ratio
    .freqRange      = DL_ADC12_CLOCK_FREQ_RANGE_24_TO_32,
};

uint32_t Driver_ADCInitAndSampling(uint32_t adcChannel, uint32_t vrefSource, uint8_t added_bits) {
    uint32_t u32AdcSum = 0;
    uint16_t adc_samples = 0;

    DL_ADC12_reset(ADC0);
    DL_ADC12_enablePower(ADC0);
    while (!DL_ADC12_isPowerEnabled(ADC0)) {
        delay_cycles(5 * 32);
    }
    // DL_ADC12_disableConversions(ADC0);
    DL_ADC12_setClockConfig(ADC0, (DL_ADC12_ClockConfig *) &gADC12_0ClockConfig);
    DL_ADC12_configConversionMem(
        ADC0, DL_ADC12_MEM_IDX_0, adcChannel, vrefSource,
        DL_ADC12_SAMPLE_TIMER_SOURCE_SCOMP0,
        added_bits ? DL_ADC12_AVERAGING_MODE_ENABLED : DL_ADC12_AVERAGING_MODE_DISABLED,
        DL_ADC12_BURN_OUT_SOURCE_DISABLED, DL_ADC12_TRIGGER_MODE_AUTO_NEXT,
        DL_ADC12_WINDOWS_COMP_MODE_DISABLED);
    if (added_bits) {
        uint32_t hw_avg_numerator;
        uint32_t hw_avg_denominator;
        if (added_bits > 3) {
            hw_avg_numerator = ADC12_CTL1_AVGN_AVG_128;
            hw_avg_denominator = ADC12_CTL1_AVGD_SHIFT3;
            added_bits -= 3;
            adc_samples = 1 << ((uint16_t)added_bits * 2 - 1);
            for (uint16_t i = 0; i < adc_samples; i++) {
                gADCSamples[i] = 0;
            }
        } else {
            hw_avg_numerator = ((uint32_t)added_bits << (1 + ADC12_CTL1_AVGN_OFS)) & ADC12_CTL1_AVGN_MASK;
            hw_avg_denominator = ((uint32_t)added_bits << ADC12_CTL1_AVGD_OFS) & ADC12_CTL1_AVGD_MASK;
        }
        DL_ADC12_configHwAverage(ADC0, hw_avg_numerator, hw_avg_denominator);
    }
    DL_ADC12_setPowerDownMode(ADC0, DL_ADC12_POWER_DOWN_MODE_MANUAL);
    DL_ADC12_setSampleTime0(ADC0, ADC_SAMPLE_TIME);
    DL_Common_updateReg(&ADC0->ULLMEM.REFCFG,
                        ADC12_REFCFG_REFEN_ENABLE | ADC12_REFCFG_REFVSEL_V1P4,
                        ADC12_REFCFG_REFEN_MASK | ADC12_REFCFG_REFVSEL_MASK | ADC12_REFCFG_IBPROG_MASK);
    DL_ADC12_initSingleSample(
        ADC0, adc_samples ? DL_ADC12_REPEAT_MODE_ENABLED : DL_ADC12_REPEAT_MODE_DISABLED,
        DL_ADC12_SAMPLING_SOURCE_AUTO, DL_ADC12_TRIG_SRC_SOFTWARE,
        DL_ADC12_SAMP_CONV_RES_12_BIT, DL_ADC12_SAMP_CONV_DATA_FORMAT_UNSIGNED);
    if (adc_samples) {
        DL_ADC12_enableFIFO(ADC0);
        DL_ADC12_setDMASamplesCnt(ADC0, 1); //single channel channel repeat, 1 32-bit sample per transfer
        DL_ADC12_enableDMATrigger(ADC0, DL_ADC12_DMA_MEM1_RESULT_LOADED);
        /* Enable ADC12 interrupt */
        DL_ADC12_clearInterruptStatus(ADC0, (DL_ADC12_INTERRUPT_DMA_DONE |
                                             DL_ADC12_INTERRUPT_UNDERFLOW));
        DL_ADC12_enableInterrupt(ADC0, (DL_ADC12_INTERRUPT_DMA_DONE |
                                        DL_ADC12_INTERRUPT_UNDERFLOW));
        DL_DMA_disableChannel(DMA, DMA_CH0_SEL);
        DL_DMA_initChannel(DMA, DMA_CH0_SEL, (DL_DMA_Config *) &gDMA_CH0Config);
        /* Configure DMA source, destination and size */
        DL_DMA_setSrcAddr(DMA, DMA_CH0_SEL,
                          (uint32_t) DL_ADC12_getFIFOAddress(ADC0));
        DL_DMA_setDestAddr(DMA, DMA_CH0_SEL, (uint32_t)gADCSamples);
        /* When FIFO is enabled 2 samples are compacted in a single word */
        DL_DMA_setTransferSize(DMA, DMA_CH0_SEL, adc_samples / 2);
        DL_DMA_enableChannel(DMA, DMA_CH0_SEL);
        DL_ADC12_enableDMA(ADC0);
    } else {
        /* Enable ADC12 interrupt */
        DL_ADC12_clearInterruptStatus(ADC0, DL_ADC12_INTERRUPT_MEM0_RESULT_LOADED);
        DL_ADC12_enableInterrupt(ADC0, DL_ADC12_INTERRUPT_MEM0_RESULT_LOADED);
    }
    gCheckADC = false;
    gADCError = 0;
    DL_ADC12_enableConversions(ADC0);
    /* Setup interrupts on device */
    NVIC_EnableIRQ(ADC0_INT_IRQn);
    DL_ADC12_startConversion(ADC0);

    while (DL_ADC12_REFERENCE_VOLTAGE_INTREF == vrefSource &&
           DL_ADC12_STATUS_REFERENCE_READY !=
           (DL_ADC12_getStatus(ADC0) & DL_ADC12_STATUS_REFERENCE_READY)) {
        delay_cycles(5 * 32);
    }
    // if (adc_samples) {
    //     while (DL_ADC12_STATUS_CONVERSION_ACTIVE !=
    //            (DL_ADC12_getStatus(ADC0) & DL_ADC12_STATUS_CONVERSION_ACTIVE)) {
    //         delay_cycles(1);
    //     }
    //     DL_ADC12_stopConversion(ADC0);
    // }

    uint16_t remain_last = DL_DMA_getTransferSize(DMA, DMA_CH0_SEL);
    uint16_t timeout = 20;
    do {
        __WFE();
        if (adc_samples) {
            uint16_t remain = DL_DMA_getTransferSize(DMA, DMA_CH0_SEL);
            if (0 == remain) {
                break;
            }
            if (remain_last == remain) {
                timeout--;
            }
            remain_last = remain;
        } else {
            delay_cycles(1);
        }
    } while (!(gCheckADC || gADCError || 0 == timeout));
    NVIC_DisableIRQ(ADC0_INT_IRQn);

    if (0 == timeout) {
        printf("ADC timeout");
    }
    if (gADCError) {
        printf("interrupt_flag: %08x", gADCError);
        return 0;
    }

    if (adc_samples) {
        uint16_t u16Counter;
        for (u16Counter = 0; u16Counter < adc_samples; u16Counter++) {
            u32AdcSum += gADCSamples[u16Counter];
            printf("gADCSamples[%u]=0x%04x", u16Counter, gADCSamples[u16Counter]);
        }
        u32AdcSum >>= added_bits;
    } else {
        u32AdcSum = DL_ADC12_getMemResult(ADC0, DL_ADC12_MEM_IDX_0);
    }
    DL_ADC12_disablePower(ADC0);
    return u32AdcSum;
}

void Driver_ADCInitAndSamplingMulti(uint8_t total_channel, const uint32_t *adcChannel,
                                    const uint32_t *vrefSource, uint16_t added_bits, uint32_t *results) {
    const uint8_t adc_multi_ch_start_ch = 0;
    uint8_t adjust_total_channel = total_channel;
    uint32_t u32AdcSum = 0;
    uint16_t adc_samples = 0;

    DL_ADC12_reset(ADC0);
    DL_ADC12_enablePower(ADC0);
    while (!DL_ADC12_isPowerEnabled(ADC0)) {
        delay_cycles(5 * 32);
    }
    // DL_ADC12_disableConversions(ADC0);
    DL_ADC12_setClockConfig(ADC0, (DL_ADC12_ClockConfig *) &gADC12_0ClockConfig);

    uint8_t ch = 0;
    while (ch < total_channel) {
        uint32_t stime = DL_ADC12_REFERENCE_VOLTAGE_VDDA == vrefSource[ch] ?
                         DL_ADC12_SAMPLE_TIMER_SOURCE_SCOMP0 : DL_ADC12_SAMPLE_TIMER_SOURCE_SCOMP1;
        DL_ADC12_configConversionMem(
            ADC0, DL_ADC12_MEM_IDX_0 + adc_multi_ch_start_ch + ch,
            adcChannel[ch], vrefSource[ch],
            stime,
            added_bits ? DL_ADC12_AVERAGING_MODE_ENABLED : DL_ADC12_AVERAGING_MODE_DISABLED,
            DL_ADC12_BURN_OUT_SOURCE_DISABLED, DL_ADC12_TRIGGER_MODE_AUTO_NEXT,
            DL_ADC12_WINDOWS_COMP_MODE_DISABLED);
        ch++;
    }
    if (added_bits) {
        uint32_t hw_avg_numerator;
        uint32_t hw_avg_denominator;
        if (added_bits > 3) {
            hw_avg_numerator = ADC12_CTL1_AVGN_AVG_128;
            hw_avg_denominator = ADC12_CTL1_AVGD_SHIFT3;
            added_bits -= 3;
            adc_samples = 1 << (added_bits * 2 - 1);
        } else {
            hw_avg_numerator = (added_bits << (1 + ADC12_CTL1_AVGN_OFS)) & ADC12_CTL1_AVGN_MASK;
            hw_avg_denominator = (added_bits << ADC12_CTL1_AVGD_OFS) & ADC12_CTL1_AVGD_MASK;
            added_bits = 0;
        }
        printf("added_bits: %d, hw_avg_numerator: 0x%08x, hw_avg_denominator: 0x%08x",
                              added_bits, hw_avg_numerator, hw_avg_denominator);
        DL_ADC12_configHwAverage(ADC0, hw_avg_numerator, hw_avg_denominator);
    }
    DL_ADC12_setPowerDownMode(ADC0, DL_ADC12_POWER_DOWN_MODE_MANUAL);
    DL_ADC12_setSampleTime0(ADC0, ADC_SAMPLE_TIME);
    DL_ADC12_setSampleTime1(ADC0, ADC_SAMPLE_TIME);
    DL_Common_updateReg(&ADC0->ULLMEM.REFCFG,
                        ADC12_REFCFG_REFEN_ENABLE | ADC12_REFCFG_REFVSEL_V1P4,
                        ADC12_REFCFG_REFEN_MASK | ADC12_REFCFG_REFVSEL_MASK | ADC12_REFCFG_IBPROG_MASK);
    if (added_bits || total_channel > 4) {
        if (total_channel & 1) {
            printf("Adjust channel, >4 and odd");
            //When using DMA, the total channel should not be odd number, use duplicate last channel
            adjust_total_channel = total_channel + 1;
            ch = total_channel - 1;
            uint32_t stime = DL_ADC12_REFERENCE_VOLTAGE_VDDA == vrefSource[ch] ?
                             DL_ADC12_SAMPLE_TIMER_SOURCE_SCOMP0 : DL_ADC12_SAMPLE_TIMER_SOURCE_SCOMP1;
            DL_ADC12_configConversionMem(
                ADC0, DL_ADC12_MEM_IDX_0 + adc_multi_ch_start_ch + total_channel,
                adcChannel[ch], vrefSource[ch],
                stime,
                added_bits ? DL_ADC12_AVERAGING_MODE_ENABLED : DL_ADC12_AVERAGING_MODE_DISABLED,
                DL_ADC12_BURN_OUT_SOURCE_DISABLED, DL_ADC12_TRIGGER_MODE_AUTO_NEXT,
                DL_ADC12_WINDOWS_COMP_MODE_DISABLED);
        }
        if (0 == added_bits) {
            adc_samples = 1;
        }
        for (uint16_t i = 0; i < adc_samples * adjust_total_channel; i++) {
            gADCSamples[i] = 0;
        }
        DL_ADC12_enableFIFO(ADC0);
        DL_ADC12_setDMASamplesCnt(ADC0, 2); //DL_ADC12_DMA_MEM1_RESULT_LOADED, 1 32-bit sample per transfer
        DL_ADC12_enableDMATrigger(ADC0, DL_ADC12_DMA_MEM3_RESULT_LOADED);
        /* Enable ADC12 interrupt */
        DL_ADC12_clearInterruptStatus(ADC0, (DL_ADC12_INTERRUPT_DMA_DONE |
                                             DL_ADC12_INTERRUPT_OVERFLOW |
                                             DL_ADC12_INTERRUPT_TRIG_OVF |
                                             DL_ADC12_INTERRUPT_UNDERFLOW));
        DL_ADC12_enableInterrupt(ADC0, (DL_ADC12_INTERRUPT_DMA_DONE |
                                        DL_ADC12_INTERRUPT_OVERFLOW |
                                        DL_ADC12_INTERRUPT_TRIG_OVF |
                                        DL_ADC12_INTERRUPT_UNDERFLOW));
        DL_DMA_disableChannel(DMA, DMA_CH0_SEL);
        DL_DMA_initChannel(DMA, DMA_CH0_SEL, (DL_DMA_Config *) &gDMA_CH0Config);
        /* Configure DMA source, destination and size */
        DL_DMA_setSrcAddr(DMA, DMA_CH0_SEL,
                          (uint32_t) DL_ADC12_getFIFOAddress(ADC0));
        DL_DMA_setDestAddr(DMA, DMA_CH0_SEL, (uint32_t)gADCSamples);
        /* When FIFO is enabled 2 samples are compacted in a single word, adc_samples has already considered this */
        DL_DMA_setTransferSize(DMA, DMA_CH0_SEL, adc_samples * adjust_total_channel / 2);
        DL_DMA_enableChannel(DMA, DMA_CH0_SEL);
        DL_ADC12_enableDMA(ADC0);
    } else {
        /* Enable ADC12 interrupt */
        uint32_t int_mask = 1 << ((ADC12_INT_EVENT0_IMASK_MEMRESIFG0_OFS +
                                   adc_multi_ch_start_ch) +
                                  adjust_total_channel - 1);
        DL_ADC12_clearInterruptStatus(ADC0, int_mask);
        DL_ADC12_enableInterrupt(ADC0, int_mask);
    }
    DL_ADC12_initSeqSample(
        ADC0, added_bits ? ADC12_CTL1_CONSEQ_REPEATSEQUENCE : ADC12_CTL1_CONSEQ_SEQUENCE,
        DL_ADC12_SAMPLING_SOURCE_AUTO, DL_ADC12_TRIG_SRC_SOFTWARE,
        ((DL_ADC12_MEM_IDX_0 + adc_multi_ch_start_ch) << ADC12_CTL2_STARTADD_OFS) & ADC12_CTL2_STARTADD_MASK,
        ((DL_ADC12_MEM_IDX_0 + adc_multi_ch_start_ch + adjust_total_channel) << ADC12_CTL2_ENDADD_OFS) & ADC12_CTL2_ENDADD_MASK,
        DL_ADC12_SAMP_CONV_RES_12_BIT, DL_ADC12_SAMP_CONV_DATA_FORMAT_UNSIGNED);
    gCheckADC = false;
    gADCError = 0;
    DL_ADC12_enableConversions(ADC0);
    /* Setup interrupts on device */
    NVIC_EnableIRQ(ADC0_INT_IRQn);
    DL_ADC12_startConversion(ADC0);

    while (DL_ADC12_STATUS_REFERENCE_READY !=
           (DL_ADC12_getStatus(ADC0) & DL_ADC12_STATUS_REFERENCE_READY)) {
        delay_cycles(5 * 32);
        printf("wait ref ready");
    }
    // if (adc_samples) {
    //     while (DL_ADC12_STATUS_CONVERSION_ACTIVE !=
    //            (DL_ADC12_getStatus(ADC0) & DL_ADC12_STATUS_CONVERSION_ACTIVE)) {
    //         delay_cycles(1);
    //     }
    //     DL_ADC12_stopConversion(ADC0);
    // }

    uint16_t remain_last = 0;
    uint16_t timeout = 10 * adjust_total_channel;
    do {
        printf("wait ADC event");
        __WFE();
        if (adc_samples) {
            uint16_t remain = DL_DMA_getTransferSize(DMA, DMA_CH0_SEL);
            if (0 == remain) {
                break;
            }
            if (remain_last == remain) {
                printf("ADC timeout: %u, remain %u", timeout, remain);
                timeout--;
            }
            remain_last = remain;
        } else {
            delay_cycles(50);
            timeout--;
        }
    } while (!(gCheckADC || gADCError || 0 == timeout));
    NVIC_DisableIRQ(ADC0_INT_IRQn);

    if (0 == timeout) {
        printf("ADC timeout");
    }
    if (gADCError) {
        printf("interrupt_flag: %08x", gADCError);
        return;
    }

    if (adc_samples) {
        printf("u16_arr");
        for (uint16_t i = 0; i < adc_samples * adjust_total_channel; i++) {
            printf("gADCSamples[%u]=0x%04x", i, gADCSamples[i]);
        }
    }

    printf("channel-specific");
    for (ch = 0; ch < total_channel; ch++) {
        if (adc_samples) {
            uint16_t u16Counter;
            u32AdcSum = 0;
            for (u16Counter = 0; u16Counter < adc_samples; u16Counter++) {
                uint16_t idx = u16Counter * adjust_total_channel + ch;
                printf("ch=%u, cnt=%u, gADCSamples[%u]=0x%04x", ch, u16Counter, idx, gADCSamples[idx]);
                u32AdcSum += (uint32_t)gADCSamples[idx];
            }
            results[ch] = u32AdcSum >> added_bits;
        } else {
            results[ch] = DL_ADC12_getMemResult(ADC0, DL_ADC12_MEM_IDX_0 + adc_multi_ch_start_ch + ch);
        }
    }
    DL_ADC12_disablePower(ADC0);
}

uint8_t max_ch = 4;    //DMA limitation: channel must be even number
uint8_t extra_bits = 0;
static void dump_adcs(void) {
    struct {
        const char *desc;
        uint32_t channel;
        uint32_t vrefSource;
    }
    const adc_meas [] = {
//      {"FIXED_LENGTH_TO______END", ADC_CHANNEL, ADC_REF_SOURCE}
        {"M0 core Temp", DL_ADC12_INPUT_CHAN_11, DL_ADC12_REFERENCE_VOLTAGE_INTREF},
        {"OPA0 int_out", DL_ADC12_INPUT_CHAN_12, DL_ADC12_REFERENCE_VOLTAGE_VDDA},
        {"OPA1 int_out", DL_ADC12_INPUT_CHAN_13, DL_ADC12_REFERENCE_VOLTAGE_VDDA},
        {"1/3 VDDA", DL_ADC12_INPUT_CHAN_15, DL_ADC12_REFERENCE_VOLTAGE_INTREF},
        {"Ext NTC temp", MEASURE_TEMPERATURE_NTC_ADC_CH, DL_ADC12_REFERENCE_VOLTAGE_VDDA},
#if defined(FRANKEN_SYSTEM) || defined(PROTO1_BOARD)
        {"GPAMP int_out", MEASURE_VCELL_GAMP_BUF_ADC_CH, DL_ADC12_REFERENCE_VOLTAGE_INTREF},
        {"VCELL direct", MEASURE_VCELL_ADC_CH, DL_ADC12_REFERENCE_VOLTAGE_INTREF},
#else
        {"OPA0 P0 in", DL_ADC12_INPUT_CHAN_2, DL_ADC12_REFERENCE_VOLTAGE_VDDA},
        {"OPA0 N0 in", DL_ADC12_INPUT_CHAN_3, DL_ADC12_REFERENCE_VOLTAGE_VDDA},
#endif
    };

#if defined(GPIO_REF_PORT) && defined(GPIO_REF_PIN)
    DL_GPIO_setPins(GPIO_REF_PORT, GPIO_REF_PIN);
    delay_cycles(300);
#endif
    printf("\nChannel name \t\tVoltage\t\tRaw sum\t\tReference");
    for (uint8_t i = 0; i < _itemsof(adc_meas); i++) {
        uint32_t sum = 0;
        sum = Driver_ADCInitAndSampling(adc_meas[i].channel,
                                        adc_meas[i].vrefSource,
                                        ADC_OVERSAMPLE_EXTRA_BITS_DEFAULT);
        printf("%s \t\t%4dmV\t\t%9d \t%s",
                              adc_meas[i].desc,
                              Driver_ADC_val_to_mV(sum, ADC_OVERSAMPLE_EXTRA_BITS_DEFAULT, adc_meas[i].vrefSource),
                              sum,
                              DL_ADC12_REFERENCE_VOLTAGE_VDDA == adc_meas[i].vrefSource ?
                              "VDDA, nominal 1.8V, see '1/3 VDDA' actual value" :
                              "INTREF, nominal 1.4V");
    }

    printf(">>multi-channel<<");
    uint32_t adc_raw[_itemsof(adc_meas)] = {0};
    uint32_t adc_channel[_itemsof(adc_meas)] = {0};
    uint32_t adc_ref[_itemsof(adc_meas)] = {0};
    if (max_ch > _itemsof(adc_meas) ||
        0 == max_ch) {
        max_ch = _itemsof(adc_meas);
    }
    if (extra_bits > ADC_OVERSAMPLE_EXTRA_BITS_MAX) {
        extra_bits = ADC_OVERSAMPLE_EXTRA_BITS_MAX;
    }
    for (uint8_t ch = 0; ch < max_ch; ch++) {
        adc_channel[ch] = adc_meas[ch].channel;
        adc_ref[ch] = adc_meas[ch].vrefSource;
    }
    Driver_ADCInitAndSamplingMulti(max_ch, adc_channel, adc_ref, extra_bits, adc_raw);
    for (uint8_t ch = 0; ch < max_ch; ch++) {
        printf("%s \t\t%4dmV\t\t%9d \t%s",
                              adc_meas[ch].desc,
                              Driver_ADC_val_to_mV(
                                  adc_raw[ch],
                                  extra_bits,
                                  adc_meas[ch].vrefSource),
                              adc_raw[ch],
                              DL_ADC12_REFERENCE_VOLTAGE_VDDA == adc_meas[ch].vrefSource ?
                              "VDDA, nominal 1.8V, see '1/3 VDDA' actual value" :
                              "INTREF, nominal 1.4V");
    }

#if defined(GPIO_REF_PORT) && defined(GPIO_REF_PIN)
    DL_GPIO_clearPins(GPIO_REF_PORT, GPIO_REF_PIN);
#endif
}

  • Hi Tiger,

    Does it mean that in non-FIFO mode, the max configurable channel is 4

    Yes, max channel is 4, if you want to use more channel, you should change the configuration of the MEMCTL.

    if we use FIFO with DMA

    When you use FIFO, the MEMRES0:3 are combined as a FIFO, so the data in RES0:3 will be the FIFO data, even if you only use MEMRES0:1, and MEMRES1:2 will still have the data due to the FIFO.

    What is the "suitable" value?

    I suggest you do several test based on each parameter setting for DMA.

    My understanding for this: It means "Number of ADC converted samples to be transferred on an ADC conversion"

    Here is a example I used to test: SAMPCNT=2, DMASZx=4 (TransferSize); it will need 2 conversions to complete a DMA transfer.

    What are the function parameters should be use for DL_ADC12_setDMASamplesCnt() and DL_DMA_setTransferSize() ?

    I suggest you to find the definition of the API functions, and you can see the parameters required. Also, in the source code, you can learn how it process.

    I attached our code in this context.

    Sorry I have not much energy to review the code. Hope the other clarifications I post here make some help.

    Also, some typos and/or unclear things in the current reference manual slau847c:

    1. I assume "ASC" is "ad-hoc single conversion"

    2. VREF->CTL0 is control VREF peripheral module, whether it output a reference voltage to other module. However, ADC0->REFCFG->REFVSEL seems to configure the VREF output, I suggest you take a test and see whether it will make imapct on VREF output to others module.

    3.The reference voltage is for all channels. And if you switch the reference, I am wondering the application of you described. As for this, user should change the VRSE to meet the demands of CONVCLK.

    B.R.

    Sal

  • Hi Sal,

    Thanks for the reply. However, the suggestions were given by you has already tried by me, that is why I ask those questions. Actually I want something more beyond the reference manual because current manual doesn't cover the case that I encounter.

    For example, if I have total 8 channels, and I want 8 rounds (means 8 samples per channel) of cycling, what should be sample count, DMA transfer size, and DMA trigger setting? Please give an example of this use case, or clearly describe why this case isn't supported.

    What is ad-hoc single conversion? I didn't see any explanation on this term. Only two occurrence of the term "ad-hoc" and don't have any explanation.

     

    Bests,

  • Hi Tiger,

    Here is my suggestion for the case:

    we can only use 4 channels and 4 MEMRES to save the conversion result simultaneously. So, you should devide them into two groups.

    For each group, there will be 8 conversions for 4 channels, so you should define SAMPCNT=2, DMASZx=16, DMA trigger is MEMRES3 loaded. It will need 8 conversions to achieve a DMA transfer. After DMA done, then you should re-modify the ADC congiguration to for another group.

    Actually I have not use ad-hoc single conersion, It requires some time to figure out what it used for and whether we should add more clarification about it. Then I can update it to you.

    B.R.

    Sal