2020-10-13 12:40 PM
The code below was implemented using a PsoC device. Maybe someone here can help me understand it and do the same in a STM32 device. AFAIK, the code is intended to build a quad buffer, but I don't understand how this is being implemented within a single array. I'm using STM32G0 and I have tested the ADC channel and DMA circular mode with HT and TC interrupts using HAL and it works OK.
Below the DMA configuration in the Psoc device:
void DMA1_Config(void)
{
uint8 DMA1_Chan;
uint8 DMA1_TD[4];
#define TRANSFER_COUNT (NO_SAMPLES * 2)
#define BUFFER_1 (NO_SAMPLES)
#define BUFFER_2 (NO_SAMPLES * 2)
#define BUFFER_3 (NO_SAMPLES * 3)
#define DMA_BYTES_PER_BURST (2u)
#define DMA_REQUEST_PER_BURST (1u)
#define DMA_SRC_BASE (CYDEV_PERIPH_BASE)
#define DMA_DST_BASE (CYDEV_SRAM_BASE)
DMA1_Chan = DMA1_DmaInitialize(DMA_BYTES_PER_BURST, DMA_REQUEST_PER_BURST, HI16(DMA_SRC_BASE), HI16(DMA_DST_BASE));
DMA1_TD[0] = CyDmaTdAllocate();
DMA1_TD[1] = CyDmaTdAllocate();
DMA1_TD[2] = CyDmaTdAllocate();
DMA1_TD[3] = CyDmaTdAllocate();
CyDmaTdSetConfiguration(DMA1_TD[0], TRANSFER_COUNT, DMA1_TD[1], DMA1__TD_TERMOUT_EN | TD_INC_DST_ADR);
CyDmaTdSetConfiguration(DMA1_TD[1], TRANSFER_COUNT, DMA1_TD[2], DMA1__TD_TERMOUT_EN | TD_INC_DST_ADR);
CyDmaTdSetConfiguration(DMA1_TD[2], TRANSFER_COUNT, DMA1_TD[3], DMA1__TD_TERMOUT_EN | TD_INC_DST_ADR);
CyDmaTdSetConfiguration(DMA1_TD[3], TRANSFER_COUNT, DMA1_TD[0], DMA1__TD_TERMOUT_EN | TD_INC_DST_ADR);
// Target
CyDmaTdSetAddress(DMA1_TD[0], LO16((uint32)ADC_1_DEC_SAMP_PTR), LO16((uint32)(&Buffer[0])));
CyDmaTdSetAddress(DMA1_TD[1], LO16((uint32)ADC_1_DEC_SAMP_PTR), LO16((uint32)(&Buffer[BUFFER_1])));
CyDmaTdSetAddress(DMA1_TD[2], LO16((uint32)ADC_1_DEC_SAMP_PTR), LO16((uint32)(&Buffer[BUFFER_2])));
CyDmaTdSetAddress(DMA1_TD[3], LO16((uint32)ADC_1_DEC_SAMP_PTR), LO16((uint32)(&Buffer[BUFFER_3])));
CyDmaChSetInitialTd(DMA1_Chan, DMA1_TD[0]);
CyDmaChEnable(DMA1_Chan, 1);// Enable DMA channel
}
This is how the buffer is used within a function. This function is called every time 1/4 buffer fill interrupt:
#define NO_SAMPLES 200u // number of samples to acquire (1/4 buffer)
int16 Buffer[4 * NO_SAMPLES];
uint8 Window[NO_SAMPLES];
double RMS_find()
{
uint64 AccMS64 = 0;
uint16 offset1=0, offset2=0;
uint16 i;
int16 v;
switch (BufferSection)
{
case 0: // -->0..1..2--3
offset1 = 3 * NO_SAMPLES;
offset2 = 0;
BufferSection=1; // next section
break;
case 1: // --0-->1..2..3
offset1 = 0;
offset2 = NO_SAMPLES;
BufferSection=2; // next section
break;
case 2: // ..0--1-->2..3
offset1 = NO_SAMPLES;
offset2 = 2 * NO_SAMPLES;
BufferSection=3; // next section
break;
case 3: // ..0..1--2-->3
offset1 = 2 * NO_SAMPLES;
offset2 = 3 * NO_SAMPLES;
BufferSection=0; // next section
break;
default: // should not come here
BufferSection=0;
}
for( i=0; i<NO_SAMPLES; i++) {
v = Buffer[i+offset1];
AccMS64 += (uint64)(v*v) * Window[(NO_SAMPLES-1)-i];
}
for( i=0; i<NO_SAMPLES; i++) {
v = Buffer[i+offset2];
AccMS64 += (uint64)(v*v) * Window[i];
}
2020-10-13 01:09 PM
I fear you have to understand both ways DMA is implemented anf you have to rewrite DMA setup and runtime code.