Finally got around to trying QDMA. Didn't work :(
My scheme is as follows;
Use QDMA channel 0 to read from a 16-bit GPIO port 16 times and save the readings in an array of 16-bit words.
After POR, I set it up as follows:
This thread has been locked.
If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.
Finally got around to trying QDMA. Didn't work :(
My scheme is as follows;
Use QDMA channel 0 to read from a 16-bit GPIO port 16 times and save the readings in an array of 16-bit words.
After POR, I set it up as follows:
Hi,
I thought you read from a fixed address (GPIO port) and move the data into a buffer with incremental destination address. For the simplest case, just read GPIO 16-bit once, so you ACNT=2, BCNT=1, will this work for you? That is, will you see the IPR bit set? What is your QDMA trigger word? If nothing happened, do you see any error for EDMA transfer? E.g in ERRSTAT register?
In the 16 times read, I thought you need to use SAM=0, DAM=1 in the OPT field.
Regards, Eric
Great to have someone finally reply!! Thanks!!
For learning purpose, I simplified the code so it is a memcpy of 8 byte array. When I run it, it results in error . ERRSTAT and ERRDET. What could be happening?
ERRSTAT 0x00000001 Error Status [Memory Mapped]
_RESV_1 **************************** Reserved
MMRAERR 0 - NONE MMR Address Error Event
TRERR 0 - NONE TR Error Event
_RESV_4 * Reserved
BUSERR 1 - ERROR Bus Error Event
ERREN 0x00000000 Error Enable [Memory Mapped]
ERRCLR 0x00000000 Error Clear Register [Memory Mapped]
ERRDET 0x00010001 Error Details [Memory Mapped]
_RESV_1 ************** Reserved
TCCHEN 0 Transfer Completion Chaining Enable
TCINTEN 1 Transfer Completion Interrupt Enable
_RESV_4 ** Reserved
TCC 000000 Transfer Completion Code
_RESV_6 **** Reserved
STAT 0001 - READ_ADDRESS Transation Status
ERRCMD 0x00000000 Error Command [Memory Mapped]
Here is the new code snippet:
bool QDMA_Done() {
uint32 x = RFDMA_READY;
bool tb = (x != 0) ? TRUE : FALSE;
return (tb);
}
//=============================================================================
void InitQDMA() {
//clear interrupt status
HWREG(ICR) = 0x00000001;
int i;
for (i=0;i<8;i++) {
dstdata[i] = 0;
}
// initialize PaRAM Set 0
HWREG(QCHMAP0) = 0x0000000c;
HWREG(QEESR) = 0x00000001;
data_PaRAM.src = (uint32) srcdata;
data_PaRAM.acnt = 1;
data_PaRAM.bcnt = 8;
data_PaRAM.srcbidx = 1;
data_PaRAM.dstbidx = 1;
data_PaRAM.bcntrld = 1;
data_PaRAM.srccidx = 0;
data_PaRAM.dstcidx = 0;
data_PaRAM.ccnt = 1;
data_PaRAM.opt = 0x0010000c; //TCINTEN=1, STATIC=1, SYNCDIM=1
data_PaRAM.link = NO_LINK;
// trigger word; must be the last assignment statement in the function
//set interrupt enable
//enable QDMA Ch 0
HWREG(IESR) = 0x00000001;
data_PaRAM.dst = (uint32) dstdata;
/* int i;
for (i=0;i<16;i++) {
RF_READINGS[i] = 0;
}
//clear interrupt status
HWREG(ICR) = 0x00000001;
//enable QDMA Ch 0
HWREG(QEESR) = 0x00000001;
// initialize PaRAM Set 0
data_PaRAM.src = RF_IN;
data_PaRAM.acnt = 2;
data_PaRAM.bcnt = 16;
data_PaRAM.srcbidx = 0;
data_PaRAM.dstbidx = 2;
data_PaRAM.bcntrld = 0;
data_PaRAM.srccidx = 0;
data_PaRAM.dstcidx = 0;
data_PaRAM.ccnt = 1;
data_PaRAM.dst = (uint32) &RF_READINGS;
data_PaRAM.link = NO_LINK;
// trigger word; must be the last assignment statement in the function
//set interrupt enable
HWREG(IESR) = 0x00000001;
data_PaRAM.opt = 0x00100008; //TCINTEN=1, STATIC=1
*/
}
Some progress made. Address adjustments for source and destination in the PaRAM made it work. I found out from other e2e posts that L2 RAM is addressed differently from edma3.
Proceeding to the gpio to 16 sample storage in L2 RAM ... If I try one sample only - that is, transfer one 16 bit gpio read to one 16 bit memory location, it works. But, one to 16 scheme does not work. Basically, I am waiting for the interrupt bit in IPR to get set forever. The parameters are
data_PaRAM.acnt = 2;
data_PaRAM.bcnt = 16;
data_PaRAM.srcbidx = 0;
data_PaRAM.dstbidx = 2;
data_PaRAM.bcntrld = 0;
data_PaRAM.srccidx = 0;
data_PaRAM.dstcidx = 0;
data_PaRAM.ccnt = 1;
Hi,
Great that you made progress --- transfer one 16 bit gpio read to one 16 bit memory location, it works. For "But, one to 16 scheme does not work.", that is you read the FIFO 16 times and each time save the reading out to a different location. You may try if data_PaRAM.dstbidx = 4 helps. Also in the OPT field, there are bit settings: Intermediate transfer completion interrupt enable and Transfer complete interrupt enable, and Transfer synchronization dimension. Try to see if using A-sync only and both intermediate and transfer complete interrupt enable, how far you can go. Whether you saw the GPIO data in the buffers or not? And how many buffers received data?
Also I'm not sure the reason you need 16 consecutive QDMA read. The DMA read is so fast and the GPIO may not populated with the new data. So you may have 16 identical GPIO data put into 16 different destination buffers. Why not each time you just do one 16-bit GPIO read into a memory, then the application needs to know when the next GPIO data will come in and schedule another QDMA read.
Regards, Eric
It's working finally after setting it up for AB synchronization.
Question:
If the polling code is slow and unable to respond in time to active IPR bit and let's say QDMA uses linking, it is possible to miss an interrupt. My question is the missed interrupt unrecoverable? IPR bit overwritten and previous one is not retained?
Hi,
I tried the scenario where IPR is not cleared (via writing ICR), but another DMA transfer came in from the same DMA channel. I found the second transfer still happened and IPR bit is overwritten amd previous interrupt is missed and can't be recovered.
Regards, Eric
Thanks. That is good info.
I'm definitely learning more about edma3. Still not clear about why A synchronization would not work, but AB sync does.
Thanks again for the follow up.
Peter