CCS C Software and Maintenance Offers
FAQFAQ   FAQForum Help   FAQOfficial CCS Support   SearchSearch  RegisterRegister 

ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

CCS does not monitor this forum on a regular basis.

Please do not post bug reports on this forum. Send them to CCS Technical Support

PIC24EP512 - How to properly handle an #INT_DMAERR [CLOSED]

 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
benoitstjean



Joined: 30 Oct 2007
Posts: 566
Location: Ottawa, Ontario, Canada

View user's profile Send private message

PIC24EP512 - How to properly handle an #INT_DMAERR [CLOSED]
PostPosted: Mon Dec 07, 2020 6:35 am     Reply with quote

Device: PIC24EP512GP806
Compiler: 5.026

Good morning,

I am using a DMA channel for the UART transmission of data between the PIC and an embedded modem. I haven't had a #INT_DMAERR for a very long time, probably over two years.

The PIC transmits AT commands to a modem and gets the corresponding response but also transmits 64kbps audio at the same time. Both the command and response get printed in Tera Term except when the transmitted data is an audio buffer since it would be too much data to be printed.

Last night, the code had been running several hours and the PIC, while transmitting audio, all of a sudden in the middle of the night after running for a few hours got an #INT_DMAERR interrupt error.

In my code, when this error happens, I print the first 15 bytes of the TX data to the screen. Since it was transmitting audio, as soon as that interrupt error happened, then it seems the PIC was stuck in that 'erratic' mode and flooded my screen with DMA interrupts which caused the PIC to eventually reset (WDT). The printed data does seem like it's the correct data (audio buffer)... it's just that it got stuck in that erratic mode and stayed that way until the WDT kicked-in.

I see that there's a dma_status() function which returns the following but doesn't seem to point to anything relevant:
Code:
#define DMA_IN_ERROR    0x01
#define DMA_OUT_ERROR   0x02
#define DMA_B_SELECT    0x04

Just as a side note, I got a piece of code in this forum to print-out any #INT_ADDRERR error interrupt to find the line that generated this error and it has proven itself to be useful because I found several bugs in my code over the years.

For the #INT_DMAERR error interrupt, is there such piece of code that could indicate what the problem was and what is the best way to handle the error and "reset" whatever "stack" there may be for DMA to prevent the problem to remain if it happens?

Is there anything I can do to make sure that if it happens, it happens only once, then whatever "reset" gets applied, continues the code without having to have the WDT kick-in?

[EDIT] Any registers I should print on the screen to see if any of them point to the problem?

[EDIT] Document DS70348C-page 22-51 states for UART:

Data waiting to be moved by the DMA channel is not overwritten by additional incoming data. Subsequent incoming data is lost, and the Overflow Error bit (OERR) is set in the UART Status register (UxSTA). Also, the UARTx Error interrupt is generated if the UART Error Interrupt Enable bit (UxEIE) is set in the Interrupt Enable Control register (IECx) in the interrupt controller.


I'm not getting any UART errors.

Thanks!

Ben


Last edited by benoitstjean on Tue Dec 08, 2020 2:36 pm; edited 1 time in total
Ttelmah



Joined: 11 Mar 2010
Posts: 19548

View user's profile Send private message

PostPosted: Mon Dec 07, 2020 12:59 pm     Reply with quote

