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

18F6722 possible math issue from compiler v5.074 to 5.105
Goto page 1, 2  Next
 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
pmuldoon



Joined: 26 Sep 2003
Posts: 212
Location: Northern Indiana

View user's profile Send private message

18F6722 possible math issue from compiler v5.074 to 5.105
PostPosted: Wed Jan 19, 2022 9:30 am     Reply with quote

I've sent this off to tech support, but I thought you guys might spot something quicker.

I'm not sure if it's my code or a math issue with the latest compiler. My code worked fine in previous versions of the compiler.

The code compiled in 2019 worked and the code I recently compiled has the issue. From the dates of my compiler updates I
concluded it must be a difference between v5.074 and v5.105.

Unfortunately I don't save the lst files of previous iterations of code. Only the source & hex. And I've never had to try to compile with a previous version of the compiler, so I'm not sure how to do that. I'm hoping this might be enough to notice a problem with my code or the compiler.

This is the context of the problem line.
The intention is to calculate a count that would be a percentage of full-scale.
Default_SP[i] is a % of full scale of the adc count. range 0-100 with 255=unused.

With i=1 SP = 35 and I expect 1433 but get 20971. The lst is a bit overwhelming and I'm not confident I could read it well enough to spot a problem.
Code:

 #include <18F6722.h>        // changed F or LF as needed
    .
    .
    const    unsigned int    Default_SP[CALPOINTS]={0,35,100,255,255,255,255,255,255,255,255};    // fill from bottom, ascending order; unused must be 255
    .
    .
    .

    void Load_Table_Defaults(int Option)
    {
        .
        .
        .
        Active.Table.FlowCnt[i]=((int32)Default_SP[i]*4095)/100;    // was =((int32)Default_SP[i]*40 (you can ignore the comment, that was a very old change)
        if(Default_SP[i]==100)Active.Table.FlowCnt[i]=4000;            // adjust so 98% flow = max
        .
        .
        .
    }

and this is the current list:
Code:

....................         Active.Table.FlowCnt[i]=((int32)Default_SP[i]*4095)/100;    // was =((int32)Default_SP[i]*40
036B6:  BCF    FD8.0
036B8:  MOVLB  1
036BA:  RLCF   xEA,W
036BC:  CLRF   03
036BE:  ADDLW  89
036C0:  MOVWF  FE9
036C2:  MOVLW  01
036C4:  ADDWFC 03,W
036C6:  MOVWF  FEA
036C8:  CLRF   03
036CA:  MOVF   xEA,W
036CC:  MOVLB  0
036CE:  CALL   00CA
036D2:  MOVWF  01
036D4:  MOVLB  1
036D6:  CLRF   xEF
036D8:  CLRF   xEE
036DA:  MOVWF  xED
036DC:  MOVFF  FEA,1F2
036E0:  MOVFF  FE9,1F1
036E4:  MOVLB  2
036E6:  CLRF   x1D
036E8:  MOVLB  2
036EA:  CLRF   x1C
036EC:  MOVLB  2
036EE:  CLRF   x1B
036F0:  MOVLB  1
036F2:  MOVFF  FE8,21A
036F6:  CLRF   x21
036F8:  CLRF   x20
036FA:  MOVLW  0F
036FC:  MOVWF  x1F
036FE:  SETF   x1E
03700:  MOVLB  0
03702:  RCALL  30FA
03704:  MOVFF  1F2,FEA
03708:  MOVFF  1F1,FE9
0370C:  MOVFF  03,1F0
03710:  MOVFF  02,1EF
03714:  MOVFF  01,1EE
03718:  MOVFF  00,1ED
0371C:  MOVFF  FEA,1F4
03720:  MOVFF  FE9,1F3
03724:  BCF    FD8.1
03726:  MOVFF  03,220
0372A:  MOVFF  02,21F
0372E:  MOVFF  01,21E
03732:  MOVFF  00,21D
03736:  MOVLB  2
03738:  CLRF   x24
0373A:  CLRF   x23
0373C:  CLRF   x22
0373E:  MOVLW  64
03740:  MOVWF  x21
03742:  MOVLB  0
03744:  RCALL  3156
03746:  MOVFF  1F4,FEA
0374A:  MOVFF  1F3,FE9
0374E:  MOVFF  01,FEC
03752:  MOVF   FED,F
03754:  MOVFF  00,FEF



Thoughts?
PCM programmer



Joined: 06 Sep 2003
Posts: 21667

View user's profile Send private message

PostPosted: Wed Jan 19, 2022 9:58 am     Reply with quote

Make us a test program that fails.

I made this one and it gives me 1433.
Code:

#include <18F6722.h>   
#fuses NOWDT 
#use delay(internal=4M)
#use rs232(UART1, baud=9600, ERRORS)

const unsigned int Default_SP[]=
{0,35,100,255,255,255,255,255,255,255,255};

