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

Help with possible compiler bug or leak in my own code.

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



Joined: 07 Aug 2008
Posts: 17

View user's profile Send private message

Help with possible compiler bug or leak in my own code.
PostPosted: Thu Dec 29, 2016 12:25 pm     Reply with quote

I am not sure what the feature is called but if someone knows it will I hope make googling a little easier. I am using Version 5.011 on Ubuntu as I have been for years. I have tried a newer compiler but had no luck getting my code to compile so I have been staying with this version for now.

Using CCS compiler if one calls a function foo(int8 in) with a string ie foo("asdf") it will auto magically create a loop to call the function for every character.

I have recently started seeing a problem where the output of this was getting corrupt so sending in "asdf" would sometimes result in "asd$".

I presume its a leak or race condition in my code and likely related to my TIMER0 interrupt or other interrupt causing some problem on the stack or somehow corrupting the buffer I am sending. I am also concerned it may be a silicon bug or another compiler bug not preserving the proper registers.

I have looked at the ASM code produce and I am trying to get my brain around how to better track down the problem.

It seems to only happen when I pass a full string "asdf" if I call it with a byte 'A' I so far have not seen it not be an 'A'.

In the end I am not happy with the resulting ASM code if for nothing it would / could be a zero copy operation unlike now where it moves the data from flash to ram and out the uart.


Here is the wrapper it created to call my function send_host() below. Here is where I think things are going bad but I have not yet figured this code out still trying to get my brain around this part. And if this is where its happening how? would an interrupt during this part of code cause an issue?

2452 *
2453 064F4: TBLRD*+
2454 064F6: MOVF FF5,F <- program memory latch
2455 064F8: BZ 6512 <- null termination check
2456 064FA: MOVFF FF6,A31 <- TBLPTRL ? kinda understand this PIC operation.
2457 064FE: MOVFF FF7,A32 <- TBLPTRH ? transfer from flash to ram.
2458 06502: MOVFF FF5,A4B <- TABLAT ? but what is A31 and A32. where is the data put? its 1 byte why 2? seems like it throws away a byte again not efficient.
2459 06506: RCALL 64DA <- call my sub function for each byte but we just got 2 bytes?
2460 06508: MOVFF A31,FF6 <- ? what?
2461 0650C: MOVFF A32,FF7 <- ? ...
2462 06510: BRA 64F4 <- loop
2463 06512: RETURN 0

here is the setup to call this with a constant located at code space @ 0x0AE6
7196 .................... send_host(SMSG_END_PROMPT_DATA);
7197 0AE84: MOVLW E6
7198 0AE86: MOVWF FF6
7199 0AE88: MOVLW 0A
7200 0AE8A: MOVWF FF7
7201 0AE8C: CALL 64F4

another example. the constants are located in code space @ 0AEC
7310 .................... send_host(SMSG_START_LINE_PROMPT);
7311 0AF14: MOVLW EC
7312 0AF16: MOVWF FF6
7313 0AF18: MOVLW 0A
7314 0AF1A: MOVWF FF7
7315 0AF1C: MOVLB 0
7316 0AF1E: CALL 64F4
7317 0AF22: MOVLB 6


Here is the subroutine that is called for each character.
If I inspect thebyte for problems with an if() i detect invalid data such as NULL here
I so far have not seen any bad data here when I send in a single character and bypass the replication call done by the compiler.

18988 064DA: BTFSS x6B.7
18989 064DC: BRA 64E8
18990 .................... fputc(thebyte,COM_B);
18991 064DE: MOVLB A
18992 064E0: MOVF x4B,W
18993 064E2: MOVLB 0
18994 064E4: BRA 64C6
18995 064E6: BRA 64F0

Thanks for any suggestions or ideas in advance!!

Best
Sean M
mathewss



Joined: 07 Aug 2008
Posts: 17

View user's profile Send private message

PostPosted: Thu Dec 29, 2016 12:46 pm     Reply with quote

Hmm maybe some idea.

I am now doing memcpy in my #INT routine moving data from code space to ram so this is doing a TBLPTR operation.

Now I am thinking this is a race condition and the registers are not saved in my #INT. continuing to dig......
temtronic



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

View user's profile Send private message

PostPosted: Thu Dec 29, 2016 1:33 pm     Reply with quote

Obvious place to start when decoding assembler is the PIC instruction set. While the 'core' of instructions is used on all PICS, some are PIC specific so you should really post which PIC you're using.
PIC assembler is quite easy to learn, only 35 instructions, well that's going back 30 years .

