- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
I am using the following code to setup a double-buffering scheme for the ADC. It appears that the DMA ISR is repeatedly being called rather than when 32 samples have been transferred. If I add the line: CyDmaClearPendingDrq(DMA_1_Chan); then it never gets called.
What could be wrong?
#include <project.h>
#include "adc_dma.h"
#include "idac.h"
#define NSAMPLES 32
#define TFR_CNT NSAMPLES * 2
#define DMA_BYTES_PER_BURST 2
#define DMA_REQUEST_PER_BURST 1
#define DMA_SRC_BASE (CYDEV_PERIPH_BASE)
#define DMA_DST_BASE (CYDEV_SRAM_BASE)
uint8 DMA_1_Chan; //TODO: use the int assigned in DMA_1_dma.h
uint8 DMA_1_TD[2];
uint16_t adc_buffer1[NSAMPLES] ={0};
uint16_t adc_buffer2[NSAMPLES] ={0};
//static volatile uint16_t total;
uint16_t adc_val = 0;
uint8 currentTD = 0;
uint16_t last_total;
void init_adc_dma(void) {
DMA_1_Chan = DMA_1_DmaInitialize(DMA_BYTES_PER_BURST, DMA_REQUEST_PER_BURST, HI16(DMA_SRC_BASE), HI16(DMA_DST_BASE));
DMA_1_TD[0] = CyDmaTdAllocate();
DMA_1_TD[1] = CyDmaTdAllocate();
CyDmaTdSetConfiguration(DMA_1_TD[0], TFR_CNT, DMA_1_TD[1],
TD_INC_DST_ADR | TD_AUTO_EXEC_NEXT | TD_TERMOUT0_EN | DMA_1__TD_TERMOUT_EN);
CyDmaTdSetConfiguration(DMA_1_TD[1], TFR_CNT, DMA_1_TD[0],
TD_INC_DST_ADR | TD_AUTO_EXEC_NEXT | TD_TERMOUT0_EN | DMA_1__TD_TERMOUT_EN);
CyDmaTdSetAddress(DMA_1_TD[0], LO16((uint32)ADC_SAR_1_SAR_WRK0_PTR), LO16((uint32)&adc_buffer1[0]));
CyDmaTdSetAddress(DMA_1_TD[1], LO16((uint32)ADC_SAR_1_SAR_WRK0_PTR), LO16((uint32)&adc_buffer2[0]));
CyDmaChSetInitialTd(DMA_1_Chan, DMA_1_TD[0]);
CyDmaChEnable(DMA_1_Chan, 1);
}
CY_ISR(ISR_DMA_DONE_ADC)
{
CyDmaChStatus(DMA_1_Chan, ¤tTD, NULL);
//process adc_buffer2
if (currentTD == DMA_1_TD[0]) {
LED_BLUE_DR |= LED_BLUE_MASK; //Turn on LED
}
//process adc_buffer1
else if (currentTD == DMA_1_TD[1]) {
LED_BLUE_DR &= ~LED_BLUE_MASK; //Turn off LED
}
CyDmaClearPendingDrq(DMA_1_Chan); //ISR never gets called if this line is included
Solved! Go to Solution.
- Labels:
-
PSoC 5LP
- Tags:
- dma
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
user_27...,
Try to remove TD_AUTO_EXEC_NEXT qaualifier.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
user_275561502,
Your design intent is not clear from your description.
This is my understanding of what you are asking.
You intend to continuously bounce between adc_buffer1 and adc_buffer2 indefinitely.
Your question deals with the ISR is called on every sample transferred(?).
It appears you are using DMA_1__TD_TERMOUT_EN for TD[0] and TD[1]. If ISR_DMA_DONE_ADC is being generated from the 'nrq' output of DMA_1, then you should only call the ISR after 32 samples are transferred. Now the ISR will continuously repeat since the end of TD[1] calls TD[0] to start everything over. It sounds that you are looking for a terminating event.
You need to determine the conditions of your terminating event. Once you determine that, you can stop ADC_SAR_1. This will stop the DMA.
I'll try to help further but I will need more information.
Len
PS: user_342122993 suggestion about removing TD_AUTO_EXEC_NEXT makes sense if you want your terminating event for the DMA to be after TD[0] or TD[1]. Note: This will only stop the DMA not the ADC_SAR_1 conversions.
"Engineering is an Art. The Art of Compromise."