//=================================
void main()
{
int16 result;
int i;

i = 1;

result = ((int32)Default_SP[i]*4095)/100;   

printf("result = %lu \r", result);
   
while(TRUE);
}
pmuldoon



Joined: 26 Sep 2003
Posts: 212
Location: Northern Indiana

View user's profile Send private message

PostPosted: Wed Jan 19, 2022 11:12 am     Reply with quote

Hmm...well that's embarrassing!

I just copied your code into a test program and ran it thru PICSIM and mine worked, too.
I guess I should have tried that first, eh?

I will have to dig deeper. I was certain this is where the problem was being created.

Thanks PCM for helping me rule out this line of code. I guess I'll have to look at the other 3000 lines of code now, LOL.
Ttelmah



Joined: 11 Mar 2010
Posts: 18130

View user's profile Send private message

PostPosted: Wed Jan 19, 2022 11:12 am     Reply with quote

FYI, the 'overwhelming' lst, is only a tiny part of the code involved.
The actual maths, is in the RCALL 3156, and the RCALL 30FA routines....
What you have posted is perhaps one tenth of the actual code... Sad
pmuldoon



Joined: 26 Sep 2003
Posts: 212
Location: Northern Indiana

View user's profile Send private message

PostPosted: Thu Jan 27, 2022 6:50 am     Reply with quote

Update:
Even though the short example version worked, the full program still did not.
I commented out the entire program and got it down to one line of code that would cause the failed calculation. So I got the enter program down to 2 lines in Main().

The first one was the LoadDefault() that had the math problem. The second was a TerminalCheck() function that checked for terminal activity and, if a key were pressed, would launch the terminal menu/interaction etc. I could uncomment all of the other code and it would calc properly as long as the TerminalCheck() remained commented out.

The TerminalCheck() contained a lot of functions and some of those functions called functions. So it had a lot of potential depth, although none of it actually executed because no key was ever pressed. I commented out it's contents and the calc worked again. Uncommented and it failed.

That was the point where I figured I was probably wasting my time and sent it off to CCS support. It seemed more likely to be a hidden issue within the compiler rather than the result of some awkward coding.

CCS responded remarkably fast with a patch. But, unfortunately, no explanation. I just sent a reply asking for a brief summary of what the problem was. I put a lot of time & effort into trying to figure out if it was me or the compiler, and in trying to narrow it down (and trying to create a simple test program). Hopefully they will respond with some info and I'll be a little smarter for it.

Bottom line: I'm glad the problem is behind me and CCS support is great! I just wish I could have posted a better answer here.
pmuldoon



Joined: 26 Sep 2003
Posts: 212
Location: Northern Indiana

View user's profile Send private message

PostPosted: Thu Jan 27, 2022 8:45 am     Reply with quote

response from CCS support:
"It was an optimization bug related to the CLRF instruction. A bank selection instruction was incorrectly removed.
It showed up when that statement used registers in both bank 1 and 2. When all the registers used where bank 1
it worked. #opt 0 should also have worked."

So, I guess it was because of the compound math statement. That would explain why, when I broke it down, it worked.

I totally get how that crazy bank switching can be complicated!!!


Code:

TestVal = Default_SP[i];   
TestVal = (TestVal * 4095) / 100;                        
printf("\nusing separate var: =  %u -> %ld", Default_SP[i], TestVal);   

Vs:
Code:

printf("\ncast =  %ld",(((signed int32)Default_SP[i]*4095)/100));   
Ttelmah



Joined: 11 Mar 2010
Posts: 18130

View user's profile Send private message

PostPosted: Thu Jan 27, 2022 10:42 am     Reply with quote

They seem to have done quite a few optimisation changes around 5.100,
suspect this is from then. These are what cause the problems for me
when using the multiple interrupt levels in PCD. before this local variables
in different priority interrupts respect each other, after this they don't.
Seems they are going a little too far on some of the 'savings'... Sad
pmuldoon



Joined: 26 Sep 2003
Posts: 212
Location: Northern Indiana

View user's profile Send private message

PostPosted: Thu Jan 27, 2022 11:51 am     Reply with quote

another one of my sources of confusion. This is right out of the CCS manual:
Quote:

#opt
Syntax:
#opt n
Elements:
All Devices: n is the optimization level 1-9 or by using the word "compress" for PIC18
and Enhanced PIC16 families.
[PCD] All Devices: n is the optimization level 0-9
Description:
The optimization level is set with this directive. This setting applies to the entire program
and may appear anywhere in the file. The default is 9 for normal. When Compress is
specified the optimization is set to an extreme level that causes a very tight ROM image,
the code is optimized for space, not speed. Debugging with this level my be more
difficult.
Examples:
#opt5


I don't know what the number means. Is 0 optimized for speed or for space? And apparently "compress" is not the same as any of the #'s.
Although it would be easy to compile and see the size difference, it would have been better if they just stated it.

