GDMA MEM TRANS does not work
Posted: Sat Apr 06, 2024 12:55 am
I'm using GDMA to copy data from internal memory to PSRAM without going through the cache, but I can't get GDMA to work even though testing with SPI, I2S... worked, I'm not what the initialization registe order, can anyone help me?
Error returning interrupt flag: GDMA_IN_DSCR_ERR_CH0_INT_RAW & GDMA_OUT_DSCR_ERR_CH0_INT_RAW
Error returning interrupt flag: GDMA_IN_DSCR_ERR_CH0_INT_RAW & GDMA_OUT_DSCR_ERR_CH0_INT_RAW
Code: Select all
void GDMA_MemInit(){
periph_module_enable(PERIPH_GDMA_MODULE);
REG_WRITE(GDMA_MISC_CONF_REG, GDMA_CLK_EN);
REG_WRITE(GDMA_IN_PRI_CH0_REG, 2);
REG_WRITE(GDMA_OUT_PRI_CH0_REG, 2);
REG_WRITE(GDMA_IN_CONF1_CH0_REG, (1UL << 13) | 64); //block 32B
REG_WRITE(GDMA_OUT_CONF1_CH0_REG, (1UL << 13));
//esp_intr_alloc(ETS_DMA_IN_CH0_INTR_SOURCE, ESP_INTR_FLAG_IRAM, CPY_Interrupt, NULL, NULL);
GDMA_Ready = 1;
}
void GDMA_MemCopy(uint8_t *dst, uint8_t *src, uint32_t len){
uint32_t i, info, s, j;
#define GDMA_SMAX 3072UL
if(!GDMA_Ready)GDMA_MemInit();
while(GDMA_CopyBusy)delay(1);
GDMA_CopyBusy = 1;
s = (len + (GDMA_SMAX-1)) / GDMA_SMAX;
for(i = 0; i < s; i++){
j = i + 1;
if(j < s && j < 8){
info = (0x80000000 | GDMA_SMAX) | (GDMA_SMAX << 12);
CPY_Inlink[i].info = info;
CPY_Inlink[i].buf = (uint32_t)dst;
CPY_Inlink[i].next = (uint32_t)&CPY_Inlink[j];
CPY_Outlink[i].info = info;
CPY_Outlink[i].buf = (uint32_t)src;
CPY_Outlink[i].next = (uint32_t)&CPY_Outlink[j];
dst += GDMA_SMAX; src += GDMA_SMAX; len -= GDMA_SMAX;
}else{
info = (0xC0000000 | GDMA_SMAX) | (len << 12);
CPY_Inlink[i].info = info;
CPY_Inlink[i].buf = (uint32_t)dst;
CPY_Inlink[i].next = 0;
CPY_Outlink[i].info = info;
CPY_Outlink[i].buf = (uint32_t)src;
CPY_Outlink[i].next = 0;
break;
}
}
//DMA
REG_WRITE(GDMA_OUT_CONF0_CH0_REG, GDMA_OUT_RST_CH0);
REG_WRITE(GDMA_IN_CONF0_CH0_REG, GDMA_IN_RST_CH0);
REG_WRITE(GDMA_OUT_INT_CLR_CH0_REG, 0xff);
REG_WRITE(GDMA_IN_INT_CLR_CH0_REG, 0xff);
REG_WRITE(GDMA_OUT_CONF0_CH0_REG, 0); // | GDMA_OUT_DATA_BURST_EN_CH0
REG_WRITE(GDMA_IN_CONF0_CH0_REG, 0); // | GDMA_IN_DATA_BURST_EN_CH0
//REG_WRITE(GDMA_IN_INT_ENA_CH0_REG, GDMA_IN_SUC_EOF_CH0_INT_ENA);
//REG_WRITE(GDMA_IN_PRI_CH0_REG, 2);
//REG_WRITE(GDMA_OUT_PRI_CH0_REG, 2);
//REG_WRITE(GDMA_IN_CONF1_CH0_REG, (1UL << 13) | 64);
//REG_WRITE(GDMA_OUT_CONF1_CH0_REG, (1UL << 13));
REG_WRITE(GDMA_OUT_LINK_CH0_REG, (((uint32_t)&CPY_Outlink[0]) & 0x000FFFFF));
REG_WRITE(GDMA_IN_LINK_CH0_REG, (((uint32_t)&CPY_Inlink[0]) & 0x000FFFFF));
REG_WRITE(GDMA_IN_CONF0_CH0_REG, GDMA_MEM_TRANS_EN_CH0);
REG_WRITE(GDMA_OUT_LINK_CH0_REG, REG_READ(GDMA_OUT_LINK_CH0_REG) | GDMA_OUTLINK_START_CH0);
REG_WRITE(GDMA_IN_LINK_CH0_REG, REG_READ(GDMA_IN_LINK_CH0_REG) | GDMA_INLINK_START_CH0);
i = 20;
while(!(REG_READ(GDMA_IN_INT_RAW_CH0_REG) & GDMA_IN_SUC_EOF_CH0_INT_RAW) && i--){ //
delayMicroseconds(10);
}
DEBUG_PRINTF("DMA Flag: %08X, %08X\r\n", REG_READ(GDMA_IN_INT_RAW_CH0_REG), REG_READ(GDMA_OUT_INT_RAW_CH0_REG) );
GDMA_CopyBusy = 0;
}