Why does ADC Flexible Scan Mode work on MK64 but not on MK10?

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

Why does ADC Flexible Scan Mode work on MK64 but not on MK10?

854 Views
m4l490n
Contributor V

@jorge_a_vazquez @danielchen sorry for tagging you directly but I need urgent help to solve this. I need to make this work for my job since I have a project starting.

 

I got the code from Using DMA to Emulate ADC Flexible Scan Mode with SDK 2.x to try to implement that on my end product based on an MK10 but it is not working correctly.

I have modified the code to have DMA channel 0 as the DMA-COCO and DMA channel 1 as the SRAM to ADC0_SC1A. Also, I altered the order of execution of the various sections to match what the code does when using the config tools.

So I have the following on main.c:

 

 

 

int main(void)
{
    /* Init board hardware. */
    BOARD_InitBootPins();
    BOARD_InitBootClocks();
    /* Init FSL debug console. */
    BOARD_InitDebugConsole();

    /****************************************
     * DMA Config
     ****************************************/
    edma_config_t userConfig= {
      .enableContinuousLinkMode = false,
      .enableHaltOnError = false,
      .enableRoundRobinArbitration = false,
      .enableDebugMode = false
    };

    /* Configure DMAMUX */
    DMAMUX_Init(DMA_DMAMUX_BASEADDR);
    EDMA_Init(DMA_DMA_BASEADDR, &userConfig);

    /* Channel adc0_coco initialization */
    /* Set the source kDmaRequestMux0ADC0 request in the DMAMUX */
    DMAMUX_SetSource(DMA_DMAMUX_BASEADDR, DMA_ADC0_COCO_DMA_CHANNEL, DMA_ADC0_COCO_DMA_REQUEST);
    /* Enable the channel 0 in the DMAMUX */
    DMAMUX_EnableChannel(DMA_DMAMUX_BASEADDR, DMA_ADC0_COCO_DMA_CHANNEL);
    /* Create the eDMA dma_adc0_coco_Handle handle */
    EDMA_CreateHandle(&dma_adc0_coco_Handle, DMA_DMA_BASEADDR, DMA_ADC0_COCO_DMA_CHANNEL);
    EDMA_SetCallback(&dma_adc0_coco_Handle, adc0_val_dma_transfer_done, NULL);

    /* Channel adc0_channel initialization */
    /* Set the source kDmaRequestMux0AlwaysOn54 request in the DMAMUX */
    DMAMUX_SetSource(DMA_DMAMUX_BASEADDR, DMA_ADC0_CHANNEL_DMA_CHANNEL, DMA_ADC0_CHANNEL_DMA_REQUEST);
    /* Enable the channel 1 in the DMAMUX */
    DMAMUX_EnableChannel(DMA_DMAMUX_BASEADDR, DMA_ADC0_CHANNEL_DMA_CHANNEL);
    /* Create the eDMA dma_adc0_channel_Handle handle */
    EDMA_CreateHandle(&dma_adc0_channel_Handle, DMA_DMA_BASEADDR, DMA_ADC0_CHANNEL_DMA_CHANNEL);
    EDMA_SetCallback(&dma_adc0_channel_Handle, adc0_channels_ready, NULL);



    /****************************************
     * ADC Config
     ****************************************/
    const adc16_channel_mux_mode_t adc0_muxMode = kADC16_ChannelMuxA;
    const adc16_hardware_average_mode_t adc0_hardwareAverageMode = kADC16_HardwareAverageCount32;
    adc16_config_t adc16ConfigStruct;
    /*
     * adc16ConfigStruct.referenceVoltageSource = kADC16_ReferenceVoltageSourceVref;
     * adc16ConfigStruct.clockSource = kADC16_ClockSourceAsynchronousClock;
     * adc16ConfigStruct.enableAsynchronousClock = true;
     * adc16ConfigStruct.clockDivider = kADC16_ClockDivider8;
     * adc16ConfigStruct.resolution = kADC16_ResolutionSE12Bit;
     * adc16ConfigStruct.longSampleMode = kADC16_LongSampleDisabled;
     * adc16ConfigStruct.enableHighSpeed = false;
     * adc16ConfigStruct.enableLowPower = false;
     * adc16ConfigStruct.enableContinuousConversion = false;
     */
    ADC16_GetDefaultConfig(&adc16ConfigStruct);
    ADC16_Init( ADC0, &adc16ConfigStruct);
    ADC16_EnableHardwareTrigger( ADC0, true);
    ADC16_SetHardwareAverage(ADC0, adc0_hardwareAverageMode);
    ADC16_SetChannelMuxMode(ADC0, adc0_muxMode);
    ADC16_DoAutoCalibration( ADC0 );
    ADC16_EnableDMA( ADC0, true);

    ADC16_SetChannelConfig(ADC0, 0, &adc0_channelsConfig[2]);



    /****************************************
     * LPTMR for ADC HW trigger Config
     ****************************************/
    lptmr_config_t lptmrConfig;
    /*
     * lptmrConfig.timerMode = kLPTMR_TimerModeTimeCounter;
     * lptmrConfig.pinSelect = kLPTMR_PinSelectInput_0;
     * lptmrConfig.pinPolarity = kLPTMR_PinPolarityActiveHigh;
     * lptmrConfig.enableFreeRunning = false;
     * lptmrConfig.bypassPrescaler = true;
     * lptmrConfig.prescalerClockSource = kLPTMR_PrescalerClock_1;
     * lptmrConfig.value = kLPTMR_Prescale_Glitch_0;
     */
    LPTMR_GetDefaultConfig(&lptmrConfig);
    lptmrConfig.bypassPrescaler = false;
    lptmrConfig.prescalerClockSource = kLPTMR_PrescalerClock_1;

    /* Initialize the LPTMR */
    LPTMR_Init(LPTMR0, &lptmrConfig);

    /* Set the LPTimer period */
    LPTMR_SetTimerPeriod( LPTMR0,USEC_TO_COUNT(200000, CLOCK_GetFreq(kCLOCK_LpoClk)));

    /* Configure SIM for ADC hw trigger source selection */
    SIM->SOPT7 |= 0x8EU;



    /****************************************
     * Application
     ****************************************/
    edma_transfer_config_t transferConfig_ch0;
    edma_transfer_config_t transferConfig_ch1;

    EDMA_PrepareTransfer(&transferConfig_ch0,   /* Prepare TCD for CH1 */
                         (uint32_t*) (ADC0_PERIPHERAL->R), /* Source Address (ADC0_RA) */
                         sizeof(uint32_t),      /* Source width (2 bytes) */
                         g_ADC0_resultBuffer,   /* Destination Address (Internal buffer)*/
                         sizeof(uint32_t),      /* Destination width (2 bytes) */
                         sizeof(uint32_t),      /* Bytes to transfer each minor loop (2 bytes) */
                         sizeof(uint32_t) * ADC0_CHANNELS * ADC0_NUM_OF_SAMPLES, /* Total of bytes to transfer (12*2 bytes) */
                         kEDMA_PeripheralToMemory); /* From ADC to Memory */
    /* Push TCD for CH1 into hardware TCD Register */
    EDMA_SubmitTransfer(&dma_adc0_coco_Handle, &transferConfig_ch0);

    EDMA_SetChannelLink(DMA_DMA_BASEADDR, DMA_ADC0_COCO_DMA_CHANNEL, kEDMA_MinorLink, DMA_ADC0_CHANNEL_DMA_CHANNEL);
    EDMA_SetChannelLink(DMA_DMA_BASEADDR, DMA_ADC0_COCO_DMA_CHANNEL, kEDMA_MajorLink, DMA_ADC0_CHANNEL_DMA_CHANNEL);

    EDMA_PrepareTransfer(&transferConfig_ch1,   /* Prepare TCD for CH0 */
                         g_ADC_mux,             /* Source Address (ADC channels array) */
                         sizeof(uint8_t),       /* Source width (1 bytes) */
                         (uint32_t*)(ADC0_PERIPHERAL->SC1),/* Destination Address (ADC_SC1A_ADCH)*/
                         sizeof(uint8_t),       /* Destination width (1 bytes) */
                         sizeof(uint8_t),       /* Bytes to transfer each minor loop (1 bytes) */
                         sizeof(uint8_t) * ADC0_CHANNELS,/* Total of bytes to transfer (3*1 bytes) */
                         kEDMA_MemoryToPeripheral);/* From ADC channels array to ADCH register */
    /* Push TCD for CH0 into hardware TCD Register */
    EDMA_SubmitTransfer(&dma_adc0_channel_Handle, &transferConfig_ch1);

    /* If transfer will continue it will need to adjust last source and destination */
    DMA0->TCD[DMA_ADC0_COCO_DMA_CHANNEL].DLAST_SGA = -sizeof(uint32_t) * ADC0_CHANNELS * ADC0_NUM_OF_SAMPLES;
    DMA0->TCD[DMA_ADC0_CHANNEL_DMA_CHANNEL].SLAST = -sizeof(uint8_t) * ADC0_CHANNELS;

    EDMA_StartTransfer(&dma_adc0_coco_Handle);


    /****************************************
     * Application
     ****************************************/

    PRINTF("\e[0m\n\n\n");
    PRINTF("┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓\n");
    PRINTF("┃      MK10DN512VLQ10 Started      ┃\n");
    PRINTF("┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛\n");

    if (kRCM_SourceWdog == RCM_GetPreviousResetSources(RCM))
    {
        PRINTF("\n\e[3;5;93mThe processor has been reset %u times by the WDOG\e[0m\n\n",
               WDOG_GetResetCount(WATCHDOG_PERIPHERAL));
    }

    /* Start the LPTimer */
    LPTMR_StartTimer(LPTMR0);

    uint8_t channel = 0;
    uint8_t sample = 0;
    PRINTF("\r\nCHANNEL_12\t VREFL_CH\t VREFH_CH\r\n--------\t --------\t --------\t\r\n");
    while (1)
    {
        if (adc0_sample_ready)
        {
            adc0_sample_ready = false;
            PRINTF("%d \t\t", g_ADC0_resultBuffer[sample][channel++]);
            PRINTF("%d \t\t", g_ADC0_resultBuffer[sample][channel++]);
            PRINTF("%d \t\t", g_ADC0_resultBuffer[sample][channel++]);
            PRINTF("\n");

            channel = 0;
            sample++;

            if (adc0_capture_done)
            {
                adc0_capture_done = false;
                sample = 0;
                PRINTF("\r\nFinished\r\n");
            }
        }
    }
    return 0;
}

 

 

 

 

