I'm using a DMA to receive data from an UART and store them to RAM. It works correctly. I need to use the preserveTds option. At a given time, I'd like to know how many bytes are received. To know that, I'd like to know where (the address in RAM) the DMA destination pointer points.
The CyDmaTdGetAddress function returns the adresse of the original (preserved) TD, not the intermediate one.
I see in the CyDma.c file, in the CyDmaChEnable function, a comment saying:
Store intermediate TD states separately in CHn_SEP_TD0/1 to preserve original TD chain
I guess the information I'm looking for is in this intermediate TD state. So my question is: is there a way to access those registers to know the current addresse where the destination pointer points?
Solved! Go to Solution.
I was involved in a discussion on this forum with a similar question. Here is the link to that discussion. Hopefully it will help.
Yes, I'm the same poster. The answer there is a solution, but I have a lot of setup time violation, or I need to lower master clock too much because of the counter. I'd like to find another approach, by looking at the current destination address.
I see this problem differently - UART is inherently asynchronous and slow protocol, this it is ok to process incoming data using interrupts on time of arrival. If this, otherwise, continuous stream at Max speed, the DMA is ok, but actual position in the RAM is not very important.
Right, I could do a RX_buffer[index++] = received_char; in the rx interrupt, but I don't like the idea to be interrupted at 115200 / 10 = 11kHz. There may be another interrupt running, so I have to be careful on priorities. I could have a try, but DMA is a nicer way to get data in the background.
Position in the RAM is needed to know how many bytes has been received. My DMA is configured to be a circular buffer that run continuously, and I need to know if data are received, how many, to treat them.
At 115k by time UART_Rx interrupt fires, there will be several chars in the buffer already, so actual isr rate will be in ~1kHz rate, which isn't that bad. I suggest to try existing demo to see if this works for your project, like this one:
Thanks for your suggestion.
115200 / 10bits per byte = 11520 bytes per seconds. The buffer can have 4 bytes max, so if buffer is full before interrupt is raised (I don't see why it would ...) then the minimum interrupt frequency is 11520 / 4 = 2,88kHz, and maximum frequency is 11,52kHz.
I'll test if that can fit my needs, even if I don't find this workaround very nice.
My first question remain, is it possible to access internal DMA registers.
I've looked at the PSoC5LP TRM (001-82120_PSoC5LP_Registers_TRM.pdf). There does not appear to be an interface register to read the current transfer count of the DMA. If I am correct, the DMA is implemented as a SPC interface which can be the equivalent of a HW state-machine interface to internal HW.
Unless Cypress can shred more light on your question, the suggestion of a parallel counter to DRQ signal may be your only means of determining approximately where the DMA transfer has progressed.
Question to the forum: Is it possible to create a 2 TD implementation where the first TD reads the comm byte memory and the second TD increments the a count in memory? The DMA configuration loops back to the first TD.