You should have dumped the listing file as it's more helpful as it shows the C code that was used to create the assembler.

Another great asset is to download some of the 'application notes' from Microchip,some deal on how to optimize assembler, how to do table reads, etc.

Actually the more you learn/understand assembler the better C programmer you can become if you optimize the C once you've seen the assembled code.

Jay
mathewss



Joined: 07 Aug 2008
Posts: 17

View user's profile Send private message

PostPosted: Thu Dec 29, 2016 2:26 pm     Reply with quote

PIC18F26K22. Most of ASM code is clear as day just like any I have done over the past 35 or more years but some of the PIC specific operations I am not well studied on such as the table read and write operations.

Seems clear as day now when I look at how CCS compiler created my interrupt vector code that it does not save the registers TABLAT, TBLPTRL,TBLPTRH.

I guess I will have to manually add these to my interrupt routines? Seems like some switch should exist to force this or did it just not detect it needed it and that would be a bug?

15 00008: MOVWF 04
16 0000A: MOVFF FD8,05
17 0000E: MOVFF FE0,06
18 00012: MOVLB 0
19 00014: MOVFF FE9,0C
20 00018: MOVFF FEA,07
21 0001C: MOVFF FE1,08
22 00020: MOVFF FE2,09
23 00024: MOVFF FD9,0A
24 00028: MOVFF FDA,0B
25 0002C: MOVFF FF3,12
26 00030: MOVFF FF4,13
27 00034: MOVFF FFA,14



temtronic wrote:
Obvious place to start when decoding assembler is the PIC instruction set. While the 'core' of instructions is used on all PICS, some are PIC specific so you should really post which PIC you're using.
PIC assembler is quite easy to learn, only 35 instructions, well that's going back 30 years .

You should have dumped the listing file as it's more helpful as it shows the C code that was used to create the assembler.

Another great asset is to download some of the 'application notes' from Microchip,some deal on how to optimize assembler, how to do table reads, etc.

Actually the more you learn/understand assembler the better C programmer you can become if you optimize the C once you've seen the assembled code.

Jay
asmboy



Joined: 20 Nov 2007
Posts: 2128
Location: albany ny

View user's profile Send private message AIM Address

PostPosted: Thu Dec 29, 2016 6:44 pm     Reply with quote

What CCS code did you enter that yielded the above ASM info?

this does not look like a .LST file extract from any CCS version i know.

this IS a CCS forum...but your .ASM data does not appear to have been generated by any normal CCS listing.
mathewss



Joined: 07 Aug 2008
Posts: 17

View user's profile Send private message

PostPosted: Thu Dec 29, 2016 6:48 pm     Reply with quote

I am using PCHL or Linux version.

CCS PCH C Compiler, Version 5.011, xxxxx 29-Dec-16 16:38

The last dump was the interrupt vector generated just after the initial jump to program space.

I have also worked around the problem for now but I will need to replace this call wrapper from "ASDF" to CHR that CCS does because it also uses a scratch memory location that changes each time global memory allocation in my code changes and I compile and this scratch memory needed to be preserved as well during my #INT or it would have the same race condition.

Code:
#INT_RTCC
void myrtcc(void) {

#ifdef CCS_BUG_FIX_1
    /* Save and restore the TBLAT, TBLPTRL and TBLPTRH registers modified by memcpy from
     * flash in this routine sometimes.
     */
    #byte TABLAT =0xFF5
    #byte TBLPTRL=0xFF6
    #byte TBLPTRH=0xFF7
    #byte TBLPTRU=0xFF8
    #byte TMPMEM =0xA4C; //FIXME: Will move :( temp memory used by CCS during page read
    static unsigned int8 _TABLAT, _TBLPTRL, _TBLPTRH, _TBLPTRU, _TMPMEM = 0;
    _TABLAT = TABLAT;
    _TBLPTRL = TBLPTRL;
    _TBLPTRH = TBLPTRH;
    _TBLPTRU = TBLPTRU;
    _TMPMEM = TMPMEM;
#endif


//do interrupt stuff here....


#ifdef CCS_BUG_FIX_1
    /* put the registers back */
    TABLAT = _TABLAT;
    TBLPTRL = _TBLPTRL;
    TBLPTRH = _TBLPTRH;
    TBLPTRU = _TBLPTRU;
    TMPMEM = _TMPMEM;
#endif

}
mathewss



Joined: 07 Aug 2008
Posts: 17

View user's profile Send private message

PostPosted: Thu Dec 29, 2016 7:19 pm     Reply with quote

meh.. much better and fewer errors but still I am getting corrupt data sometimes.

