@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):
Register | Value |
DMA-CR | 0x80 |
DMA-ERQ | 0x1 |
DMA-TCD0-SADDR | 0x4003b010 |
DMA-TCD1-SADDR | 0x20000000 |
DMA-TCD0-SOFF | 0x0 |
DMA-TCD1-SOFF | 0x1 |
DMA-TCD0-ATTR | 0x202 |
DMA-TCD1-ATTR | 0x0 |
DMA-TCD0-NBYTES-MLNO | 0x4 |
DMA-TCD1-NBYTES-MLNO | 1 |
DMA-TCD0-NBYTES-MLOFFNO | 0x4 |
DMA-TCD1-NBYTES-MLOFFNO | 0x1 |
DMA-TCD0-NBYTES-MLOFFYES | 0x4 |
DMA-TCD1-NBYTES-MLOFFYES | 0x1 |
DMA-TCD0-SLAST | 0x0 |
DMA-TCD1-SLAST | 0xfffffffd |
DMA-TCD0-DADDR | 0x20000028 |
DMA-TCD1-DADDR | 0x4003b000 |
DMA-TCD0-OFF | 0x4 |
DMA-TCD1-OFF | 0x0 |
DMA-TCD0-CITER-ELINKNO | 0x820c |
DMA-TCD1-CITER-ELINKNO | 0x3 |
DMA-TCD0-CITER-ELINKYES | 0x820c |
DMA-TCD1-CITER-ELINKYES | 0x3 |
DMA-TCD0-DLASTSGA | 0xffffffd0 |
DMA-TCD1-DLASTSGA | 0x0 |
DMA-TCD0-CSR | 0x12a |
DMA-TCD1-CSR | 0x0 |
DMA-TCD0-BITER-ELINKNO | 0x820c |
DMA-TCD1-BITER-ELINKNO | 0x3 |
DMA-TCD0-BITER-ELINKYES | 0x820c |
DMA-TCD1-BITER-ELINKYES | 0x3 |
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:
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.
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