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 support@ccsinfo.com

[Solved] PIC24EP512 - Can a DMA transfer be paused?
Goto page Previous  1, 2, 3, 4  Next
 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
newguy



Joined: 24 Jun 2004
Posts: 1902

View user's profile Send private message

PostPosted: Tue Sep 24, 2019 2:09 pm     Reply with quote

Sounds like something that's dogged me on & off when using interrupt driven transmits (either transmit buffer empty [TBE] or DMA tied to TBE).

Any chance your logic which dictates what gets sent (I think you said something about a buffer, with a transmit write index and transmit read index?) gets out of sync? Unless the logic for how the buffer gets filled and subsequently emptied is rock solid, your "empty the buffer" logic can 'runaway' quite easily. Given that there is suddenly no longer a ~4ms gap between transmit bursts, that is reminiscent of the times my transmits "ranaway" on me.
benoitstjean



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

View user's profile Send private message

PostPosted: Tue Sep 24, 2019 2:32 pm     Reply with quote

Just as I was about to leave work, I tried one last thing and magic! Stuff seems to be working well!

So first thing tomorrow I will investigate the line I commented-out. I also changed the timer interrupt for the 'sensors' message to be reported after 12 seconds rather than 10 and after a few minutes of streaming, I no longer get the INT_UART1E error interrupt.

On top of all of that, I was also seeing that the modem was sending me lots of UIH MSC frames and the documentation on that message is quite vague even with the 3GPP specifications. I have contacted an FAE with the modem manufacturer and he will provide more details tomorrow.

By commenting-out the line mentioned above, the UIH MSC messages from the modem disappeared all of a sudden. So I am starting to think that they may have meant something about the quantity and rate of data I was sending it.

Ben
benoitstjean



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

View user's profile Send private message

PostPosted: Wed Sep 25, 2019 4:39 am     Reply with quote

Newguy, sorry, I guess I sent my message and didn't realize you had sent one!

Yeah, exactly what you're saying, "runaway". Wasn't sure how to express it... my view of that was like the Plinko game on the Price is Right... all goes through following a path based on events caused by the little pegs and all of a sudden, remove all the pegs from the Plinko board and pucks just fly through! Just like my code as if all of a sudden it just goes through non-stop.

I don't see how it can get out of sync because the line immediately before the dma_start() sets the state of the transfer:
Code:

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

The DMA.IsTransferDone will only be set to TRUE when the DMA transfer is complete in the #INT_DMA0 interrupt, in the #INT_DMAERR interrupt of if my "no DMA interrupt" timer timeout interrupt. That flag is also a condition for the Process_TXQueue() to get serviced.

Getting back to work soon, I'll continue to investigate.

Ben
Ttelmah



Joined: 11 Mar 2010
Posts: 19224

View user's profile Send private message

PostPosted: Wed Sep 25, 2019 6:27 am     Reply with quote

You don't actually show that 'DMA.IsransferDone is tested for being
false before the code to start it again is called...
benoitstjean



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

View user's profile Send private message

PostPosted: Wed Sep 25, 2019 6:42 am     Reply with quote

Oh it's somewhere else.

I have a function called SYSTEM_GenerateDMAPacket( parameters ) and a 'service' function called SYSTEM_DequeueTXMessage().

The 'service' function checks for new messages to process out of the TX queue.

However, it will only process the next message in the queue if DMA is done and the only way DMA can be done sending is when it fired one of the interrupts (done or error) or the transfer timed-out due to either of the interrupts not firing.

Ben
newguy



Joined: 24 Jun 2004
Posts: 1902

View user's profile Send private message

PostPosted: Wed Sep 25, 2019 7:08 am     Reply with quote

benoitstjean wrote:
Newguy, sorry, I guess I sent my message and didn't realize you had sent one!

Yeah, exactly what you're saying, "runaway". Wasn't sure how to express it... my view of that was like the Plinko game on the Price is Right... all goes through following a path based on events caused by the little pegs and all of a sudden, remove all the pegs from the Plinko board and pucks just fly through! Just like my code as if all of a sudden it just goes through non-stop.

I don't see how it can get out of sync because the line immediately before the dma_start() sets the state of the transfer:

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

The DMA.IsTransferDone will only be set to TRUE when the DMA transfer is complete in the #INT_DMA0 interrupt, in the #INT_DMAERR interrupt of if my "no DMA interrupt" timer timeout interrupt. That flag is also a condition for the Process_TXQueue() to get serviced.

Getting back to work soon, I'll continue to investigate.

Ben


