Hi !
I'm trying to configure the ADC1 to 7 ranks conversion and a GPDMA1 channel (0) in "Standard Request Mode" to transfer the ADC data into the memory.
First, I've configured the ADC without GPDMA channel, and it worked fine (Polling mode, no interrupts).
Then, I tried to configure the GPDMA channel, and got stuck on a situation that the GPDMA transfers only one byte of the data of the ADC, and it moves the data only on the first element of my memory buffer (destination of DMA not incrementing).
Notice that I do get a "TC" and "HT" interrupts and not getting any of the errors interrupts, I'll be glad to get some help with that.
Here's my code (using the LL_Drivers):
LL_DMA_LinkNodeTypeDef Node_GPDMA1_Channel0;
/* ADC data buffer */
__attribute__ ((aligned (32))) unsigned short pusAdcData[7];
/* GPDMA Clock enable */
LL_AHB1_GRP1_EnableClock(LL_AHB1_GRP1_PERIPH_GPDMA1);
/* ADC and DMA configurations */
static void MX_ADC1_Init(void)
{
/* USER CODE BEGIN ADC1_Init 0 */
LL_DMA_DisableChannel(GPDMA1, LL_DMA_CHANNEL_0);
/* USER CODE END ADC1_Init 0 */
LL_ADC_CommonInitTypeDef ADC_CommonInitStruct = {0};
LL_ADC_InitTypeDef ADC_InitStruct = {0};
LL_ADC_REG_InitTypeDef ADC_REG_InitStruct = {0};
LL_GPIO_InitTypeDef GPIO_InitStruct = {0};
LL_DMA_InitNodeTypeDef NodeConfig = {0};
LL_DMA_InitLinkedListTypeDef DMA_InitLinkedListStruct = {0};
LL_RCC_SetADCDACClockSource(LL_RCC_ADCDAC_CLKSOURCE_SYSCLK);
/* Peripheral clock enable */
LL_AHB2_GRP1_EnableClock(LL_AHB2_GRP1_PERIPH_ADC12);
LL_AHB2_GRP1_EnableClock(LL_AHB2_GRP1_PERIPH_GPIOA);
LL_AHB2_GRP1_EnableClock(LL_AHB2_GRP1_PERIPH_GPIOB);
/**ADC1 GPIO Configuration
PA3 ------> ADC1_IN8
PA5 ------> ADC1_IN10
PA4 ------> ADC1_IN9
PB1 ------> ADC1_IN16
PA2 ------> ADC1_IN7
PB2 ------> ADC1_IN17
PB0 ------> ADC1_IN15
*/
GPIO_InitStruct.Pin = LL_GPIO_PIN_3|LL_GPIO_PIN_5|LL_GPIO_PIN_4|LL_GPIO_PIN_2;
GPIO_InitStruct.Mode = LL_GPIO_MODE_ANALOG;
GPIO_InitStruct.Pull = LL_GPIO_PULL_NO;
LL_GPIO_Init(GPIOA, &GPIO_InitStruct);
GPIO_InitStruct.Pin = LL_GPIO_PIN_1|LL_GPIO_PIN_2|LL_GPIO_PIN_0;
GPIO_InitStruct.Mode = LL_GPIO_MODE_ANALOG;
GPIO_InitStruct.Pull = LL_GPIO_PULL_NO;
LL_GPIO_Init(GPIOB, &GPIO_InitStruct);
/* ADC1 DMA Init */
/* GPDMA1_REQUEST_ADC1 Init */
NodeConfig.DestAllocatedPort = LL_DMA_DEST_ALLOCATED_PORT1;
NodeConfig.DestHWordExchange = LL_DMA_DEST_HALFWORD_PRESERVE;
NodeConfig.DestByteExchange = LL_DMA_DEST_BYTE_PRESERVE;
NodeConfig.DestBurstLength = 1;
NodeConfig.DestIncMode = LL_DMA_DEST_INCREMENT;
NodeConfig.DestDataWidth = LL_DMA_DEST_DATAWIDTH_HALFWORD;
NodeConfig.SrcAllocatedPort = LL_DMA_SRC_ALLOCATED_PORT0;
NodeConfig.SrcByteExchange = LL_DMA_SRC_BYTE_PRESERVE;
NodeConfig.DataAlignment = LL_DMA_DATA_ALIGN_ZEROPADD;
NodeConfig.SrcBurstLength = 1;
NodeConfig.SrcIncMode = LL_DMA_SRC_FIXED;
NodeConfig.SrcDataWidth = LL_DMA_SRC_DATAWIDTH_HALFWORD;
NodeConfig.TransferEventMode = LL_DMA_TCEM_BLK_TRANSFER;
NodeConfig.TriggerPolarity = LL_DMA_TRIG_POLARITY_MASKED;
NodeConfig.BlkHWRequest = LL_DMA_HWREQUEST_SINGLEBURST;
NodeConfig.Direction = LL_DMA_DIRECTION_PERIPH_TO_MEMORY;
NodeConfig.Request = LL_GPDMA1_REQUEST_ADC1;
NodeConfig.BlkRptCount = 1;
NodeConfig.UpdateRegisters = (LL_DMA_UPDATE_CTR1 | LL_DMA_UPDATE_CTR2 | LL_DMA_UPDATE_CBR1 | LL_DMA_UPDATE_CSAR | LL_DMA_UPDATE_CDAR | LL_DMA_UPDATE_CLLR);
NodeConfig.NodeType = LL_DMA_GPDMA_LINEAR_NODE;
NodeConfig.SrcAddress = LL_ADC_DMA_GetRegAddr(ADC1, LL_ADC_DMA_REG_REGULAR_DATA);
NodeConfig.DestAddress = (unsigned long)&(pusAdcData[0]);
NodeConfig.BlkDataLength = sizeof(pusAdcData);
LL_DMA_CreateLinkNode(&NodeConfig, &Node_GPDMA1_Channel0);
LL_DMA_ConnectLinkNode(&Node_GPDMA1_Channel0, LL_DMA_CLLR_OFFSET5, &Node_GPDMA1_Channel0, LL_DMA_CLLR_OFFSET5);
LL_DMA_SetLinkedListBaseAddr(GPDMA1, LL_DMA_CHANNEL_0, (uint32_t)&Node_GPDMA1_Channel0);
DMA_InitLinkedListStruct.Priority = LL_DMA_HIGH_PRIORITY;
DMA_InitLinkedListStruct.LinkStepMode = LL_DMA_LSM_FULL_EXECUTION;
DMA_InitLinkedListStruct.LinkAllocatedPort = LL_DMA_LINK_ALLOCATED_PORT0;
DMA_InitLinkedListStruct.TransferEventMode = LL_DMA_TCEM_BLK_TRANSFER;
LL_DMA_List_Init(GPDMA1, LL_DMA_CHANNEL_0, &DMA_InitLinkedListStruct);
/* USER CODE BEGIN ADC1_Init 1 */
LL_DMA_ConfigAddresses(GPDMA1, LL_DMA_CHANNEL_0, LL_ADC_DMA_GetRegAddr(ADC1, LL_ADC_DMA_REG_REGULAR_DATA), (unsigned long)&(pusAdcData[0]));
LL_DMA_SetBlkDataLength(GPDMA1, LL_DMA_CHANNEL_0, sizeof(pusAdcData));
LL_DMA_EnableIT_DTE(GPDMA1, LL_DMA_CHANNEL_0);
LL_DMA_EnableIT_ULE(GPDMA1, LL_DMA_CHANNEL_0);
LL_DMA_EnableIT_USE(GPDMA1, LL_DMA_CHANNEL_0);
LL_DMA_EnableIT_TC(GPDMA1, LL_DMA_CHANNEL_0);
/* USER CODE END ADC1_Init 1 */
/** Common config
*/
LL_ADC_SetTriggerFrequencyMode(ADC1, LL_ADC_TRIGGER_FREQ_HIGH);
ADC_CommonInitStruct.CommonClock = LL_ADC_CLOCK_ASYNC_DIV4;
LL_ADC_CommonInit(__LL_ADC_COMMON_INSTANCE(ADC1), &ADC_CommonInitStruct);
ADC_InitStruct.Resolution = LL_ADC_RESOLUTION_14B;
ADC_InitStruct.LowPowerMode = LL_ADC_LP_MODE_NONE;
ADC_InitStruct.LeftBitShift = LL_ADC_LEFT_BIT_SHIFT_NONE;
LL_ADC_Init(ADC1, &ADC_InitStruct);
LL_ADC_SetGainCompensation(ADC1, 0);
ADC_REG_InitStruct.TriggerSource = LL_ADC_REG_TRIG_EXT_EXTI_LINE11;
ADC_REG_InitStruct.SequencerLength = LL_ADC_REG_SEQ_SCAN_ENABLE_7RANKS;
ADC_REG_InitStruct.SequencerDiscont = LL_ADC_REG_SEQ_DISCONT_DISABLE;
ADC_REG_InitStruct.ContinuousMode = LL_ADC_REG_CONV_CONTINUOUS;
ADC_REG_InitStruct.Overrun = LL_ADC_REG_OVR_DATA_OVERWRITTEN;
ADC_REG_InitStruct.DataTransferMode = LL_ADC_REG_DMA_TRANSFER_UNLIMITED;
LL_ADC_REG_Init(ADC1, &ADC_REG_InitStruct);
LL_ADC_SetOverSamplingScope(ADC1, LL_ADC_OVS_DISABLE);
LL_ADC_REG_SetTriggerEdge(ADC1, LL_ADC_REG_TRIG_EXT_FALLING);
/* Disable ADC deep power down (enabled by default after reset state) */
LL_ADC_DisableDeepPowerDown(ADC1);
/* Enable ADC internal voltage regulator */
LL_ADC_EnableInternalRegulator(ADC1);
/* Delay for ADC internal voltage regulator stabilization. */
/* Compute number of CPU cycles to wait for, from delay in us. */
/* Note: Variable divided by 2 to compensate partially */
/* CPU processing cycles (depends on compilation optimization). */
/* Note: If system core clock frequency is below 200kHz, wait time */
/* is only a few CPU processing cycles. */
__IO uint32_t wait_loop_index;
wait_loop_index = ((LL_ADC_DELAY_INTERNAL_REGUL_STAB_US * (SystemCoreClock / (100000 * 2))) / 10);
while(wait_loop_index != 0)
{
wait_loop_index--;
}
/** Configure Regular Channel
*/
LL_ADC_SetChannelSingleDiff(ADC1, LL_ADC_CHANNEL_7, LL_ADC_SINGLE_ENDED);
LL_ADC_REG_SetSequencerRanks(ADC1, LL_ADC_REG_RANK_1, LL_ADC_CHANNEL_7);
LL_ADC_SetChannelSamplingTime(ADC1, LL_ADC_CHANNEL_7, LL_ADC_SAMPLINGTIME_20CYCLES);
LL_ADC_SetChannelPreselection(ADC1, LL_ADC_CHANNEL_7);
/** Configure Regular Channel
*/
LL_ADC_SetChannelSingleDiff(ADC1, LL_ADC_CHANNEL_8, LL_ADC_SINGLE_ENDED);
LL_ADC_REG_SetSequencerRanks(ADC1, LL_ADC_REG_RANK_2, LL_ADC_CHANNEL_8);
LL_ADC_SetChannelSamplingTime(ADC1, LL_ADC_CHANNEL_8, LL_ADC_SAMPLINGTIME_20CYCLES);
LL_ADC_SetChannelPreselection(ADC1, LL_ADC_CHANNEL_8);
/** Configure Regular Channel
*/
LL_ADC_SetChannelSingleDiff(ADC1, LL_ADC_CHANNEL_9, LL_ADC_SINGLE_ENDED);
LL_ADC_REG_SetSequencerRanks(ADC1, LL_ADC_REG_RANK_3, LL_ADC_CHANNEL_9);
LL_ADC_SetChannelSamplingTime(ADC1, LL_ADC_CHANNEL_9, LL_ADC_SAMPLINGTIME_20CYCLES);
LL_ADC_SetChannelPreselection(ADC1, LL_ADC_CHANNEL_9);
/** Configure Regular Channel
*/
LL_ADC_SetChannelSingleDiff(ADC1, LL_ADC_CHANNEL_10, LL_ADC_SINGLE_ENDED);
LL_ADC_REG_SetSequencerRanks(ADC1, LL_ADC_REG_RANK_4, LL_ADC_CHANNEL_10);
LL_ADC_SetChannelSamplingTime(ADC1, LL_ADC_CHANNEL_10, LL_ADC_SAMPLINGTIME_20CYCLES);
LL_ADC_SetChannelPreselection(ADC1, LL_ADC_CHANNEL_10);
/** Configure Regular Channel
*/
LL_ADC_SetChannelSingleDiff(ADC1, LL_ADC_CHANNEL_15, LL_ADC_SINGLE_ENDED);
LL_ADC_REG_SetSequencerRanks(ADC1, LL_ADC_REG_RANK_5, LL_ADC_CHANNEL_15);
LL_ADC_SetChannelSamplingTime(ADC1, LL_ADC_CHANNEL_15, LL_ADC_SAMPLINGTIME_20CYCLES);
LL_ADC_SetChannelPreselection(ADC1, LL_ADC_CHANNEL_15);
/** Configure Regular Channel
*/
LL_ADC_SetChannelSingleDiff(ADC1, LL_ADC_CHANNEL_16, LL_ADC_SINGLE_ENDED);
LL_ADC_REG_SetSequencerRanks(ADC1, LL_ADC_REG_RANK_6, LL_ADC_CHANNEL_16);
LL_ADC_SetChannelSamplingTime(ADC1, LL_ADC_CHANNEL_16, LL_ADC_SAMPLINGTIME_20CYCLES);
LL_ADC_SetChannelPreselection(ADC1, LL_ADC_CHANNEL_16);
/** Configure Regular Channel
*/
LL_ADC_SetChannelSingleDiff(ADC1, LL_ADC_CHANNEL_17, LL_ADC_SINGLE_ENDED);
LL_ADC_REG_SetSequencerRanks(ADC1, LL_ADC_REG_RANK_7, LL_ADC_CHANNEL_17);
LL_ADC_SetChannelSamplingTime(ADC1, LL_ADC_CHANNEL_17, LL_ADC_SAMPLINGTIME_20CYCLES);
LL_ADC_SetChannelPreselection(ADC1, LL_ADC_CHANNEL_17);
/* USER CODE BEGIN ADC1_Init 2 */
LL_ADC_SetCalibrationOffsetFactor(ADC1, LL_ADC_SINGLE_ENDED, 0U);
LL_ADC_StartCalibration(ADC1, LL_ADC_CALIB_LINEARITY);
while(LL_ADC_IsCalibrationOnGoing(ADC1)) {};
wait_loop_index = ((LL_ADC_DELAY_INTERNAL_REGUL_STAB_US * (SystemCoreClock / (100000 * 2))) / 10);
while(wait_loop_index != 0)
{
wait_loop_index--;
}
//LL_ADC_EnableIT_OVR(ADC1);
//LL_ADC_EnableIT_EOC(ADC1);
LL_ADC_ClearFlag_ADRDY(ADC1);
LL_ADC_Enable(ADC1);
while(LL_ADC_IsActiveFlag_ADRDY(ADC1) != 0)
;
LL_ADC_ClearFlag_ADRDY(ADC1);
LL_DMA_EnableChannel(GPDMA1, LL_DMA_CHANNEL_0);
LL_ADC_REG_StartConversion(ADC1);
/* USER CODE END ADC1_Init 2 */
}
/* Main Function */
if(LL_DMA_IsActiveFlag_TC(GPDMA1, LL_DMA_CHANNEL_0))
{
LL_DMA_ConfigAddresses(GPDMA1, LL_DMA_CHANNEL_0, LL_ADC_DMA_GetRegAddr(ADC1, LL_ADC_DMA_REG_REGULAR_DATA), (unsigned long)&(pusAdcData[0]));
LL_DMA_SetBlkDataLength(GPDMA1, LL_DMA_CHANNEL_0, sizeof(pusAdcData));
LL_DMA_ClearFlag_HT(GPDMA1, LL_DMA_CHANNEL_0);
LL_DMA_ClearFlag_TC(GPDMA1, LL_DMA_CHANNEL_0);
LL_DMA_EnableChannel(GPDMA1, LL_DMA_CHANNEL_0);
}
if( LL_DMA_IsActiveFlag_USE(GPDMA1, LL_DMA_CHANNEL_0)
|| LL_DMA_IsActiveFlag_ULE(GPDMA1, LL_DMA_CHANNEL_0)
|| LL_DMA_IsActiveFlag_DTE(GPDMA1, LL_DMA_CHANNEL_0) )
{
LL_DMA_ClearFlag_DTE(GPDMA1, LL_DMA_CHANNEL_0);
LL_DMA_ClearFlag_ULE(GPDMA1, LL_DMA_CHANNEL_0);
LL_DMA_ClearFlag_USE(GPDMA1, LL_DMA_CHANNEL_0);
LL_DMA_EnableChannel(GPDMA1, LL_DMA_CHANNEL_0);
}
Thanks,
Tal.T