Apparent code size problem


Closed Thread
Results 1 to 11 of 11
  1. #1
    Join Date
    Sep 2006
    Posts
    8

    Default Apparent code size problem

    I am having a problem that appears to be related to code size. The chip is 16F917, PBP version is 2.46

    The total code size is over 4000 words Everything compiles and one version of the code works just fine. However a small change is one subroutine to make it more user friendly seems to break eveything. It appears to fail to initialize properly ( based on fact that the opening splash screen never displays and the instrument will not respond to any of the inputs it should immediately after power up). The code is for a company project and so I can not post it all, but I have posted the two code snippets, the total word count of the program when using each variation and the address range

    I encountered this problem once or twice before during this project and both times a change in code size has corrected it. Once was nothing more than adding a line like X = X. This leads me to think it may be some type of boundry issue, but I have to admit I am new enough to PICs and PBP that I am more than a little confused at this time.

    Any help or suggestions would be appreciated.

    The one that works:
    4145 words
    0-1037 address range

    IF (OhmCheck = FAILED) or _ ' resistor out of tolerance or
    (FlagResult <> 0) then ' hardware flag
    GOSUB Houston
    ENDIF
    -------------------------------------------------

    Replace it with this one and it does not work:
    4281 words
    0-10bf address range

    IF OhmCheck = FAILED THEN
    ErrCnt = ErrCnt + 1
    IF ErrCnt = 1 then 'first time gets a pass for a recheck
    Device = DISPLAY
    GOSUB SetCtrl
    LCDOUT $FE,1,"Chk Dckbill conn"
    LCDOUT $FE,$C0,"then retry test"
    PAUSE 1000
    ENDIF
    ENDIF
    IF (ErrCnt > 1) or (FlagResult <> 0) THEN
    GOSUB Houston
    ENDIF

  2. #2
    Join Date
    Nov 2005
    Location
    Bombay, India
    Posts
    947


    Did you find this post helpful? Yes | No

    Default

    It might have something to do with the gosub Houston routine. Maybe the branch is out of range. You could try to reposition the subroutine Houston and see if it works. I could be totally wrong too...

  3. #3
    Join Date
    Jan 2006
    Location
    Istanbul
    Posts
    1,185


    Did you find this post helpful? Yes | No

    Default

    Quote Originally Posted by eetech View Post
    ...

    Code:
    IF (OhmCheck = FAILED) or _  	' resistor out of tolerance or
        (FlagResult <> 0) then                 ' hardware flag  
        GOSUB Houston
    ENDIF
    Try this for the one above:
    Code:
     
    IF ErrCnt > 1 or FlagResult > 0 THEN GOSUB Houston
    -------------------------------------------------
    Quote Originally Posted by eetech View Post
    ...
    Replace it with this one and it does not work:
    Code:
    IF OhmCheck = FAILED THEN
       ErrCnt = ErrCnt + 1
       IF ErrCnt = 1 then	'first time gets a pass for a recheck 
          Device = DISPLAY
          GOSUB SetCtrl
          LCDOUT $FE,1,"Chk Dckbill conn"
          LCDOUT $FE,$C0,"then retry test"
          PAUSE 1000
       ENDIF
    ENDIF
    IF (ErrCnt > 1) or (FlagResult <> 0) THEN 
       GOSUB Houston
    ENDIF
    And try this for the one above:

    Code:
    IF OhmCheck = FAILED or FlagResult > 0 then GOSUB Houston

    And try this separately:

    Code:
    IF OhmCheck = FAILED THEN
        ErrCnt = ErrCnt + 1     
    
        IF ErrCnt = 1 then 'first time gets a pass for a recheck
            Device = DISPLAY
            GOSUB SetCtrl
            LCDOUT $FE,1,"Chk Dckbill conn"
            LCDOUT $FE,$C0,"then retry test"
            PAUSE 1000
        else
            gosub Houston 
        endif
        
    ENDIF
    
    
    IF FlagResult > 0 THEN GOSUB Houston
    Question: Do you set ErrCnt = 0 before the program starts running, or it gets some values from somewhere else?
    In your code, it seems that it must be set to zero at initial power up before coming to "IF OhmCheck = FAILED THEN" condition.

    Question: FlagResult is a hardware flag. So it can be 1 or 0 only, right? If yes, then why not use IF FlagResult = 1 instead of FlagResult <> 0 ?


    Also, as Jerson said, we should see Houston subroutine.

    May be there is something in it that makes things messed up.


    --------------------------------
    Last edited by sayzer; - 26th July 2007 at 10:00.
    "If the Earth were a single state, Istanbul would be its capital." Napoleon Bonaparte

  4. #4
    sinoteq's Avatar
    sinoteq Guest


    Did you find this post helpful? Yes | No

    Default I think I have seen this before

    What you say looks like something I had some time ago. Check the forum for broken code. http://www.picbasic.co.uk/forum/showthread.php?t=5674

    The problem is when you add a new variable PBP makes a word variable span 2 banks and that is not allowed. If this happens you get "The Harry Potter Syndrome" black magic and nothing is logical anymore. I fixed this for my 18F4620 pic by adding a dummy variable at the last address in each bank. For example:

    bogus_0 VAR BYTE $7F ' force a byte at location 07F
    bogus_1 VAR BYTE $0FF ' force a byte at location 0FF
    bogus_2 VAR BYTE $1FF ' force a byte at location 1FF
    bogus_3 VAR BYTE $2FF ' force a byte at location 2FF
    bogus_4 VAR BYTE $3FF ' force a byte at location 3FF
    bogus_5 VAR BYTE $4FF ' force a byte at location 4FF
    bogus_6 VAR BYTE $5FF ' force a byte at location 5FF
    bogus_7 VAR BYTE $6FF ' force a byte at location 6FF
    bogus_8 VAR BYTE $7FF ' force a byte at location 7FF

    Make sure you get the location right, depending on MCU you should go for different values. Look in the .ASM file for your compiled program and early you will find:

    BANK0_START EQU 00080h
    BANK0_END EQU 000FFh
    BANK1_START EQU 00100h
    BANK1_END EQU 001FFh
    BANK2_START EQU 00200h
    BANK2_END EQU 002FFh
    BANK3_START EQU 00300h
    BANK3_END EQU 003FFh

    Use the END value for you bogus variable and PBP can not make this misstake. Make sure you include BANKA also in the fix.

    Hope this will help to remove Harry Potter from your code. And YES MELABS knows about this because they helped me to find it.

    Mike
    Last edited by sinoteq; - 26th July 2007 at 14:25.

  5. #5
    Join Date
    Sep 2006
    Posts
    8


    Did you find this post helpful? Yes | No

    Default

    Quote Originally Posted by sayzer View Post
    Try this for the one above:
    Code:
     
    IF ErrCnt > 1 or FlagResult > 0 THEN GOSUB Houston
    -------------------------------------------------


    And try this for the one above:

    Code:
    IF OhmCheck = FAILED or FlagResult > 0 then GOSUB Houston
    And try this separately:

    Code:
    IF OhmCheck = FAILED THEN
        ErrCnt = ErrCnt + 1     
    
        IF ErrCnt = 1 then 'first time gets a pass for a recheck
            Device = DISPLAY
            GOSUB SetCtrl
            LCDOUT $FE,1,"Chk Dckbill conn"
            LCDOUT $FE,$C0,"then retry test"
            PAUSE 1000
        else
            gosub Houston 
        endif
        
    ENDIF
    
    
    IF FlagResult > 0 THEN GOSUB Houston
    Question: Do you set ErrCnt = 0 before the program starts running, or it gets some values from somewhere else?

    In your code, it seems that it must be set to zero at initial power up before coming to "IF OhmCheck = FAILED THEN" condition.

    Question: FlagResult is a hardware flag. So it can be 1 or 0 only, right? If yes, then why not use IF FlagResult = 1 instead of FlagResult <> 0 ?

    FlagResult is a hardware flag, but it is a set of BIT flags so it can have a result other than 0 or 1.

    Also, as Jerson said, we should see Houston subroutine.

    May be there is something in it that makes things messed up.


    --------------------------------

    Both of those examples are fundamentally the same. The difference being your use of the IF without the ENDIF, which some languages (like PBP) allow.
    I did try it though.

    Yes, ErrCnt is set to 0 before usage.

    FlagResult is a hardware flag, but it is a set of BIT flags so it can have a result other than 0 or 1.

    The subroutine Houston uses Select Case to decode FlagResult and displays the appropriate error message. It does not return from there but goes into a continous loop because errors that cause Houston to be called are considered critical problems with either the instrument or the site being tested.

    I may not have made myself clear in the original post, the problem does not occur because the code in question is run (the program never gets that far). The problem occurs when the first piece of code is replaced by the second.

  6. #6
    sinoteq's Avatar
    sinoteq Guest


    Did you find this post helpful? Yes | No

    Default Try the dummy variable fix

    This is what I had, I changed in one place and it died in another. If you check the asm file that you have on the NOT working program it is easy to see. Just look at the end address for each bank and most likely you will see Byte0 of a Word variable there. Byte1 will be in then next bank and this messes up all the RAM area for you even if you don't use that variable in the start of your program.

    M

  7. #7
    Join Date
    Jul 2003
    Posts
    2,405


    Did you find this post helpful? Yes | No

    Default

    Without seeing all of your code it's tough for someone to help debug, but it
    does sound like a page boundary issue.

    If the splash screen never shows on power-up, I'm curious as to where the
    routine that handles this is located? Is it near the end of your program?

    Are you 100% sure you don't have a GOSUB to a sub-routine somewhere with
    a GOTO VS RETURN in the called sub-routine?
    Regards,

    -Bruce
    tech at rentron.com
    http://www.rentron.com

  8. #8
    Join Date
    Sep 2006
    Posts
    8


    Did you find this post helpful? Yes | No

    Default Results so far

    There is one thing I did forget to mention (and I aplogize to all of you that have offered help). The mcu initialization is done in assembly. That code block is located immediately after all the variable declarations, etc.
    -----------------------------------------------------------------

    Mike,
    I tried the dummy variable fix, it did not cure the problem. after putting the dummies in I checked the address of every word variable in the asm listing to make sure none crossed a page. Here is the asm listing of the page banks and the dummy declarations.

    RAM_START EQU 00020h
    RAM_END EQU 001EFh
    RAM_BANKS EQU 00004h
    BANK0_START EQU 00020h
    BANK0_END EQU 0007Fh
    BANK1_START EQU 000A0h
    BANK1_END EQU 000EFh
    BANK2_START EQU 00120h
    BANK2_END EQU 0016Fh
    BANK3_START EQU 00190h
    BANK3_END EQU 001EFh
    EEPROM_START EQU 02100h
    EEPROM_END EQU 021FFh


    '******************************************
    ' Dummy Variable Declarations *
    '******************************************
    bogus_0 VAR BYTE $07F
    bogus_1 VAR BYTE $0EF
    bogus_2 VAR BYTE $16F
    bogus_3 VAR BYTE $1EF

    ----------------------------------------------------------------

    Bruce,
    The code that displays the splash screen is physically located early in the code and is the first code ran once the initializatin sequences are finished.
    I doubled checked my routines, as you suggested, everything ok there.

    I know it is hard to help when you can't see the code, and believe me if I could I would upload the entire project and let everyone have a field day with it.


    The code blocks out like this:

    fuse settings
    defines
    constant declarations
    variable decalrations

    GOTO Start

    INI:
    assembly block (with return) to setup the chip

    Setup:
    routine (with return) to set initial state of variables, etc

    Start:
    GOSUB INI
    GOSUB Setup

    Splash screen is displayed here.

    Some initail instrument checks ( proper hookup, etc) are performed here

    Switch polling routine here

    rest of code body.

  9. #9
    Join Date
    Jul 2003
    Posts
    2,405


    Did you find this post helpful? Yes | No

    Default

    Have you tried replacing your .asm initialization with a BASIC version?

    I know you can sometimes save a few bytes by doing some things in .asm,
    but if you initialize everything in banks PBP doesn't insert a ton of bank
    switching code flipping back & forth between banks. I.E.

    ' Bank0 first
    PORTB = 0
    PORTC = 0
    T2CON = 0
    ' Bank1 next
    TRISA = 0
    TRISB = 0
    CMCON1 = 7, etc, etc,

    Are you using assembler in other routines?

    I would think either something in the INI or Setup routines is causing
    the problem since the splash screen routine is supposed to run directly
    after Setup.

    If one routine is causing the problem, it should be easy to spot.

    Start:
    GOSUB INI
    blink an LED on return to here x times
    GOSUB Setup
    blink an LED on return to here x times, etc, etc,.

    Of course you could always run it through MPSIM too.
    Regards,

    -Bruce
    tech at rentron.com
    http://www.rentron.com

  10. #10
    Join Date
    Sep 2006
    Posts
    8


    Did you find this post helpful? Yes | No

    Default

    Bruce,

    I tried the idea of replacing the asm routine with a basic one; pared the program down to just the ini and setup stuff and a display routine. Two versions, one all PBP and the other with the asm block.

    Now... I really feel stupid, the all basic one will not run, the other works just fine. So before I can actually try your idea I now have to figure out what I am doing wrong with the ini code in basic. ( and just in case everyone is wondering at this point... yes, I did write the asm block)

    I have included both below so that anyone who wants ( after they get up off the floor from laughing) can point out my mistake if they would.

    hope I got the code formatting command right so it is easy to read.

    Robert

    [code]
    '************************************************* ***************
    ' MCU Setup - inline assembly block *
    '************************************************* ***************
    INIMCU:
    asm
    bsf STATUS,RP0 ; Select Bank 1

    movlw 07h ; turn off comparators
    movwf CMCON0

    movlw 0xEC ; set A<5,1,0> as digital I/O
    movwf ANSEL ; A<3:2> and E<2:0> as analog

    movlw 0xFF ; set A<7:0> input; (A<3:2> analog; A<7:4,1:0> digital)
    movwf TRISA

    movlw 50h ; set A2D Clock 10h:Fosc/8 50h:Fosc/16
    movwf ADCON1

    movlw 00h ; set PORTB as outputs
    movwf TRISB

    movlw 0xF8 ; set PORTC C<7:3> as inputs; C<2:0> as outputs
    movwf TRISC

    movlw 0x00 ; set PORTD as inputs
    movwf TRISD

    movlw 0Fh ; set PORTE as inputs
    movwf TRISE

    bcf STATUS,RP0 ; Select Bank 2
    bsf STATUS,RP1 ;

    clrf LCDCON ; Disable VLCD<3:1>
    ; inputs on RC<2:0>

    bcf STATUS,RP0 ; Select Bank 0
    bcf STATUS,RP1
    endasm
    return



    '******************************
    ' MCU Setup - PBP
    '******************************
    INIMCU:
    CMCON0 = 7
    ANSEL = $EC
    TRISA = $FF
    ADCON1 = $50
    TRISB = 0
    TRISC = $F8
    TRISD = 0
    TRISE = $0F
    LCDCON = 0
    return

    [\code]

  11. #11
    Join Date
    Nov 2005
    Location
    Bombay, India
    Posts
    947


    Did you find this post helpful? Yes | No

    Default

    Robert

    I am wondering if you can do the following. Bruce already suggested this. I am just reminding you of the possibility (to catch a problem) of debugging this technique offers.

    Code:
    GOTO Start 
    
    INI:
    assembly block (with return) to setup the chip
    
    Setup:
    routine (with return) to set initial state of variables, etc
    
    Start:
       Led = 1:pause 1000:Led = 0
    GOSUB INI 
       Led = 1:pause 1000:Led = 0
    GOSUB Setup
       Led = 1:pause 1000:Led = 0
    
    Splash screen is displayed here.
    
    Some initail instrument checks ( proper hookup, etc) are performed here
    
    Switch polling routine here
    
    rest of code body
    if you see 3 flashes of the led, you have reached the splash screen code.

    Perhaps this will help you find if you are missing a return / stacking too deep. You may have a problem due to the limited caller stack size. Have you looked into this too?

    Jerson

Similar Threads

  1. Loop with two motor and 2 sensors
    By MrRoboto in forum mel PIC BASIC
    Replies: 4
    Last Post: - 8th December 2008, 23:40
  2. Making Program Code Space your playground...
    By Melanie in forum Code Examples
    Replies: 15
    Last Post: - 19th July 2008, 08:26
  3. problem with my code
    By civicgundam in forum mel PIC BASIC Pro
    Replies: 0
    Last Post: - 3rd February 2008, 01:52
  4. Setting code size boundaries
    By Charles Linquis in forum mel PIC BASIC Pro
    Replies: 10
    Last Post: - 8th March 2007, 20:11
  5. Servo Code problem
    By ALFRED in forum General
    Replies: 1
    Last Post: - 2nd March 2006, 03:30

Members who have read this thread : 1

You do not have permission to view the list of names.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts