Trying to use GDMA to transfer ADC readings to memory.
I’ve set the ADC to be triggered by timer, and - I think - done all the setup necessary on the ADC to have its trigger to the DMA enabled, called ADC_RXGDMA_Init and enabled it.
The ADC is reading - I can see the FIFO go full - but the DMA is not being activated. Hardware platform is BW16 with RTL8720DN SoC.
I can read values from the ADC successfully using programmed IO (with appropriate configuration and the ADC_Readbuf() function)
My source is below (the comments on ‘how to do it’ are copied from the SDK file rtl8721d_adc.h)
void morse_adc_init(){
u8 EfuseBuf[2];
u32 index;
u32 addressOffset = 0x1D0;
u32 addressGain = 0x1D2;
#define pin _PB_3
gpio_t adcpin;
//First set the ADC we want to use and set the corresponding pad to ADC mode
Pinmux_Swdoff(); //Disable the Software Debug function of port B bit 3 module pin 2
//Set relevant GPIO mode to be an input with no pull-up or pulldown
gpio_init(&adcpin,_PB_3);
gpio_dir(&adcpin,PIN_INPUT);
gpio_mode(&adcpin,PullNone);//If we are using the api initialization, the calibration is done the first time the ADC_Init function is called
memset((void )adcbuf,0,sizeof(adcbuf)); //Clear the receive buffer
/*****************************************************************************************
- How to use ADC in DMA mode (copied from rtl8721d_adc.h )
To use ADC in DMA mode, the following steps are mandatory:1. Enable the ADC interface clock:RCC_PeriphClockCmd(APBPeriph_ADC, APBPeriph_ADC_CLOCK, ENABLE);/
RCC_PeriphClockCmd(APBPeriph_ADC, APBPeriph_ADC_CLOCK, ENABLE);
/ 2. Fill the ADC_InitStruct with the desired parameters.
**/uint32_t adc_idx; adc_idx = pinmap_peripheral(_PB_3, PinMap_ADC); printf("analogin_init [%x:%x ]\n",pin, adc_idx); assert_param(adc_idx != NC); /* Shutdown ADC gpio pin to prevent leakage current */ if(pin <= PB_31) { PAD_CMD(pin, DISABLE); }ADC_InitTypeDef ADC_InitStruct; //Defined in rtl8721d_adc.h l120 Scope: Local, non-persistent
/* Initialize ADC */ ADC_StructInit(&ADC_InitStruct); //Sets some basic parameters, some of which we over-write ADC_InitStruct.ADC_OpMode = ADC_TIM_TRI_MODE; //ADC_InitStruct.ADC_OpMode = ADC_AUTO_MODE; ADC_InitStruct.ADC_CvlistLen = 0; ADC_InitStruct.ADC_Cvlist[0] = adc_idx;ADC_InitStruct.ADC_DMAThresholdLevel = 3; //Grab four readings at a time
ADC_InitStruct.ADC_ChIDEn = ENABLE; //Optional: Place the channel ID in the output reading (MS Nibble)/* ADC_INTConfig(BIT_ADC_IT_FIFO_FULL_EN, ENABLE); InterruptRegister((IRQ_FUN)adc_irq_handle, ADC_IRQ, NULL, 10); InterruptEn(ADC_IRQ, 10); *//* 3. Init Hardware use step2 parameters.
ADC_Init(ADC_InitTypeDef* ADC_InitStruct).*/
ADC_Init(&ADC_InitStruct);/* 4. Enable DMA read mode.
ADC_SetDmaEnable().*/
ADC_SetDmaEnable(ENABLE); //Set the flag in the ADC registers/* 5. Init and Enable ADC RX GDMA, configure GDMA related configurations(source address/destination address/block size etc.)
ADC_RXGDMA_Init().*/
GDMA_InitTypeDef GDMA_InitStruct;
//Note: Block length must be from 0 to 4095 (it is masked with 0xFFF)
DCache_CleanInvalidate((u32)adcbuf, 8192); //Copied from the uart DMA driver
uint32_t dmaRes = ADC_RXGDMA_Init(&GDMA_InitStruct,(IRQ_FUN)DMA_Callback,(void *)&DMA_CbData,(u8 )&adcbuf,(u32)128);
//NVIC_SetPriority(GDMA_GetIrqNum(0, GDMA_InitStruct.GDMA_ChNum), 12);
/ 6. Activate the ADC peripheral:
ADC_Cmd(ENABLE).*/
printf(“dmaRes: %x, chan: %d; Hitting trigger\n\r”,dmaRes,GDMA_InitStruct.GDMA_ChNum);
dmaDone = false;
ticks1 = tCounter;
ADC_Cmd(ENABLE); //If the mode is set to AUTO rather than timer triggered, this will start the system
/* 7. Enable specified mode:
*
ADC_TimerTrigCmd(Tim_Idx, PeriodMs, ENABLE)*/
ADC_TimerTrigCmd(2, 1, ENABLE); //Temporarily set to 1ms sampling rate
//ADC_ReceiveBuf(adcbuf,8192);
ticks2 = tCounter;
}