Hi everyone,
I am trying to do an ADC DMA reading to RAM buffer. I need to start DMA ADC conversion and fill my RAM buffer with 100 values. The point is to collect 100 audio input values to make calculations with them.
I found an example code of demo dma adc, but here only one value is saved.
I have tried to increase g_AdcConvResult buffer to 100 -> g_AdcConvResult[100] and change Dma transfer width sizeof(uint32_t) to 100*sizeof(uint32_t), but no success.
Could you please take a look what I have to modify in this demo code?
dma_handle_t g_DmaHandleStruct; /* Handler structure for using DMA. */
uint32_t g_AdcConvResult[1]; /* Keep the ADC conversion resulut moved from ADC data register by DMA. */
volatile bool g_DmaTransferDoneFlag; /* Flag of DMA transfer done trigger by ADC conversion. */
/* DMA descripter table used for ping-pong mode. */
DMA_ALLOCATE_LINK_DESCRIPTORS(s_dma_table, 2U);
const uint32_t g_XferConfig =
DMA_CHANNEL_XFER(true, /* Reload link descriptor after current exhaust, */
true, /* Clear trigger status. */
true, /* Enable interruptA. */
false, /* Not enable interruptB. */
sizeof(uint32_t), /* Dma transfer width. */
kDMA_AddressInterleave0xWidth, /* Dma source address no interleave */
kDMA_AddressInterleave0xWidth, /* Dma destination address no interleave */
sizeof(uint32_t) /* Dma transfer byte. */
);
const uint32_t g_Adc_12bitFullRange = 4096U;
/*******************************************************************************
* Code
******************************************************************************/
static void ADC_ClockPower_Configuration(void)
{
/* SYSCON power. */
POWER_DisablePD(kPDRUNCFG_PD_ADC0); /* Power on the ADC converter. */
POWER_DisablePD(kPDRUNCFG_PD_VD7_ENA); /* Power on the analog power supply. */
POWER_DisablePD(kPDRUNCFG_PD_VREFP_SW); /* Power on the reference voltage source. */
POWER_DisablePD(kPDRUNCFG_PD_TEMPS); /* Power on the temperature sensor. */
CLOCK_EnableClock(kCLOCK_Adc0); /* SYSCON->AHBCLKCTRL[0] |= SYSCON_AHBCLKCTRL_ADC0_MASK; */
}
/*!
* @brief Main function
*/
int main(void)
{
/* Initialize board hardware. */
/* attach 12 MHz clock to FLEXCOMM0 (debug console) */
CLOCK_AttachClk(BOARD_DEBUG_UART_CLK_ATTACH);
BOARD_InitBootPins();
BOARD_InitBootClocks();
BOARD_InitDebugConsole();
/* Enable the power and clock for ADC. */
ADC_ClockPower_Configuration();
PRINTF("ADC DMA example.\r\n");
/* Configure peripherals. */
NVIC_EnableIRQ(DMA0_IRQn);
DMA_Configfuation();
#if !(defined(FSL_FEATURE_ADC_HAS_NO_CALIB_FUNC) && FSL_FEATURE_ADC_HAS_NO_CALIB_FUNC)
uint32_t frequency = 0U;
/* Calibration after power up. */
#if defined(FSL_FEATURE_ADC_HAS_CALIB_REG) && FSL_FEATURE_ADC_HAS_CALIB_REG
ADC0->CTRL |= ADC_CTRL_BYPASSCAL_MASK;
frequency = CLOCK_GetFreq(kCLOCK_BusClk);
if (true == ADC_DoOffsetCalibration(ADC0, frequency))
#else
#if defined(SYSCON_ADCCLKDIV_DIV_MASK)
frequency = CLOCK_GetFreq(DEMO_ADC_CLOCK_SOURCE) / CLOCK_GetClkDivider(kCLOCK_DivAdcClk);
#else
frequency = CLOCK_GetFreq(DEMO_ADC_CLOCK_SOURCE);
#endif /* SYSCON_ADCCLKDIV_DIV_MASK */
if (true == ADC_DoSelfCalibration(ADC0, frequency))
#endif /* FSL_FEATURE_ADC_HAS_CALIB_REG */
{
PRINTF("ADC Calibration Done.\r\n");
}
else
{
PRINTF("ADC Calibration Failed.\r\n");
}
#endif /* FSL_FEATURE_ADC_HAS_NO_CALIB_FUNC */
ADC_Configuration();
PRINTF("Configuration Done.\r\n");
#if defined(FSL_FEATURE_ADC_HAS_CTRL_RESOL) & FSL_FEATURE_ADC_HAS_CTRL_RESOL
PRINTF("ADC Full Range: %d\r\n", g_Adc_12bitFullRange);
#endif /* FSL_FEATURE_ADC_HAS_CTRL_RESOL */
PRINTF("Type in any key to trigger the conversion ...\r\n");
while (1)
{
/* Get the input from terminal and trigger the converter by software. */
GETCHAR();
g_DmaTransferDoneFlag = false;
ADC_DoSoftwareTriggerConvSeqA(ADC0); /* Trigger the ADC and start the conversion. */
/* Wait for the converter & transfer to be done. */
while (!g_DmaTransferDoneFlag)
{
}
PRINTF("Conversion word : 0x%X\r\n", g_AdcConvResult[0]);
PRINTF("Conversion value: %d\r\n", (g_AdcConvResult[0] & ADC_DAT_RESULT_MASK) >> ADC_DAT_RESULT_SHIFT);
PRINTF("\r\n");
}
}
static void ADC_Configuration(void)
{
adc_config_t adcConfigStruct;
adc_conv_seq_config_t adcConvSeqConfigStruct;
adc_result_info_t adcResultInfoStruct;
/* Configure the converter. */
#if defined(FSL_FEATURE_ADC_HAS_CTRL_ASYNMODE) & FSL_FEATURE_ADC_HAS_CTRL_ASYNMODE
adcConfigStruct.clockMode = kADC_ClockSynchronousMode; /* Using sync clock source. */
#endif /* FSL_FEATURE_ADC_HAS_CTRL_ASYNMODE */
adcConfigStruct.clockDividerNumber = 1U;
#if defined(FSL_FEATURE_ADC_HAS_CTRL_RESOL) & FSL_FEATURE_ADC_HAS_CTRL_RESOL
adcConfigStruct.resolution = kADC_Resolution12bit;
#endif /* FSL_FEATURE_ADC_HAS_CTRL_RESOL */
#if defined(FSL_FEATURE_ADC_HAS_CTRL_BYPASSCAL) & FSL_FEATURE_ADC_HAS_CTRL_BYPASSCAL
adcConfigStruct.enableBypassCalibration = false;
#endif /* FSL_FEATURE_ADC_HAS_CTRL_BYPASSCAL */
#if defined(FSL_FEATURE_ADC_HAS_CTRL_TSAMP) & FSL_FEATURE_ADC_HAS_CTRL_TSAMP
adcConfigStruct.sampleTimeNumber = 0U;
#endif /* FSL_FEATURE_ADC_HAS_CTRL_TSAMP */
#if defined(FSL_FEATURE_ADC_HAS_CTRL_LPWRMODE) & FSL_FEATURE_ADC_HAS_CTRL_LPWRMODE
adcConfigStruct.enableLowPowerMode = false;
#endif /* FSL_FEATURE_ADC_HAS_CTRL_LPWRMODE */
#if defined(FSL_FEATURE_ADC_HAS_TRIM_REG) & FSL_FEATURE_ADC_HAS_TRIM_REG
adcConfigStruct.voltageRange = kADC_HighVoltageRange;
#endif /* FSL_FEATURE_ADC_HAS_TRIM_REG */
ADC_Init(ADC0, &adcConfigStruct);
#if !(defined(FSL_FEATURE_ADC_HAS_NO_INSEL) && FSL_FEATURE_ADC_HAS_NO_INSEL)
/* Use the temperature sensor input to channel 0. */
ADC_EnableTemperatureSensor(ADC0, true);
#endif /* FSL_FEATURE_ADC_HAS_NO_INSEL. */
/* Enable channel 4U's conversion in Sequence A. */
adcConvSeqConfigStruct.channelMask =
(1U << 4U); /* Includes channel 4U. */
adcConvSeqConfigStruct.triggerMask = 0U;
adcConvSeqConfigStruct.triggerPolarity = kADC_TriggerPolarityPositiveEdge;
adcConvSeqConfigStruct.enableSingleStep = false;
adcConvSeqConfigStruct.enableSyncBypass = false;
adcConvSeqConfigStruct.interruptMode = kADC_InterruptForEachSequence; /* Enable the interrupt/DMA trigger. */
ADC_SetConvSeqAConfig(ADC0, &adcConvSeqConfigStruct);
ADC_EnableConvSeqA(ADC0, true); /* Enable the conversion sequence A. */
/* Clear the result register. */
ADC_DoSoftwareTriggerConvSeqA(ADC0);
while (!ADC_GetChannelConversionResult(ADC0, 4U, &adcResultInfoStruct))
{
}
ADC_GetConvSeqAGlobalConversionResult(ADC0, &adcResultInfoStruct);
/* Enable DMA trigger when Seq A conversion done. */
ADC_EnableInterrupts(ADC0, kADC_ConvSeqAInterruptEnable);
}
/* Software ISR for DMA transfer done. */
void ADC_DMA_Callback(dma_handle_t *handle, void *param, bool transferDone, uint32_t tcds)
{
if (true == transferDone)
{
g_DmaTransferDoneFlag = true;
}
}
static void DMA_Configfuation(void)
{
dma_channel_config_t dmaChannelConfigStruct;
dma_channel_trigger_t dmaChannelTriggerStruct;
/* Init DMA. This must be set before INPUTMUX_Init() for DMA peripheral reset will clear the mux setting. */
DMA_Init(DMA0);
/* Configure DMAMUX. */
INPUTMUX_Init(INPUTMUX);
INPUTMUX_AttachSignal(INPUTMUX, 0U, kINPUTMUX_Adc0SeqaIrqToDma);
/* Configure DMA. */
DMA_EnableChannel(DMA0, 0U);
DMA_CreateHandle(&g_DmaHandleStruct, DMA0, 0U);
DMA_SetCallback(&g_DmaHandleStruct, ADC_DMA_Callback, NULL);
/*
* Configure the DMA trigger:
* The DATAVALID of ADC will trigger the interrupt. This signal is also for thie DMA triger, which is changed 0 ->
* 1.
*/
dmaChannelTriggerStruct.burst = kDMA_EdgeBurstTransfer1;
dmaChannelTriggerStruct.type = kDMA_RisingEdgeTrigger;
dmaChannelTriggerStruct.wrap = kDMA_NoWrap;
/* Prepare and submit the transfer. */
DMA_PrepareChannelTransfer(&dmaChannelConfigStruct, /* DMA channel transfer configurationstructure. */
(void *)(uint32_t)(&(ADC0->DAT[4U])), /* DMA transfer source address. */
(void *)g_AdcConvResult, /* DMA transfer destination address. */
g_XferConfig, /* Xfer configuration */
kDMA_MemoryToMemory, /* DMA transfer type. */
&dmaChannelTriggerStruct, /* DMA channel trigger configurations. */
(dma_descriptor_t *)&(s_dma_table[0]) /* Address of next descriptor. */
);
DMA_SubmitChannelTransfer(&g_DmaHandleStruct, &dmaChannelConfigStruct);
/* Set two DMA descripters to use ping-pong mode. */
DMA_SetupDescriptor(&(s_dma_table[0]), g_XferConfig, (void *)(uint32_t)(&(ADC0->DAT[4U])), (void *)g_AdcConvResult,
(dma_descriptor_t *)&(s_dma_table[1]));
DMA_SetupDescriptor(&(s_dma_table[1]), g_XferConfig, (void *)(uint32_t)(&(ADC0->DAT[4U])), (void *)g_AdcConvResult,
(dma_descriptor_t *)&(s_dma_table[0]));
}