When I run the code on the MK64 board it works flawlessly, with no issues at all. But when I use the code on my MK10 it presents a weird behavior.

I'm down to register level debug on trying to know what is going on and I have observed the following:

When debugging the code, the DMA register values for both projects are exactly the same when looking at the DMA peripheral for both. These are the DMA register values for both (simplified for CH0 and CH1 only):

RegisterValue
DMA-CR0x80
DMA-ERQ0x1
DMA-TCD0-SADDR0x4003b010
DMA-TCD1-SADDR0x20000000
DMA-TCD0-SOFF0x0
DMA-TCD1-SOFF0x1
DMA-TCD0-ATTR0x202
DMA-TCD1-ATTR0x0
DMA-TCD0-NBYTES-MLNO0x4
DMA-TCD1-NBYTES-MLNO1
DMA-TCD0-NBYTES-MLOFFNO0x4
DMA-TCD1-NBYTES-MLOFFNO0x1
DMA-TCD0-NBYTES-MLOFFYES0x4
DMA-TCD1-NBYTES-MLOFFYES0x1
DMA-TCD0-SLAST0x0
DMA-TCD1-SLAST0xfffffffd
DMA-TCD0-DADDR0x20000028
DMA-TCD1-DADDR0x4003b000
DMA-TCD0-OFF0x4
DMA-TCD1-OFF0x0
DMA-TCD0-CITER-ELINKNO0x820c
DMA-TCD1-CITER-ELINKNO0x3
DMA-TCD0-CITER-ELINKYES0x820c
DMA-TCD1-CITER-ELINKYES0x3
DMA-TCD0-DLASTSGA0xffffffd0
DMA-TCD1-DLASTSGA0x0
DMA-TCD0-CSR0x12a
DMA-TCD1-CSR0x0
DMA-TCD0-BITER-ELINKNO0x820c
DMA-TCD1-BITER-ELINKNO0x3
DMA-TCD0-BITER-ELINKYES0x820c
DMA-TCD1-BITER-ELINKYES0x3

 

 

But when I get to the part when the LPTMR is started to trigger the ADC, after executing LPTMR_StartTimer a change happens for the MK10. The DMA-TCD1-SADDR register changes from 0x20000000 to 0x20000002 and I don't know why.

Then immediately after executing uint8_t channel = 0; the DMA-INT register changes from 0x0 to 0x3 for no apparent reason and adc0_sample_ready as well as adc0_capture_done are immediately set to true on the MK10 and I see the following on the RAM buffer:

m4l490n_0-1614718913342.png

And I don't know why all the buffer has those values.

Could anyone please help me know what's going on? The code and configurations are exactly the same for both and it works just fine for the MK64 but not for the MK10.

0 Kudos
1 Reply

816 Views
jingpan
NXP TechSupport
NXP TechSupport

Hi,

Since I haven't K10D100M board, I tested jorge_a_vazquez's code on TWR-K60D100M. It could be used to verify K10 project. I copied his main.c directly. The demo can works fine. Since we can't find the difference between K10 and K64 DMA module, you can use the demo code directly too to speed up your project.

 

Regards,

Jing

0 Kudos