Maybe I missed some byte :(
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Thu Dec 29, 2016 8:03 pm     Reply with quote

You didn't post a test program, so I made one and compiled it with
vs. 5.066. This is the Windows version, PCH command line compiler.

Here is the interrupt dispatcher code. This may help you.
Code:
00008:  MOVWF  04
0000A:  MOVFF  STATUS,05
0000E:  MOVFF  BSR,06
00012:  MOVLB  0
00014:  MOVFF  FSR0L,0C
00018:  MOVFF  FSR0H,07
0001C:  MOVFF  FSR1L,08
00020:  MOVFF  FSR1H,09
00024:  MOVFF  FSR2L,0A
00028:  MOVFF  FSR2H,0B
0002C:  MOVFF  PRODL,12
00030:  MOVFF  PRODH,13
00034:  MOVFF  PCLATH,14
00038:  MOVFF  TABLAT,15
0003C:  MOVFF  TBLPTRL,16
00040:  MOVFF  TBLPTRH,17
00044:  MOVFF  00,0E
00048:  MOVFF  01,0F
0004C:  MOVFF  02,10
00050:  MOVFF  03,11
00054:  BTFSS  INTCON.TMR0IE
00056:  GOTO   0060
0005A:  BTFSC  INTCON.TMR0IF
0005C:  GOTO   00AE
00060:  MOVFF  0E,00
00064:  MOVFF  0F,01
00068:  MOVFF  10,02
0006C:  MOVFF  11,03
00070:  MOVFF  0C,FSR0L
00074:  MOVFF  07,FSR0H
00078:  BSF    07.7
0007A:  MOVFF  08,FSR1L
0007E:  MOVFF  09,FSR1H
00082:  MOVFF  0A,FSR2L
00086:  MOVFF  0B,FSR2H
0008A:  MOVFF  12,PRODL
0008E:  MOVFF  13,PRODH
00092:  MOVFF  14,PCLATH
00096:  MOVFF  15,TABLAT
0009A:  MOVFF  16,TBLPTRL
0009E:  MOVFF  17,TBLPTRH
000A2:  MOVF   04,W
000A4:  MOVFF  06,BSR
000A8:  MOVFF  05,STATUS
000AC:  RETFIE 0


If the following program, when compiled with your version, gives a
different result, I'd suggest you upgrade. If, as you said, your program
doesn't compile with the latest version of CCS, then fix the program.
There are too many bugs in an early version like 5.011. There are bugs
in later versions. We find them and note them on this forum. But I don't
see any good reason to use 5.011.


Test program:
Code:

#include <18F26K22.h>
#fuses INTRC_IO,NOWDT,PUT,BROWNOUT
#use delay(clock=4M)
#use rs232(baud=9600, UART1, ERRORS, stream=COM_B)

#define SMSG_END_PROMPT_DATA "asdf"
#define SMSG_START_LINE_PROMPT "xyz"

#INT_RTCC
void myrtcc(void)
{
int8 temp;

temp = 0x55;   
}

//--------------------------
void send_host(char thebyte)
{
fputc(thebyte, COM_B);
}


//=====================================
void main()
{
setup_timer_0(T0_INTERNAL | T0_DIV_1);
clear_interrupt(INT_TIMER0);
enable_interrupts(INT_TIMER0);
enable_interrupts(GLOBAL);

send_host(SMSG_END_PROMPT_DATA);
send_host(SMSG_START_LINE_PROMPT);

while(TRUE);
}
mathewss



Joined: 07 Aug 2008
Posts: 17

View user's profile Send private message

PostPosted: Thu Dec 29, 2016 10:44 pm     Reply with quote

looks like the compiler version you have did save the table registers and here is what I get no save.

Thanks! for doing the test.

As I mentioned I was stuck on this version because at the time of my last update purchase of version 5.028 the compiler would segfault on Linux if one used memcpy() and I could not compile anything. I sent samples and just had not heard back as to the status of the bug report in July 2015.


I will get an updated version this week and test to see if it fixes / creates any new issues. Hopefully they have that sorted out now.

I went ahead and replaced my function and use #DEVICE PASS_STRINGS=IN_RAM. Code space went up by 15% but at least its working for now.


Code:
 *
 13 00000:  GOTO   00DC
 14 *
 15 00008:  MOVWF  04
 16 0000A:  MOVFF  FD8,05
 17 0000E:  MOVFF  FE0,06
 18 00012:  MOVLB  0
 19 00014:  MOVFF  FE9,0C
 20 00018:  MOVFF  FEA,07
 21 0001C:  MOVFF  FE1,08
 22 00020:  MOVFF  FE2,09
 23 00024:  MOVFF  FD9,0A
 24 00028:  MOVFF  FDA,0B
 25 0002C:  MOVFF  FF3,12
 26 00030:  MOVFF  FF4,13
 27 00034:  MOVFF  FFA,14
 28 00038:  MOVFF  00,0E
 29 0003C:  MOVFF  01,0F
 30 00040:  MOVFF  02,10
 31 00044:  MOVFF  03,11
 32 00048:  BTFSS  FF2.5
 33 0004A:  GOTO   0054
 34 0004E:  BTFSC  FF2.2
 35 00050:  GOTO   0096
 36 00054:  MOVFF  0E,00
 37 00058:  MOVFF  0F,01
 38 0005C:  MOVFF  10,02
 39 00060:  MOVFF  11,03
 40 00064:  MOVFF  0C,FE9
 41 00068:  MOVFF  07,FEA
 42 0006C:  BSF    07.7
Ttelmah



Joined: 11 Mar 2010
Posts: 19561

View user's profile Send private message

PostPosted: Fri Dec 30, 2016 2:54 am     Reply with quote

The Linux versions are always rather 'out of sync' with the Windows ones.
However the version number really is before V5 started to work at all reasonably, so perhaps 'not surprised'. However if you find that the later version has problems there is one tiny thing you could try.
Put the option:

#DEVICE CCS4

in your file.
This switches the compiler 'back' to handling the register saves the way they were done on the V4 compilers. Since I don't remember these ever failing to save the TBL registers, it might well fix the problem.
mathewss



Joined: 07 Aug 2008
Posts: 17

View user's profile Send private message

PostPosted: Fri Dec 30, 2016 1:47 pm     Reply with quote

Cool switch thanks! had not noticed that one in docs before. Did a test with the sample code above and it did not seem to change the interrupt vector code it still skips the table registers.

Ttelmah wrote:
The Linux versions are always rather 'out of sync' with the Windows ones.
However the version number really is before V5 started to work at all reasonably, so perhaps 'not surprised'. However if you find that the later version has problems there is one tiny thing you could try.
Put the option:

#DEVICE CCS4

in your file.
This switches the compiler 'back' to handling the register saves the way they were done on the V4 compilers. Since I don't remember these ever failing to save the TBL registers, it might well fix the problem.
Ttelmah



Joined: 11 Mar 2010
Posts: 19561

View user's profile Send private message

PostPosted: Fri Dec 30, 2016 2:04 pm     Reply with quote

Curses. It was worth a try. Looks as if the registers have just been skipped in the code in the early Linux versions then.
Obviously if the later version proves otherwise OK, then this will be the best fix.
mathewss



Joined: 07 Aug 2008
Posts: 17

View user's profile Send private message

PostPosted: Thu Jan 05, 2017 12:17 am     Reply with quote

Ok finally got a chance to test the new compiler version tonight.

CCS PCH C Compiler, Version 5.062
Again this is a pic18f26k22.

Looks like it preserves FF5,FF6 and FF7 but not FF8.
Looking this over I see now that if the code space is only 64k then FFB register should never be needed unless something changes or reads the device id, user or config bits. Is that possibly an issue? hmm. I saved all 4 maybe excessive on my part but I still wonder if that is not a possible bug lurking.

I do not get the fancy register names :( on the linux version still. I have to look em up by hex.

Code:
   14 *
   15 00008:  MOVWF  04
   16 0000A:  MOVFF  FD8,05
   17 0000E:  MOVFF  FE0,06
   18 00012:  MOVLB  0
   19 00014:  MOVFF  FE9,0C
   20 00018:  MOVFF  FEA,07
   21 0001C:  MOVFF  FE1,08
   22 00020:  MOVFF  FE2,09
   23 00024:  MOVFF  FD9,0A
   24 00028:  MOVFF  FDA,0B
   25 0002C:  MOVFF  FF3,12
   26 00030:  MOVFF  FF4,13
   27 00034:  MOVFF  FFA,14
   28 00038:  MOVFF  FF5,15
   29 0003C:  MOVFF  FF6,16
   30 00040:  MOVFF  FF7,17
Ttelmah



Joined: 11 Mar 2010
Posts: 19561

View user's profile Send private message

PostPosted: Thu Jan 05, 2017 1:43 am     Reply with quote

If you compile for a chip that has more than 64K flash, it does save the FF8 register.
So they are being 'sensible' here, and not saving a register that their code does not change.
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