Luckily I've never touched that option. Chip memory sizes have increased faster than my ability to write slow, bloated code. Wink
Ttelmah



Joined: 11 Mar 2010
Posts: 18130

View user's profile Send private message

PostPosted: Thu Jan 27, 2022 11:54 am     Reply with quote

0 turns it off.

The point is that the problem is part of their optimisation, and they are
saying that if you use zero (so this is off), this isn't done.
kda406



Joined: 17 Sep 2003
Posts: 97
Location: Atlanta, GA, USA

View user's profile Send private message

PostPosted: Thu Jan 27, 2022 2:06 pm     Reply with quote

I cannot believe I ran into this thread today.

I have been having to simplify single, complex math statements down to 2-3-4 lines since around 5.09x, Ttelmah. Statements that have worked for years through 3,x, 4.x, even in other C compliers, suddenly no longer work in 5.x and must be rewritten.

Recently, I have been struggling with interrupts. I could not understand why ISRs that had worked for years with CCS and various PIC families no longer worked. Today an ISR for INT0 stopped working. I was troubleshooting that.

I noticed I was using optimization level 9 and could not remember if that was correct. I saw the same ridiculous explanation in the manual as was quoted above. I was confused so I searched the forum and found this thread where you are discussing the same issues I'm having today. Wow.

So I changed my #opt to 0 and guess what? The ISR for INT0 that I have been troubleshooting for 3 days magically works again. Mad

I cannot begin to total up all the lost-time troubleshooting, rewriting, and simplifying math code that used to work recently. I bet it is months of lost productivity. Frustrating! Mad

Even so, I say thanks for the helpful discussion guys.

-Kyle
temtronic



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

View user's profile Send private message

PostPosted: Fri Jan 28, 2022 6:13 am     Reply with quote

I'm thinking, yeah..like the dinosaur I am.., that the 'optimization' default should be ZERO.
Only when a program is 'up and running', should 'optimization' be enabled, kinda like the WDT.

I'm betting no one KNOWS what happens for levels 1 thru 9, what exactly the compiler's doing or HOW it's doing it. Maybe level 4 is great for project 'x', and 7 perfect for project 'Z'.

It is scary that a feature designed to HELP programmers, actually can cause so much pain !
kda406



Joined: 17 Sep 2003
Posts: 97
Location: Atlanta, GA, USA

View user's profile Send private message

PostPosted: Fri Jan 28, 2022 7:28 am     Reply with quote

Especially considering the recent "improvements", I agree, it should be zero unless set otherwise. Good idea.

Every one of my projects includes the same header file as the first element. I'm curious about using #opt 0 as a line there.

Here is why I ask about the inline directive though. I use multiple compile units (MCU) and my larger projects have dozens of program and header files. If your code is solid and elegant it works. I use MPLabX and love it - it's the same as NetBeans that I use for C and other languages mostly for programming Windows and Linux stuff. With MPLabX, you set the project up and hidden in the project is an assignment for code optimization. It defaults to 9. It passes this as a CL parameter to the compiler (and linker?) as it builds the project. The projects are setup automatically and I will need to remember to punch in and change the optimization parameter on every project. Sad

Do any of you know: If I put #opt 0 in the configuration header of every compile unit and MPLabX passes the default CL parameter of 9, which one will "win" and be used for the build?
Ttelmah



Joined: 11 Mar 2010
Posts: 18130

View user's profile Send private message

PostPosted: Fri Jan 28, 2022 8:37 am     Reply with quote

Hm. I'd have expected the ones 'in code' to override the ones on the build
line. However the answer would probably be to test. You can usually see
changes in the OPT level in the build size, so see if the code gets a little
larger with the optimisation turned down in code. If it does, you know
which has priority.
temtronic



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

View user's profile Send private message

PostPosted: Fri Jan 28, 2022 8:45 am     Reply with quote

hmmmm I wouldn't guess (it'd be wrong...Murphy's Laws..)
yes, try a small program and see what happens...
kda406



Joined: 17 Sep 2003
Posts: 97
Location: Atlanta, GA, USA

View user's profile Send private message

PostPosted: Fri Jan 28, 2022 9:00 am     Reply with quote

GOOD NEWS

I was hoping one of you guys could just tell me... Wink

This morning I'm working on a project with just a few compile units. No math to simplify like the OP for this thread, but this one does have the ISR routines that work with optimize set to 0 and simply do not work (at all) when set to 9.

I put #opt 0 as the first line of the single config header that is included in every compile unit. I made sure the project (IDE) was set for the default 9, and verified the CL arguments passed to the compiler included +Y=9.

In my experiment, the #opt 0 line takes precedence over the command line for PCH 5.107. That's good news for what temtronic mentioned above where the optimization could be different for different projects. This will allow us to embed the best optimization for a project right into the code. I believe that will be better than worrying about potential changes in our IDE affecting CL parameters in the future.

HTH,
Kyle
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 1, 2  Next
Page 1 of 2

 
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