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
 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
Ttelmah



Joined: 11 Mar 2010
Posts: 19225

View user's profile Send private message

PostPosted: Wed Sep 25, 2019 11:38 pm     Reply with quote

OK.

The reason your search did not find much, was you are being too
specific. The same method is used for all error interrupts. Maths and
address error in particular.
Address error is the more common one where this has been covered,
since this interrupt can be caused if you try to do a 16bit access to
an 8bit aligned pointer, an operation that can accidentally be done in
code.

Looking at what you have posted, using sprintf, to put data into
the same buffer it is printing data 'from', seems designed to go wrong.
Problem is that the output will overwrite the end of string 'null', as
it outputs the buffer. Result could easily be a runaway condition.

There is the following note about this with sprintf:
Quote:

If copying takes place between objects that overlap as a result of a call to
sprintf() or snprintf(), the results are undefined.


What you do, is ok, if used like:

sprintf( Buffer, "%s UNABLE TO PROCESS SMS COMMAND, DATA IS SAVING TO SD CARD", Buffer );

Note the lack of the brackets round the %s. This is a standard way of
_appending_ to a buffer.
However this is not legal with the brackets added. The reason is that this
implies the /0 at the end of the buffer will be overwritten before the last
byte of the buffer is read. Result can be code that runs for ever.

It's also illegal for another reason. sprintf requires that the target must be
large enough to hold what is being written. If buffer contains more than
max size <59 characters, it is always going to overflow this.
Ttelmah



Joined: 11 Mar 2010
Posts: 19225

View user's profile Send private message

PostPosted: Thu Sep 26, 2019 1:21 am     Reply with quote

Can confirm (just tested it), that this causes a major program problem.

Arrives at the sprintf. Buffer contains "Test/0".
First loop round becomes "<est/0".
Then

"<<st/0"
"<<<t/0"
"<<<</0"
"<<<<<"
"<<<<<<"
"<<<<<<<"

and goes off walking through memory....

Without the brackets works OK, since the terminating character is not
overwritten before it is read.

It does depend how 'buffer' is generated. If you generate it as a simple
array the compiler does protect the rest of memory. If however it is
allocated using malloc, the code walks off through the whole of memory.
benoitstjean



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

View user's profile Send private message

PostPosted: Thu Sep 26, 2019 4:53 am     Reply with quote

I didn't realize I was printing a string to the same string. Can't see the forest from the trees anymore!


Buffer is declared like this:

#define DATA_STRING_SIZE 133 (that's defined in my header file).

unsigned char Buffer[DATA_STRING_SIZE] = "";


I'll change that when I get to work shortly. I'll use another temporary buffer already declared. I guess I really forgot this one. But up until yesterday (I think), that piece of code has always worked. I know for sure it worked last week.

Basically, if I try to SMS the circuit while it's connected over IP, it'll respond back saying that command is invalid.


I'm not sure I fully understand why the <> symbols I added can cause a problem... shouldn't they just be treated as any other character?

What is being printed in the buffer from the buffer are three letters so the total of that string will be less than 133 bytes for sure.

And just before the string gets printed to, I clear the buffer with NULL's using a memset
Ttelmah



Joined: 11 Mar 2010
Posts: 19225

View user's profile Send private message

PostPosted: Thu Sep 26, 2019 5:26 am     Reply with quote

It's the displacement caused.

If you had no extra character in the format string, the %s would copy
the values from buffer into the same location they already occupy.
With the extra character in from of the %s, it is copying characters from
buffer into the next character in the output. Problem is this results in the
'\0' at the end of the values already there being overwritten. Disaster...
temtronic



Joined: 01 Jul 2010
Posts: 9113
Location: Greensville,Ontario

View user's profile Send private message

PostPosted: Thu Sep 26, 2019 6:04 am     Reply with quote

re: ...and goes off walking through memory....
and
...Can't see the forest from the trees anymore!

sounds like every day around here for me Laughing

One day Mr. T's head wll explode from all the PIC knowledge that's trapped up there !
benoitstjean



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

View user's profile Send private message

PostPosted: Thu Sep 26, 2019 6:18 am     Reply with quote

Brilliant. That was the problem. Smart man. A million thanks.

In my 100K+ lines of pure C code, that's the only place where I have an sprintf printing a string inside itself.... I guess that was just overlooked. I searched in all files for 'sprintf' and checked all of them and that's the only place...

I guess I never encountered this particular problem because this line has worked since the early programming stage so its always been like this.

Perhaps it all of a sudden started to fail because of other code I added and how the compiler makes use of the program space.

So then, to back to the stack interrupt itself... to understand how to troubleshoot it and for other users....

Not sure if this will help but I found a bit of code below in another post. Again, this is getting beyond my level of comprehension...

Using that code, I forced the stack interrupt error to occur. The resulting printout is after the code:

