|
|
View previous topic :: View next topic |
Author |
Message |
mathewss
Joined: 07 Aug 2008 Posts: 17
|
Help with possible compiler bug or leak in my own code. |
Posted: Thu Dec 29, 2016 12:25 pm |
|
|
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
|
|
Posted: Thu Dec 29, 2016 12:46 pm |
|
|
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: 9226 Location: Greensville,Ontario
|
|
Posted: Thu Dec 29, 2016 1:33 pm |
|
|
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
|
|
Posted: Thu Dec 29, 2016 2:26 pm |
|
|
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
|
|
Posted: Thu Dec 29, 2016 6:44 pm |
|
|
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
|
|
Posted: Thu Dec 29, 2016 6:48 pm |
|
|
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
|
|
Posted: Thu Dec 29, 2016 7:19 pm |
|
|
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
|
|
Posted: Thu Dec 29, 2016 8:03 pm |
|
|
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
|
|
Posted: Thu Dec 29, 2016 10:44 pm |
|
|
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: 19513
|
|
Posted: Fri Dec 30, 2016 2:54 am |
|
|
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
|
|
Posted: Fri Dec 30, 2016 1:47 pm |
|
|
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: 19513
|
|
Posted: Fri Dec 30, 2016 2:04 pm |
|
|
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
|
|
Posted: Thu Jan 05, 2017 12:17 am |
|
|
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: 19513
|
|
Posted: Thu Jan 05, 2017 1:43 am |
|
|
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. |
|
|
|
|
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
|