Code compiling but not executing???

Discussion in 'Embedded Systems and Microcontrollers' started by spinnaker, Jan 12, 2014.

  1. spinnaker

    Thread Starter AAC Fanatic!

    Oct 29, 2009
    4,884
    1,005
    I have the function below that is compiling without errors or warnings yet part of the code is not executing in the debugger.

    I am using the XCB compiler V1.21 in MPLaBX V2.0

    My chip is the PIC18F14K22.

    If I set a breakpoint at the line "ones = val;" then I get a Broken Breakpoint in the IDE when the code starts to execute.

    If I add a breakpoint on the line that calls display_setRefrigeratorValue and step into display_setRefrigeratorValue then it steps to the line ones = val within the while loop.

    I also noticed that I cannot pause my code.




    If I add the line int "m = 123;" after "ones = val;" then all works fine. The breakpoint works and I can pause the code.

    At first I thought it might be a bad memory location (even though the chip verifies OK) so I changed out the chip with the same results. I also added a function with the same code but got similar results.

    Any ideas what the heck is going on???





    Code ( (Unknown Language)):
    1.  
    2. void display_setRefrigeratorValue(int val)
    3. {
    4.     unsigned char tens;
    5.     unsigned char ones;
    6.    
    7.     ones = val;        // If breakpoint is set here, I get Broken Breakpoint, unless the line below is not commented.
    8.  // int m = 123;      If this line is uncomented then code executes as expected.
    9.  
    10.  
    11.     while (val >= 10)
    12.     {
    13.       tens++;
    14.       val -= 10;
    15.       ones = val;    //Code steps to here if breakpoint is set where display_setRefrigeratorValue is being called.
    16.     }
    17.  
    18.      val = ones;
    19.     display_select(3);
    20.     unsigned char portVal = DISPLAY_VALUE & 0xf0;
    21.     DISPLAY_VALUE = portVal | (val);
    22.  
    23.     val = tens;
    24.     display_select(2);
    25.     unsigned char portVal = DISPLAY_VALUE & 0xf0;
    26.     DISPLAY_VALUE = portVal | (val);
    27.  
    28.    
    29.  
    30.  }
    31.  
     
    Last edited: Jan 12, 2014
  2. JohnInTX

    Moderator

    Jun 26, 2012
    2,345
    1,028
    I think its because you can only set a breakpoint on a line that actually generates code. The function name generates no code so the breakpoint can't resolve to a physical memory address. Sometimes I'll put a dummy variable operation to get a point to stop at so I can step into the first statement of a function.

    It also may be a result of optimization. The first ones=val is not used before its updated in the loop. If you look at the disassembled output you can see where the actual machine code goes and at what address its set at.
     
    Last edited: Jan 12, 2014
  3. spinnaker

    Thread Starter AAC Fanatic!

    Oct 29, 2009
    4,884
    1,005

    That can't be it. The line ones = val has to generate code. Why would adding a line int m = 123; fix it?

    It also does not explain why Pause is disabled and why the code skips a number of lines of code when the function is stepped into.


    I am think (maybe) it is because I was trying to modify a variable that was pushed onto the stack???

    I changed things around so a temp variable is set with the value of val and that seems to work.
     
  4. Tesla23

    Active Member

    May 10, 2009
    318
    67
    Turn off optimization.

    It looks like your compiler has eliminated all lines that refer to ones - as they don't do anything - check it out - just ignore all the lines that refer to ones, the algorithm still works. If that's the case that's impressive optimization.

    Also, unless your compiler guarantees initialisation, you should initialise tens.
     
  5. shteii01

    AAC Fanatic!

    Feb 19, 2010
    3,387
    497
    val is an integer. ones is declared as char. So main is passing an integer to the user defined function, but then in the user defined function you use it as character. Could this be a problem?
     
  6. tshuck

    Well-Known Member

    Oct 18, 2012
    3,531
    675
    You could make them volatile, telling the compiler to not optimize them and implement them as coded.

    The compiler might optimize out the first "ones = val", as this could be deemed unnecessary.
     
  7. JohnInTX

    Moderator

    Jun 26, 2012
    2,345
    1,028
    XC8 is incredibly aggressive in its optimization. It can and will remove anything it decides isn't required - especially in the PRO (full-optimize) mode. The source lines that imply this removed code are basically comments i.e. source text that doesn't generate code. In multi-file projects, code that is generated by the compiler (extern functions etc) will be removed by the linker if its not referenced by anything. That's why I suggested that the disassembly listing be consulted to see what it actually generated. Its a different beast.

    I don't know why adding the int m=123; line makes it work. Perhaps its actually breaking on the code that initializes the variable.

    EDIT: I built the OP's code fragment in XC8 1.21 free (not full optimized) mode with the following results. Misc vars and routines are stubbed but as you can see on lines 25 and 34, no code is generated by ones=val because it doesn't affect anything. That's why you can't set a breakpoint on it.

    Its too bad it doesn't show back in the source but that's the way it is.

    Code ( (Unknown Language)):
    1. Disassembly Listing for Spinnaker
    2. Generated From:
    3. M:/UP/XC8/Spinaker/Spinnaker.X/dist/default/production/Spinnaker.X.production.elf
    4. Jan 12, 2014 10:56:11 PM
    5.  
    6. ---  M:/UP/XC8/Spinaker/Spinnaker.X/Spinaker.c  ---------------------------------------------------------
    7. 1:             /*
    8. 2:              * File:   Spinaker.c
    9. 3:              * Author: John
    10. 4:              *
    11. 5:              * Created on January 12, 2014, 10:52 PM
    12. 6:              */
    13. 7:            
    14. 8:             #include <xc.h>
    15. 9:            
    16. 10:            
    17. 11:            /*
    18. 12:             *
    19. 13:             */
    20. 14:            
    21. 15:            //void display_setRefrigeratorValue(int val)
    22. 16:            int val;
    23. 17:            unsigned char portVal, DISPLAY_VALUE;
    24. 18:            
    25. 19:            void main() {
    26. 3FB8  D005     BRA 0x3FC4
    27. 20:            
    28. 21:            
    29. 22:            {
    30. 23:                unsigned char tens;
    31. 24:                unsigned char ones;
    32. 25:   *********** ADDED BY JohnInTX: Note no code generated for the next line..  ******  
    33. 26:                ones = val;        // If breakpoint is set here, I get Broken Breakpoint, unless the line below is not commented.
    34. 27:             // int m = 123;      If this line is uncomented then code executes as expected.
    35. 28:            
    36. 29:            
    37. 30:                while (val >= 10)
    38. 3FC8  5002     MOVF 0x2, W, ACCESS
    39. 3FCA  0A80     XORLW 0x80
    40. 3FCC  0F80     ADDLW 0x80
    41. 3FCE  0E0A     MOVLW 0xA
    42. 3FD0  B4D8     BTFSC STATUS, 2, ACCESS
    43. 3FD2  5C01     SUBWF val, W, ACCESS
    44. 3FD4  B0D8     BTFSC STATUS, 0, ACCESS
    45. 3FD6  D7F1     BRA 0x3FBA
    46. 31:                {
    47. 32:                  tens++;
    48. 3FBA  2A05     INCF tens, F, ACCESS
    49. 33:                  val -= 10;
    50. 3FBC  0EF6     MOVLW 0xF6
    51. 3FBE  2601     ADDWF val, F, ACCESS
    52. 3FC0  0EFF     MOVLW 0xFF
    53. 3FC2  2202     ADDWFC 0x2, F, ACCESS
    54. 34:                  ones = val;    //Code steps to here if breakpoint is set where display_setRefrigeratorValue is being called.
    55. 3FC4  C001     MOVFF val, ones
    56. 3FC6  F006     NOP
    57. 35:                }
    EDIT2: As to why it breaks with m=123, adding that to the code gets this (excerpt):
    Code ( (Unknown Language)):
    1. 19:            void main() {
    2. 20:            
    3. 21:            
    4. 22:            {
    5. 23:                unsigned char tens;
    6. 24:                unsigned char ones;
    7. 25:            
    8. [B]26:                ones = val;        // If breakpoint is set here, I get Broken Breakpoint, unless the line below is not commented.
    9. 3FAC  C006     MOVFF val, ones
    10. 3FAE  F004     NOP[/B]
    11. 27:              int m = 123;      //If this line is uncomented then code executes as expected.
    12. 3FB0  0E00     MOVLW 0x0
    13. 3FB2  6E02     MOVWF 0x2, ACCESS
    14. 3FB4  0E7B     MOVLW 0x7B
    15. 3FB6  6E01     MOVWF m, ACCESS
    You can see that ones=val now generates code. I don't know why but that's where your breakpoint on ones=val came from.

    Finally, I don't have PRO mode for 1.21 but DID rebuild it in 1.12 PRO mode with the same results, ones=val is generated but not int m=123. It DID issue warnings about unused variables though. Go figure.
     
    Last edited: Jan 13, 2014
  8. Tesla23

    Active Member

    May 10, 2009
    318
    67
    I'm intrigued that the compiler still generated code for
    Code ( (Unknown Language)):
    1. ones = val
    inside the loop. Did it actually do the assignment
    Code ( (Unknown Language)):
    1. val = ones
    after the loop, if so it would appear to be incorrect in the case that the loop doesn't execute (val < 10). If it omitted the one after the loop, then why did it leave the one inside the loop?

    Ah - I see. It's not very aggressive optimization, it's just noticed that it can skip the initial "ones = val" line by having the entry point of the routine to be the "ones = val" line in the while loop. If you put anything else before the loop this doesn't work, so it has to generate the additional "ones = val" code before the loop.
     
    Last edited: Jan 13, 2014
  9. JohnInTX

    Moderator

    Jun 26, 2012
    2,345
    1,028
    Beats me. In PRO mode it did warn about assigning a value that was never used, more like a conventional compiler.

    I've been trying off and on to master XC8's optimizations. I have an old project using an RTOS that does scheduling via stack operations. XC8 doesn't seem to be able to track that kind of thing so it optimizes out pretty much the whole 30K lines of C. Unfortunate.
     
  10. Tesla23

    Active Member

    May 10, 2009
    318
    67
    I think I figured it out - and edited it into my previous reply while you were posting. In case you missed it:

    It's not very aggressive optimization, it's just noticed that it can skip the initial "ones = val" line by having the entry point of the routine to be the "ones = val" line in the while loop. If you put anything else before the loop this doesn't work, so it has to generate the additional "ones = val" code before the loop.
     
    JohnInTX likes this.
  11. JohnInTX

    Moderator

    Jun 26, 2012
    2,345
    1,028
    Makes sense. Thanks for looking at it.
     
Loading...