Hello,
currently we are solving a problem how to efficiently implement the RS485 communication using the RM48L952 processor with SCI + DMA.
In the past we were using the STM32 processor which had two very useful functions (among others):
1. Interrupt generation while IDLE state was present on the serial line
2. If the DMA channel was stopped in between the transmition, it was possible to read the remaining count of characters to be transferred.
None of these options seems to be present in this processor. There is only an SCI IDLE flag which would have to be polled. This is quite hard to be done, but let's say it's possible to detect the IDLE state using for example an external FPGA (which is already on the board), monitoring the RX line and generating an external interrupt when the IDLE state occurs.
But the second feature is much more needed and related to the first one, consider the following scenario:
A previously uknown number of characters is received (and, more importantly, is shorter than the number of characters programmed into DMA PCP), then the IDLE state on the serial line is detected. Now we need to evaluate the received characters and switch the RS485 driver to transmitting - how could we determine the number of already received bytes in the buffer?
As far as we understand, the only way how to use the SCI with DMA is configuring the DMA for frame transfers, where the size of an element is 8 bit and the number of elements for frame is 1 (not considering the multibuffer now as it makes things more complicated). Then, once a new character is received, the DMA frame transfer is triggered and the character is copied into a buffer. Once the programmed number of characters is received, the BTC interrupt is generated and the buffer can be processed. So far so good, but how to deal with the situation, that less number of characters than expected is received and then the IDLE condition occurs?
CTCOUNT (DMA working packet) is not possible to use, because it needs another DMA transfer to be performed as we found out from previous posts. PBACTC register contains the current (or rather last) active channel element remaining count, but how to determine the current/last active channel? DMASTAT is not possible to use, because once the frame transfer is finished, the DMASTAT is reset to zeros (as far as we have found out). Once again, after the IDLE condition is detected, we need to find out how many characters have already been received.
We found a suggested solution in some of the previous posts, which does not seem to be very efficient - trigger two DMA channels with the SCI RX simultaneously, one for the SCI itself and one for copying a table of consequent values 1,2,3,... into some fixed location in the memory. Therefore, we would need 2 DMA channels for RX and one for TX. Using both of the SCI channels this means 6 DMA channels to be used just for SCI.
Or we came up with another solution - after the IDLE state occurs, periodically trigger the RX DMA channel using the SW trigger and increment a counter. Once the interrupt is generated, we can tell how many characters were received by simply subtracting the counter from the initial count. This is not very efficient, either.
The only solution for this problem seems to be not to use the DMA, but rather the RX interrupt, then, after each character reception to increment the number of characters and at the same time to start some timeout counter. Once the timeout counter overflows, it is safe to tell the upper sw layer the amount of received characters (which is known now due to the counter incremented after each RX interrupt), enable the RS485 transmitter and start transmitting.
Is there really no sophisticated way of using the SCI + DMA and handle the RS485 communication with IDLE state?
Thanks in advance.
Lukas