That's probably where your problem lies. An unexpected program execution "path" is leading to a race condition. Can you do a trace on your data to see if things are getting repeated, over and over? My issues have always revolved around my circular buffer. Code has access to the "transmit write" pointer of the buffer. A different function examines the write pointer and a different transmit read pointer. If they're different, there's stuff in the buffer which needs to be sent. This routine is responsible for loading the UART (or whatever), and then reloading it when the data has successfully been sent.

What I'd sometimes find is that everything would work fine until it didn't - and then I'd get one massive "avalanche" of transmit data out of the UART. The issue boiled down to my pointers getting out of sync, and then the "send" routine would churn through the entire circular buffer in order to get back into sync.

Any test of a flag which can be toggled in an interrupt must be wrapped in a disable interrupt/ test here /enable interrupt pair. Try that first.
Ttelmah



Joined: 11 Mar 2010
Posts: 19224

View user's profile Send private message

PostPosted: Wed Sep 25, 2019 7:10 am     Reply with quote

OK.
One possibility is that you are running into the same problem involved
here:
<http://www.ccsinfo.com/forum/viewtopic.php?t=58220>

Here, the poster found that bit based variables, that are allocated into
bytes that share other bits with values changes inside an interrupt, could
end up being corrupted. Worth looking very carefully at your variable
allocation, and making sure that you do not have any bit variables where
this could apply.
benoitstjean



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

View user's profile Send private message

PostPosted: Wed Sep 25, 2019 10:57 am     Reply with quote

Although it may not be the best idea, I use unsigned int8 for a 'bool' type (typedef unsigned int8 bool) and for these types, I always set them to TRUE or FALSE.

I realize that taking-up an entire byte for a bool type is not ideal, however, the PIC24 has so much space that it doesn't really affect anything. Also, I don't have a million bool flags, I have probably less than 50.

Back to the problems, I think I may have found a solution but it pertains to my stuff so there's no point going into too many details.

By looking at the data sampled by my analyzer, I realized that when audio started to stutter, I checked what IP message was last set to the PC app and I found a pattern. I don't think also that I really need this code any longer so by commenting it out and re-compiling, all seems to be working as expected:

- The data is consistently sent at a regular interval.
- I don't seem to be getting any random UART errors.
- Modem no longer sends me a bunch of MSC framed.

The modem MSC frames, I think (still waiting on manufacturer to get back) were caused by probably an excess of data being sent to it and it was telling me to 'hold-off' but since I cannot find appropriate documentation for that frame, it's difficult to tell and that's why I'm waiting for a response.


This error also caused the data to not be sent at regular intervals since data was just "slipping through".

Anyhow, I'll continue to investigate a bit because now I have audio thats been properly streaming for about 10 minutes but I get the odd cut and when I check the analyzer, the packets following the cut are immediately one after the other without the 4.8ms gap in-between.

I'll keep posting on new findings.
Ttelmah



Joined: 11 Mar 2010
Posts: 19224

View user's profile Send private message

PostPosted: Wed Sep 25, 2019 12:03 pm     Reply with quote

at least you are moving 'forwards'... Smile
benoitstjean



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

View user's profile Send private message

PostPosted: Wed Sep 25, 2019 1:41 pm     Reply with quote

Ohhh lordy lordy lordy....

How do I get rid of stack errors and how, in the #INT_STACKERR, can I capture some information about what is causing this?!

Just as everything was going well...

I had #build ( stack=1024 ) but I changed it to 2048 but didn't change a thing...

[EDIT] I can reproduce the problem but I just need to know how to capture *whatever* in this interrupt and display it so I can find what/where is the cause of the problem. Any idea what I can print out? Any registers? Any value?

[EDIT] A few years ago, Ttelmah you had me add the following code snippet (you handed it to me) in the #INT_ADDRERR interrupt and that helped me greatly. Any kind of code I can add for the stack interrupt error? This is getting way past my knowledge...
Code:

   unsigned long trapaddr;

   #asm
   mov w15, w0
   sub #38, w0
   mov [w0++], w1
   mov w1, trapaddr
   mov [w0], w1
   and #0x7f, w1
   mov w1, trapaddr+2
   #endasm
Ttelmah



Joined: 11 Mar 2010
Posts: 19224

View user's profile Send private message

PostPosted: Wed Sep 25, 2019 1:48 pm     Reply with quote

The most likely thing if increasing the stack doesn't solve it, is that it is a
stack _underflow_, not overflow. Something is popping data off the stack
that is not there.
In all interrupts, you can extract what is in the stack when you arrive
at the handler to see what program address actually triggered the error.
Has been described here several times.
benoitstjean



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

View user's profile Send private message

PostPosted: Wed Sep 25, 2019 1:49 pm     Reply with quote

Would the code above that I use in the #INT_ADDRERR work?

