Hi,
I'm attempting to sample signals at a rate of 80kHz, but for some reason I'm able to achieve only 40kHz. My set-up is a follows:
- MKL17Z128VFM4
- Running on LIRC
- Core Clock : 8MHz
- Bus Clock : 4 MHz
- ADC Dma code is taken from \demo_apps\adc16_low_power_async_dma and adapted to use PIT instead of LPTMR
I've calculated that with my current ADC Setup conversion time is abou 9.25us, while sampling time is between 1.5-2.5us which gives maximum rate of around 88kHz. Setting the pit interval to 100 ticks (4M/100 = 40kHz) works like a charm every time, while setting the tick count to 50 (4M/50=80kHz) yields interesting results:
1. noise_dma_read is executed
2. DMA0_IRQHandler is hit where the contents of DMA_DSR_BCRn are equal to (1<<24) which means that transfer is complete and no errors are detected.
3. Immediately after DMA_ClearChannelStatusFlags(DMA0, 0, kDMA_TransactionsDoneFlag); is executed the contents of register DMA_DSR_BCRn are equal to (1<<24) | (1<<30)
4. The code then gets stuck in DMA0_IRQHandler
I'm not quite sure what is causing this behavior and how to handle it. Prior to clearing channel status flag DMA_DSR_BCRn clearly states that transfer is complete and there are no errors and no bytes left to transmitt.
static uint32_t noiseDmaBuf[1024];
static adc16_config_t nDmaCfg;
static adc16_channel_config_t nDmaChCfg;
static dma_handle_t nDmaHandle;
static dma_transfer_config_t nDmaXferCfg;
static volatile bool noiseDmaDone;
static void noise_dma_adc_cfg (void);
static void noise_dma_cfg (void);
static void noise_dma_pit_cfg (void);
static void noise_dma_sim_cfg (void);
static void noise_dma_get_freq (void);
void noise_dma_init (void)
{
noise_dma_adc_cfg ();
noise_dma_cfg ();
noise_dma_pit_cfg ();
noise_dma_sim_cfg ();
noiseDmaDone = true;
}
uint32_t *noise_dma_read (void)
{
noiseDmaDone = false;
PIT_StartTimer(PIT, kPIT_Chnl_0);
while (!noiseDmaDone);
return (uint32_t*)&noiseDmaBuf[0];
}
static void noise_dma_adc_cfg (void)
{
nDmaChCfg.channelNumber = 1;
nDmaChCfg.enableDifferentialConversion = false;
nDmaChCfg.enableInterruptOnConversionCompleted = false;
ADC16_GetDefaultConfig(&nDmaCfg);
nDmaCfg.resolution = kADC16_Resolution16Bit;
nDmaCfg.enableContinuousConversion = false;
nDmaCfg.clockSource = kADC16_ClockSourceAlt0;
nDmaCfg.clockDivider = kADC16_ClockDivider1;
nDmaCfg.enableHighSpeed = true;
nDmaCfg.longSampleMode = kADC16_LongSampleDisabled;
nDmaCfg.enableLowPower = false;
nDmaCfg.referenceVoltageSource = kADC16_ReferenceVoltageSourceValt;
ADC16_Init(ADC0, &nDmaCfg);
noise_dma_get_freq ();
ADC16_DoAutoCalibration (ADC0);
ADC16_SetChannelConfig(ADC0, 0, &nDmaChCfg);
ADC16_SetHardwareAverage(ADC0, kADC16_HardwareAverageDisabled);
ADC16_EnableHardwareTrigger(ADC0, true);
ADC16_EnableDMA(ADC0, true);
}
static void noise_dma_cfg (void)
{
DMAMUX_Init(DMAMUX0);
DMAMUX_SetSource(DMAMUX0, 0U, kDmaRequestMux0ADC0);
DMAMUX_EnableChannel(DMAMUX0, 0U);
DMA_Init(DMA0);
DMA_CreateHandle(&nDmaHandle, DMA0, 0U);
DMA_PrepareTransfer(&nDmaXferCfg, (void *)(uint32_t)(&ADC0->R[0]), sizeof(uint32_t),
(void *)noiseDmaBuf, sizeof(uint32_t), sizeof(noiseDmaBuf),
kDMA_PeripheralToMemory);
DMA_SetTransferConfig(DMA0, 0U, &nDmaXferCfg);
DMA_EnableInterrupts(DMA0, 0U);
DMA_EnableAsyncRequest(DMA0, 0U, true);
DMA_EnableCycleSteal(DMA0, 0U, true);
DMA_StartTransfer(&nDmaHandle);
NVIC_EnableIRQ(DMA0_IRQn);
}
static void noise_dma_pit_cfg (void)
{
pit_config_t pitCfg;
PIT_GetDefaultConfig(&pitCfg);
PIT_Init(PIT, &pitCfg);
PIT_SetTimerPeriod(PIT, kPIT_Chnl_0, 50);
}
static void noise_dma_sim_cfg (void)
{
SIM->SOPT7 |= SIM_SOPT7_ADC0TRGSEL(4) | SIM_SOPT7_ADC0ALTTRGEN(1);
}
void DMA0_IRQHandler (void)
{
PIT_StopTimer(PIT, kPIT_Chnl_0);
noiseDmaDone = true;
DMA_ClearChannelStatusFlags(DMA0, 0, kDMA_TransactionsDoneFlag);
DMA_PrepareTransfer(&nDmaXferCfg, (void *)(uint32_t)(&ADC0->R[0]), sizeof(uint32_t),
(void *)noiseDmaBuf, sizeof(uint32_t), sizeof(noiseDmaBuf),
kDMA_PeripheralToMemory);
DMA_SetTransferConfig(DMA0, 0U, &nDmaXferCfg);
}