| 
	
	|  |  |  
	
		| View previous topic :: View next topic |  
		| Author | Message |  
		| pmuldoon 
 
 
 Joined: 26 Sep 2003
 Posts: 218
 Location: Northern Indiana
 
 
			    
 
 | 
			
				| 18F6722 possible math issue from compiler v5.074 to 5.105 |  
				|  Posted: Wed Jan 19, 2022 9:30 am |   |  
				| 
 |  
				| 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: 21708
 
 
 
			    
 
 | 
			
				|  |  
				|  Posted: Wed Jan 19, 2022 9:58 am |   |  
				| 
 |  
				| 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: 218
 Location: Northern Indiana
 
 
			    
 
 | 
			
				|  |  
				|  Posted: Wed Jan 19, 2022 11:12 am |   |  
				| 
 |  
				| 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: 19967
 
 
 
			    
 
 | 
			
				|  |  
				|  Posted: Wed Jan 19, 2022 11:12 am |   |  
				| 
 |  
				| 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...
  |  |  
		|  |  
		| pmuldoon 
 
 
 Joined: 26 Sep 2003
 Posts: 218
 Location: Northern Indiana
 
 
			    
 
 | 
			
				|  |  
				|  Posted: Thu Jan 27, 2022 6:50 am |   |  
				| 
 |  
				| 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: 218
 Location: Northern Indiana
 
 
			    
 
 | 
			
				|  |  
				|  Posted: Thu Jan 27, 2022 8:45 am |   |  
				| 
 |  
				| 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: 19967
 
 
 
			    
 
 | 
			
				|  |  
				|  Posted: Thu Jan 27, 2022 10:42 am |   |  
				| 
 |  
				| 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'...
  |  |  
		|  |  
		| pmuldoon 
 
 
 Joined: 26 Sep 2003
 Posts: 218
 Location: Northern Indiana
 
 
			    
 
 | 
			
				|  |  
				|  Posted: Thu Jan 27, 2022 11:51 am |   |  
				| 
 |  
				| 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.
  |  |  
		|  |  
		| Ttelmah 
 
 
 Joined: 11 Mar 2010
 Posts: 19967
 
 
 
			    
 
 | 
			
				|  |  
				|  Posted: Thu Jan 27, 2022 11:54 am |   |  
				| 
 |  
				| 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
 
 
			    
 
 | 
			
				|  |  
				|  Posted: Thu Jan 27, 2022 2:06 pm |   |  
				| 
 |  
				| 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.
   
 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!
   
 Even so, I say thanks for the helpful discussion guys.
 
 -Kyle
 |  |  
		|  |  
		| temtronic 
 
 
 Joined: 01 Jul 2010
 Posts: 9589
 Location: Greensville,Ontario
 
 
			    
 
 | 
			
				|  |  
				|  Posted: Fri Jan 28, 2022 6:13 am |   |  
				| 
 |  
				| 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
 
 
			    
 
 | 
			
				|  |  
				|  Posted: Fri Jan 28, 2022 7:28 am |   |  
				| 
 |  
				| 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.
   
 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: 19967
 
 
 
			    
 
 | 
			
				|  |  
				|  Posted: Fri Jan 28, 2022 8:37 am |   |  
				| 
 |  
				| 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: 9589
 Location: Greensville,Ontario
 
 
			    
 
 | 
			
				|  |  
				|  Posted: Fri Jan 28, 2022 8:45 am |   |  
				| 
 |  
				| 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
 
 
			    
 
 | 
			
				|  |  
				|  Posted: Fri Jan 28, 2022 9:00 am |   |  
				| 
 |  
				| GOOD NEWS 
 I was hoping one of you guys could just tell me...
   
 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
 |  |  
		|  |  
		|  |  
  
	| 
 
 | 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
 
 |