Code:

   int16 w[16];
   int16 h,l;
   int32 val;

   #asm
      POP h;
      POP l;
   #endasm
   
   #word W0REG=0
   #word W1REG=2
   #word W2REG=4
   #word W3REG=6
   #word W4REG=8
   #word W5REG=10
   #word W6REG=12
   #word W7REG=14
   #word W8REG=16
   #word W9REG=18
   #word W10REG=20
   #word W11REG=22
   #word W12REG=24
   #word W13REG=26
   #word W14REG=28
   #word W15REG=30

   w[0] = W0REG;
   w[1] = W1REG;
   w[2] = W2REG;
   w[3] = W3REG;
   w[4] = W4REG;
   w[5] = W5REG;
   w[6] = W6REG;
   w[7] = W7REG;
   w[8] = W8REG;
   w[9] = W9REG;
   w[10] = W10REG;
   w[11] = W11REG;
   w[12] = W12REG;
   w[13] = W13REG;
   w[14] = W14REG;
   w[15] = W15REG;
   
   h &= 0x00FF;
   
   val = make32(h, l);
   val -= 2;
   
   // this address might be off by 2 bytes
   fprintf( MONITOR_SERIAL, "\r\n\nSTACK FAULT @ 0x%LX ", val );
   
   for( l = 0; l < 16 ; l++ )
   {
      fprintf( MONITOR_SERIAL, "\n\rW%U:%LX", l, w[l] );
   }

Printout:
Code:

STACK FAULT @ 0x3EFE
W0:1C
W1:4740
W2:6600
W3:4680
W4:1C0
W5:FFFF
W6:172C
W7:FF
W8:0
W9:0
W10:0
W11:C2D8
W12:3F00
W13:0
W14:0
W15:D024

Does this point to any valuable information that could help identify where the problem is?

Really, all I want is a piece of code similar to the address trap interrupt where it prints the address of where the problem occured. Your code below has saved me many times over the years. I just don't have anything for the stack interrupt.

Yesterday you mentioned something about "the actual amount that has to be subtracted from the top of stack depends on the compiler version"... where can I find that?

Your code:
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: 19225

View user's profile Send private message

PostPosted: Thu Sep 26, 2019 7:08 am     Reply with quote

Smile

Yes. How bad the result will be, will depend on if there is another variable
beyond the end of the buffer containing a '0'. If there is, the problem code
will stop at this point, so the result may only be a couple of unwanted
characters (or even none). However if this gets changed, the genie is
released from the bottle.... :(

The new assembler you are posting, is assuming that
the return address is at the top of the stack. It isn't. It can be made to
work by flagging the interrupt as 'FAST' so the compiler does not write
to the stack. Then there is no offset needed to access the return
address. Unless this is flagged like this, the address will be wrong.

On the subtraction amount the key is how much data CCS put on the stack.
When an interrupt is called they save all register that may be used by the
code. The older compilers saved a particular number, then as some
point they increased how many registers are saved.
If you look at the interrupt assembler, on a 'current' compiler, you get:
Code:

0388:  PUSH    42
038A:  PUSH    36
038C:  PUSH    32
038E:  MOV     W0,[W15++]
0390:  MOV     #2,W0
0392:  REPEAT  #C
0394:  MOV     [W0++],[W15++]

W15, is the stack pointer.
This results in 27 pairs of bytes being pushed to the stack. So to go back
to where the return address is on the stack, you have to subtract 56. On
the older (V4?) compilers you only had to subtract 54. The actual change
was a few versions 'after' the launch of V5, but when it was still almost
a 'beta'.
benoitstjean



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

View user's profile Send private message

PostPosted: Fri Sep 27, 2019 4:53 am     Reply with quote

Well, I guess my problems are gone now.

I added at the top of my main .h file #device NESTED_INTERRUPTS=TRUE.

I also changed #INT_RDA to #INT_RDA LEVEL=6.

As for the INT_UART1E interrupt error, it seems to happen quite less now. Actually, yesterday, over a 30 minute running time streaming non-stop 64kbps data over the UART to a remote IP client, I haven't gotten a single error. While the data is sent out the modem, data is also received from the modem such as modem messages like signal strength, network type update etc but also commands from the remote client.

As for the funky modem errors I was getting:

F9 01 EF 0B E3 07 0F 0D 01 79 F9
This means that channel 3 is allowed to send data.

F9 01 EF 0B E3 07 0F 07 01 79 F9
This means that the buffer for channel 3 is full. No more data is allowed to be sent through channel 3.

Channel 3 is where the MCU is sending the 64kbps data on the virtual UART using the multiplexer protocol.

When these two errors were returned from the modem to the PIC, that's when I started to get INT_UART1E interrupts. All of the above + a few things I modified now makes that the circuit seem to be as stable as it has ever been.

Thanks Ttelmah and newguy for your time and help, it's very appreciated!

I just realized Ttelmah that your name is Hamlet backwards!

Ben
newguy



Joined: 24 Jun 2004
Posts: 1902

View user's profile Send private message

PostPosted: Fri Sep 27, 2019 7:56 am     Reply with quote

Glad you have it sorted. Hopefully no more surprises in store!
Ttelmah



Joined: 11 Mar 2010
Posts: 19225

View user's profile Send private message

PostPosted: Fri Sep 27, 2019 8:53 am     Reply with quote

Dead right. With two t's (Shakespeare couldn't spell!...) - actually probably
true, he may well have heard the name and not seen it spelt, since when he
was writing, my ancestors were operating a trading barque between the
Low Countries and the Vale of Evesham. So 'Hamlett' trading with Denmark,
makes it very easy for him to have created the 'Prince'. The name comes
from the Low Country area, originally spelt Hamblett. Smile

Glad you have it working properly. Smile
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
Page 4 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