View previous topic :: View next topic |
Author |
Message |
benoitstjean
Joined: 30 Oct 2007 Posts: 566 Location: Ottawa, Ontario, Canada
|
[Solved] PIC24EP512 - Can a DMA transfer be paused? |
Posted: Thu Sep 12, 2019 8:26 am |
|
|
Device: PIC24EP512GP806
Compiler: 5.026
Hi guys,
Note here I haven't done any research yet because I've been busy but I thought I'd ask while I think of it... is there a way to pause an ongoing DMA transmission out of a UART?
The outgoing data uses a DMA channel tied to UART1 TX and the packets are of variable length.
The incoming data is straight UART RX using #INT_RDA for each character (note: I haven't checked how to do incoming DMA).
While the PIC is transmitting real-time data at 115200 BPS on its TX DMA channel, it can (and will) also receive data.
What I'd like to do is if a packet is being transmitted and right in the middle of the transmission, a data packet arrives, I'd like to pause the transmission where its at, grab the incoming packet, then resume the transmission...
So for example, if the outgoing data is "HELLO EVERYBODY HOW IS IT GOING" and data starts arriving in the middle of the word 'everybody', it would look like this:
TX: HELLO EVERYB-------------------------------ODY HOW IS IT GOING
RX: ----------------HEY MAN ARE YOU THERE?---------------------------
This is what I currently have:
TX: HELLO EVERYBODY HOW IS IT GOING
RX: HEY MAN ARE YOU THERE?
Thanks!
Ben
Last edited by benoitstjean on Sat Sep 28, 2019 2:09 pm; edited 1 time in total |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Fri Sep 13, 2019 3:12 am |
|
|
PIC32 has a SUSPEND bit in the DMACON register. Your PIC24 does not. |
|
|
benoitstjean
Joined: 30 Oct 2007 Posts: 566 Location: Ottawa, Ontario, Canada
|
|
Posted: Sat Sep 14, 2019 6:37 am |
|
|
Ok thanks. But that's on the PIC32. I guess I'll just live with it for now and if I ever go to PIC32, then I'll re-evaluate.
Ben |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19550
|
|
Posted: Mon Sep 16, 2019 4:08 am |
|
|
I think you can do this with the CHEN bit.
However it then requires extra code in the interrupt handler.
If you set CHEN=0 for the channel involved, it will stop the current transaction,
but the DMAIRQ can trigger to say the transation has 'finished'. In the IRQ
handler you need to check that CHEN is 1 before triggering anything else.
CHEN=0, with the DMAIRQ ether set or clear signals 'DMA transfer
ended without completion'. Potentially provided the counters are not
lost when this is done (not described in the data sheet, will need testing),
setting CHEN back to 1 should continue the transaction. |
|
|
temtronic
Joined: 01 Jul 2010 Posts: 9245 Location: Greensville,Ontario
|
|
Posted: Mon Sep 16, 2019 4:22 am |
|
|
Ok, please humour the old guy, but if both in and out streams are interrupt driven with buffers.. why stop the outgoing ?
Jay |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19550
|
|
Posted: Mon Sep 16, 2019 5:09 am |
|
|
Presumably there is something at the other end that needs the transmission
to stop when it sends you something. Otherwise it doesn't make any sense. |
|
|
benoitstjean
Joined: 30 Oct 2007 Posts: 566 Location: Ottawa, Ontario, Canada
|
|
Posted: Mon Sep 16, 2019 4:08 pm |
|
|
Hi guys,
Thanks for the replies. Sorry I didn't respond earlier, for some reason I didn't get email notifications.
Well, without going into details, it's just that on rare occarsions, I may get the odd RX interrupt error while data is arriving and I am suspecting that this may be caused by the MCU being in the middle of a DMA transmission. The UART data is 115200 but I am working on getting this double the speed in the near future. I can't recreate the problem to troubleshoot it since it is seldom nor can I sit there and hammer away into the unknown until the problem happens because I just don't know how or when it happens.
So if I had a way to pause an outgoing DMA transmission when data arrives, byte by byte on each INT_RDA interrupt, I'd be able to prove if that's the problem or not.
I guess ideally the best way to go about that, if possible, would be to use a DMA interrupt for incoming data if that's even possible. The problem is that I never know the length of the incoming data and also, UART1 is setup on the MCU to use the multiplexer 3GPP protocol. That means all outgoing packets are framed before being sent to the DMA channel (this includes framing bytes, configuration bytes, payload and CRC to name a few) and on the receiving end, it's the same idea in a sense that the data arrives 'framed' but it's never the same length.... so not sure how to use DMA for incoming data as the data length is never known.
The "main" part in my code is just a while loop that checks if there's any data to process in the incoming queue or the outgoing queue and both queues are exclusively mutual... that's for the "processing" part of the queues. But when all of this happens, the interrupts can still fire to make sure no data is missed.... so when a string is being transmitted and physically on the UART (handled by DMA), as much as the incoming queue cannot get processed even if data is waiting to get processed, a string may arrive on the UART RX pin which will make the MCU jump to the INT_RDA interrupt to grab all the bytes. These bytes will get stored in the next incoming queue free spot but not processed until the TX DMA DONE interrupt has fired.
So back to the problem, I suspect that while data is getting output, since there's a crap-load of other stuff happening which I haven't named here (e.g. other interrupts up to 128kHz on INT_CNI), I suspect that once in a while, incoming data on the UART may get missed somehow.
If it's not possible, then so be it.
Thanks.
Ben |
|
|
newguy
Joined: 24 Jun 2004 Posts: 1909
|
|
Posted: Mon Sep 16, 2019 4:40 pm |
|
|
That's a 16 bit processor. Have you played with the LEVEL directive of the various interrupts? Raise the priority of the incoming RDA interrupt over all others and see if the problem goes away or causes other issues to pop up. |
|
|
benoitstjean
Joined: 30 Oct 2007 Posts: 566 Location: Ottawa, Ontario, Canada
|
|
Posted: Mon Sep 16, 2019 7:39 pm |
|
|
Hi newguy,
Good point. I'll check that tomorrow!
Thanks!
Ben |
|
|
benoitstjean
Joined: 30 Oct 2007 Posts: 566 Location: Ottawa, Ontario, Canada
|
|
Posted: Tue Sep 17, 2019 6:23 am |
|
|
Hi again,
Reading through the interrupts document DS70000600D and the priority thing is quite a complex mechanism. I'll be honest with you, it's a lot of information to digest.
To make it short and simple, should I set the INT_RDA interrupt to level 7? It appears that 7 is the highest priority.
Thanks again,
Benoit |
|
|
newguy
Joined: 24 Jun 2004 Posts: 1909
|
|
Posted: Tue Sep 17, 2019 7:00 am |
|
|
I believe that 7 means that nothing else will be examined. For all intents and purposes, 6 is the highest practical level. Set everything else to 4 or 5.
The other thing to add if you start playing with levels, is the ability for interrupts to interrupt other interrupts. There is a #device directive which allows this. Consult the compiler's help file as I can't off hand remember the nomenclature. |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19550
|
|
Posted: Tue Sep 17, 2019 12:04 pm |
|
|
Remember you also need to set nesting=TRUE, to allow interrupt
routines to interrupt other routines.
Just leave all the interrupts as normal, set INT_RDA to level=4, and
enable nesting. This will then allow the RDA interrupt to occur even if the
code is inside another interrupt. |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19550
|
|
Posted: Tue Sep 17, 2019 1:47 pm |
|
|
Also, worth adding, that the INT_RDA handler on a PIC24/30/33, should
loop 'while' data is available. Remember there can be several characters
in the buffer when the interrupt occurs. |
|
|
newguy
Joined: 24 Jun 2004 Posts: 1909
|
|
Posted: Tue Sep 17, 2019 2:33 pm |
|
|
Ttelmah wrote: | Also, worth adding, that the INT_RDA handler on a PIC24/30/33, should
loop 'while' data is available. Remember there can be several characters
in the buffer when the interrupt occurs. |
Yes, very true. Structure the code inside the interrupt in a do { ... } while. Only exit when there are no characters left to fetch. |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19550
|
|
Posted: Wed Sep 18, 2019 12:53 am |
|
|
Yes. My thought was that if he only handles a single character on each
interrupt (the normal/correct approach for a PIC16/18), and a second
interrupt handler was slow enough for two or three characters to be in
the buffer at some point, it might then never recover.... :( |
|
|
|