This is beyond my knowledge quite frankly... Or I'll have to do a bit of research...
Ttelmah



Joined: 11 Mar 2010
Posts: 19224

View user's profile Send private message

PostPosted: Wed Sep 25, 2019 1:53 pm     Reply with quote

Looks right, though the actual amount that has to be subtracted from
the top of stack depends on the compiler version.
However remember the address given is the _return_ address. The actual
fault is caused by the instruction before this.
benoitstjean



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

View user's profile Send private message

PostPosted: Wed Sep 25, 2019 1:55 pm     Reply with quote

Right there, you lost me with "the actual amount that has to be subtracted from the top of stack".

I'm using a bastardized version... IDE 5.071 but the rest is 5.026...
benoitstjean



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

View user's profile Send private message

PostPosted: Wed Sep 25, 2019 2:03 pm     Reply with quote

I just searched the forum and there's only 12 results when I search for "INT_STACKERR" and none of them show how to find information on what causes the stack error.

I'm trying to decipher the assembly code you had given me a long time ago because I'd like to apply it to the stack interrupt but again, this is beyond what I understand. I have the Section 29. Instruction Set document DS31029A but it's really gibberish.

I know the following may not mean much but the code below causes the stack interrupt error, commenting-out everything except the return does not crash. Not sure which line exactly causes the crash, I may have to go by elemination tomorrow by eleminating one line at a time, compiling and testing...


.................... if( Data.IsSaving == TRUE )
473EA: PUSH 42B8
473EC: MOV [--W15],W0
473EE: LSR W0,#8,W0
473F0: SE W0,W0
473F2: CP W0,#1
473F4: BRA NZ,47438
.................... {
.................... sprintf( Buffer, "<%s> UNABLE TO PROCESS SMS COMMAND, DATA IS SAVING TO SD CARD", Buffer );
473F6: MOV #55BC,W4
473F8: MOV W4,10F4
473FA: MOV.B #3C,W0L
473FC: CALL FFEA
47400: MOV #55BC,W1
47402: CP0.B [W1]
47404: BRA Z,47416
47406: MOV W1,[W15++]
47408: MOV W1,W4
4740A: MOV.B [W4],W0L
4740C: CALL FFEA
47410: MOV [--W15],W1
47412: INC W1,W1
47414: BRA 47402
47416: MOV #3,W1
47418: MOV W1,W0
4741A: CLR.B 1
4741C: CALL 46B6
47420: INC W1,W1
47422: MOV W1,[W15++]
47424: MOV W0,[W15++]
47426: MOV [--W15],W0
47428: CALL FFEA
4742C: MOV [--W15],W1
4742E: MOV #40,W0
47430: CPSGT W1,W0
47432: BRA 47418
.................... }
47434: GOTO 4748C
.................... else
.................... {
.................... sprintf( Buffer, "<%s> UNABLE TO PROCESS SMS COMMAND, CONNECTED TO %s", Buffer, Address );
47438: MOV #55BC,W4
4743A: MOV W4,10F4
4743C: MOV.B #3C,W0L
4743E: CALL FFEA
47442: MOV #55BC,W1
47444: CP0.B [W1]
47446: BRA Z,47458
47448: MOV W1,[W15++]
4744A: MOV W1,W4
4744C: MOV.B [W4],W0L
4744E: CALL FFEA
47452: MOV [--W15],W1
47454: INC W1,W1
47456: BRA 47444
47458: MOV #3,W1
4745A: MOV W1,W0
4745C: CLR.B 1
4745E: CALL 46FE
47462: INC W1,W1
47464: MOV W1,[W15++]
47466: MOV W0,[W15++]
47468: MOV [--W15],W0
4746A: CALL FFEA
4746E: MOV [--W15],W1
47470: MOV #30,W0
47472: CPSGT W1,W0
47474: BRA 4745A
47476: MOV #3E6E,W1
47478: CP0.B [W1]
4747A: BRA Z,4748C
4747C: MOV W1,[W15++]
4747E: MOV W1,W4
47480: MOV.B [W4],W0L
47482: CALL FFEA
47486: MOV [--W15],W1
47488: INC W1,W1
4748A: BRA 47478
.................... }
....................
.................... SMS_Send( Number, Buffer, 22 );
4748C: MOV #3E88,W4
4748E: MOV W4,6150
47490: MOV #55BC,W4
47492: MOV W4,6152
47494: MOV #16,W4
47496: MOV W4,6154
47498: MOV #0,W4
4749A: MOV W4,6156
4749C: CALL 16046
....................
.................... return;
474A0: BRA 4B492
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Goto page Previous  1, 2, 3, 4  Next
Page 3 of 4

 
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