The DMA error interrupt normally means that either more data has been
loaded before the transmission has completed, or that the receive handler
has had more data arrive before the earlier packet has been handled.
You won't get an OERR, this only triggers when the UART buffer overflows.
So look carefully at whether anything might be disabling servicing of the
DMA handler (remember if you are not using interrupt levels, an interrupt
won't be called if you are in an interrupt handler).
benoitstjean



Joined: 30 Oct 2007
Posts: 566
Location: Ottawa, Ontario, Canada

View user's profile Send private message

PostPosted: Mon Dec 07, 2020 1:29 pm     Reply with quote

Hmmmm.... the only level I have assigned is #INT_RDA LEVEL=7 to make sure that this has the highest priority since it has to capture all incoming modem data, especially to make sure it receives the unsolicited messages from the modem. The device functionality relies on the state of the modem therefore it cannot miss any modem messages.

I didn't set the priority level for any other interrupt. Not sure if this is correct or not... The entire code runs off interrupts.

This is the code I have when sending data to the UART TX DMA channel:
Code:

DMA.IsTransferDone = FALSE;
dma_start( 0, DMA_ONE_SHOT | DMA_FORCE_NOW, &DMAPacket0[0], packetLength - 1 );

The DMA.IsTransferDone flag is set back to TRUE when the #INT_DMAERR or #INT_DMA0 occur. I also have a transfer timeout counter through timer 1 that if it expires, then it means that the DMA xfer failed somehow therefore the timeout timer is stopped. Otherwise, the timeout is stopped when either of the DMA interrupts fire.

Received modem data or data transmitted to the modem cannot be dequeued for processing from their respective Rx or Tx queues when that flag is FALSE.... in other words, when entering either Dequeue functions, if the DMA is not done, the dequeuing is canceled.

I've added the following in the #INT_DMAERR interrupt in case it can point to any problems:
Code:

   fprintf( MONITOR_SERIAL, "\n\r#INT_DMAERR ERROR:" );
   fprintf( MONITOR_SERIAL, "\n\rDMA0CON : 0x%04X", DMA0CON );
   fprintf( MONITOR_SERIAL, "\n\rDMA0REQ : 0x%04X", DMA0REQ );
   fprintf( MONITOR_SERIAL, "\n\rDMA0STAH: 0x%04X", DMA0STAH );
   fprintf( MONITOR_SERIAL, "\n\rDMA0STBH: 0x%04X", DMA0STBH );
   fprintf( MONITOR_SERIAL, "\n\rDMA0PAD : 0x%04X", DMA0PAD );
   fprintf( MONITOR_SERIAL, "\n\rDMAPWC  : 0x%04X", DMAPWC );
   fprintf( MONITOR_SERIAL, "\n\rDMARQC  : 0x%04X", DMARQC );
   fprintf( MONITOR_SERIAL, "\n\rDMALCA  : 0x%04X", DMALCA );
   fprintf( MONITOR_SERIAL, "\n\rDMAPPS  : 0x%04X", DMAPPS );
//   fprintf( MONITOR_SERIAL, "\n\rDSADR   : 0x%04X", DSADR ); (commented-out this one, compiler doesn't recognize it??)

So if the #INT_DMAERR interrupt occurs, I will see how the DMA-related registers are configured. Not sure it will help but it doesn't hurt to try.

I'm not too concerned since this is a very very rare problem, like I said, hasn't occurred for a very long time...

If you think I should dump other registers or information to the screen, let me know.

Thanks for your time.

Ben
Ttelmah



Joined: 11 Mar 2010
Posts: 19548

View user's profile Send private message

PostPosted: Tue Dec 08, 2020 1:16 am     Reply with quote

Is it possible that something can result in it getting stuck 'in' the INT_RDA
handler?.

There seems to be a 'confusion' here. You are obviously handling received
data using INT_RDA, not DMA. So the comments about OERR don't apply.

It sounds as if you are using the DMA for transmit only?. In which case the
only 'error' would occur if you tried to start a transaction when the UART
was already busy. Now it is possible that this could happen for your chip,
because of an erratum. If you are testing the TX interrupt flag to verify
the chip has completed transmission, this can set before the chip has
actually finished (errata 16). You would need to poll the transmit buffer
empty bit to be confident the transmission had completed, before triggering
the new DMA.
benoitstjean



Joined: 30 Oct 2007
Posts: 566
Location: Ottawa, Ontario, Canada

View user's profile Send private message

PostPosted: Tue Dec 08, 2020 6:24 am     Reply with quote

Oh, yes, I am in fact using the DMA to transmit only. Quite frankly, I've never gone the way to implementing DMA on received data, I had too much on my plate, my Rx code worked well but also, I wasn't too sure how to do it with incoming data of varying length.

I guess I'll have to look at it at some point.

I don't know about the errata 16. I'll go search online.

So to 'poll' the 'transmit buffer empty' bit, I presume you mean bit 8 TRMT: Transmit Shift Register is Empty bit of the U1STA register for the UART?

Thanks.

Ben

[EDIT] Found it:
Quote:


https://ww1.microchip.com/downloads/en/DeviceDoc/dsPIC33EPXXX(GP-MC-MU)806-810-814-and-PIC24EPXXX(GP-GU)810-814-Family-Errata.pdf

DS80000526H-page 10

16. Module: UART

When using UTXISEL = 01 (interrupt when last
character is shifted out of the Transmit Shift
Register), and the final character is being shifted
out through the Transmit Shift Register (TSR), the
TX interrupt may occur before the final bit is shifted
out.

Work around:
If it is critical that the interrupt processing occurs
only when all transmit operations are complete,
after which the following work around can be
implemented:

EXAMPLE 2:


Code:
// in UART2 initialization code
...
U2STAbits.UTXISEL0 = 1; // Set to generate TX interrupt when all
U2STAbits.UTXISEL1 = 0; // transmit operations are complete.
...
U2TXInterrupt(void)
{
 while(U2STAbits.TRMT==0); // wait for the transmit buffer to be empty
 ... // process interrupt

Quote:


Hold off the interrupt routine processing by adding
a loop at the beginning of the routine that polls the
transmit shift register empty bit, as shown in
Example 2.

Affected Silicon Revisions: B1


I guess now it's a matter of figuring out if I have a B1 revision.
Ttelmah



Joined: 11 Mar 2010
Posts: 19548

View user's profile Send private message

PostPosted: Tue Dec 08, 2020 6:38 am     Reply with quote

Yes, it is the only thing that I can see that could result if the timing just
happened to be 'wrong' in the packet being started too early....
I suspect it'd require a very particular relationship between the serial
clock, the interrupt response, and the CPU clock. You can see why it'd be
'rare'.
benoitstjean



Joined: 30 Oct 2007
Posts: 566
Location: Ottawa, Ontario, Canada

View user's profile Send private message

PostPosted: Tue Dec 08, 2020 8:04 am     Reply with quote

That's what I figured, some race conditions that occurs once in a blue moon.

Fair enough.

Thanks for your time, again.

Ben
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2005 phpBB Group