Shop OBEX P1 Docs P2 Docs Learn Events
Tip: Bizarre compiler condition (with OWRESET) — Parallax Forums

Tip: Bizarre compiler condition (with OWRESET)

VonSzarvasVonSzarvas Posts: 3,526
edited 2008-10-22 15:34 in General Discussion
Hello all,

I am sure this has been noticed before, but I could not find a note so just in case...

I recently created an SX/B program which compiled correctly but failed to run when "uploaded" to the device.

Basically the program was reading bytes from a 1-wire sensor. The OWRESET, pin, replyByte command would return nonsense in the replyByte.

Uploading a "stock" program to the device and all was well. So I knew it was a program fault. Checked every line of code 1 by 1 and all correct.


Now, changed the resonator to 50 mhz (from 4 mhz), and the compiler failed, warning me a memory location was being overwritten.

So that was it. I had exceeded memory - or at least was on the limit. (no surprise with the bloaty 1-wire stuff). The compiler did not complain with the 4mhz resonator DEVICE setting, so maybe this is an error ?

After removing a couple of VAR bytes and switching back to the 4mhz, problem solved.

SO- as a tip - if you are getting some bizarre results from your code which may seem otherwise perfect, try compiling with a 50mhz DEVICE setting! It may throw up an error to help you!



(Maybe there is some indicator of memory use in the IDE that could have also shown me this, but not aware of that feature)

Comments

  • JonnyMacJonnyMac Posts: 9,214
    edited 2007-11-25 13:23
    At 50 MHz the delays necessary to create 1-Wire timing require more code, hence the change you saw going from 4 to 50 MHz. It's always a good idea to create shell subroutines and functions for any timing-bases SX/B routine (1-Wire, SERIN, SEROUT, PAUSE, PAUSEUS, etc.); this will save a lot of code space.
  • VonSzarvasVonSzarvas Posts: 3,526
    edited 2007-11-25 14:47
    Thanks JonnyMac>

    That explains the 50mhz thing, although still a pity the compiler passed OK on 4mhz, when actually a memory conflict was waiting to happen. - Still, I know about it now!

    As for the 1-wire subroutine thing, I have read this is a long-time "quibble" with the 1-wire stuff - 64-bit serial number code and management painful, single io pin code bearable but bloaty.

    Actually following some of your earlier comments, I have been looking at i2c temp devices for later, just a balance of accuracy and price over the very low cost and +-0.5C "highly accurate" ds18b20's.

    But for now, it occurs to me a future version of the SX IDE might allow passing of a PIN reference to a sub or function - which would enable 1wire code to be used simply in subroutines when wishing to communicate with multiple devices on separate pins. Just a thought...
  • JonnyMacJonnyMac Posts: 9,214
    edited 2007-11-25 15:50
    There's nothing stopping any of us from re-crafting anything that is built in to SX/B. 1-Wire was not in the original release. A Parallax customer was having trouble with the DS1996 timing with the BS2p and I happened to live in Dallas, so I visited Maxim/Dallas tech department and got the *real* skinny on reliable 1-Wire communications. I took those specs and wrote 1-Wire routines in SX/B (see attached program -- note how old it is, and that it should be updated to current SX/B standards) -- they worked great, and at a later date Terry folded them into the compiler.

    There is no mechanism in the SX for passing a pin variable, e.g., RA.3. In PBASIC, many routines use a pin number, 0 to 15, and then those are massaged into a mask for the port that holds the target pin. You could update the 1-Wire routines I've attached and use the following subroutines for dealing with a given pin; in this case the valid numbers are 0..19 to handle all the I/Os on an SX28. Please keep in mind, however, that these routines take time so you may have to trim the 1-Wire timing to account for that, especially at low FREQ settings.

    SUB MAKE_INPUT
      tmpB1 = __PARAM1
    
      IF tmpB1 < 4 THEN                             ' RA = 0..3
        tmpB1 = 1 << tmpB1                          ' create pin mask
        TRIS_A = TRIS_A | tmpB1                     ' make pin an input
      ELSEIF tmpB1 < 12 THEN                        ' RB = 4..11
        tmpB1 = tmpB1 - 4                           ' offset for RB
        tmpB1 = 1 << tmpB1
        TRIS_B = TRIS_B | tmpB1
      ELSEIF tmpB1 < 20 THEN                        ' RC = 12..19
        tmpB1 = tmpB1 - 12                          ' offset for RC
        tmpB1 = 1 << tmpB1
        TRIS_C = TRIS_C | tmpB1
      ENDIF
      ENDSUB 
    
    
    
    SUB MAKE_LOW
      tmpB1 = __PARAM1
    
      IF tmpB1 < 4 THEN                             ' RA = 0..3
        tmpB1 = 1 << tmpB1                          ' create pin mask
        tmpB1 = ~tmpB1                              ' invert
        RA = RA & tmpB1                             ' write 0 to pin
        TRIS_A = TRIS_A & tmpB1                     ' make pin an output
      ELSEIF tmpB1 < 12 THEN                        ' RB = 4..11
        tmpB1 = tmpB1 - 4                           ' offset for RB
        tmpB1 = 1 << tmpB1
        tmpB1 = ~tmpB1
        RB = RB & tmpB1
        TRIS_B = TRIS_B & tmpB1
      ELSEIF tmpB1 < 20 THEN                        ' RC = 12..19
        tmpB1 = tmpB1 - 12                          ' offset for RC
        tmpB1 = 1 << tmpB1
        tmpB1 = ~tmpB1
        RC = RC & tmpB1
        TRIS_C = TRIS_C & tmpB1
      ENDIF
      ENDSUB
    



    My point is not to be limited by what the compiler has built in, but to take advantage of its flexibility in creating custom routines. Keep in mind that SX/B has always been designed as a learning tool, and as such sometimes does things at a lower level than traditional compilers (which are certainly available at a variety of $ levels).

    I believe the DS1621 is the I2C equivalent of the DS1620, and the DS1631 has even greater precision -- devices you might look into. In the end, I've used 1-Wire but am not a tremendous fan.

    Post Edited (JonnyMac) : 11/25/2007 4:32:56 PM GMT
  • PJMontyPJMonty Posts: 983
    edited 2007-11-26 20:54
    Maxwin,

    Can you post a version of your program that demonstrates the 4 MHz/50Mhz problem? I would like to see if this is a compiler issue or a SASM issue. I suspect SASM, but I won't know without a piece of code that demonstrates the problem.

    Thanks,
    PeterM
  • VonSzarvasVonSzarvas Posts: 3,526
    edited 2007-11-27 08:54
    PJMonty- I will, but I am away until Monday. Will send it then.
  • VonSzarvasVonSzarvas Posts: 3,526
    edited 2008-10-22 09:30
    Whilst not wishing to earn a black mark for admitting to such a late reply, I finally found the piece of code which was causing this problem. blush.gif

    After a year it may now be irrelevant, but I post it anyhow in-case it helps.

    Apologies to PeterM eyes.gif

    Max.
  • BeanBean Posts: 8,129
    edited 2008-10-22 11:12
    Faster clock speeds require more instructions to perform delays.
    So the same SX/B instructions require more program space when compiled at 50MHz compared to 4MHz.

    The code at 4MHz uses 2013 of the 2047 instruction locations. Using 50MHz pushes it over the edge.

    Bean.

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    "It is our choices, Harry, that show what we truly are, far more than our abilities."·Dumbledore from Harry Potter

    www.iElectronicDesigns.com

    ·
  • VonSzarvasVonSzarvas Posts: 3,526
    edited 2008-10-22 14:42
    Thank you for the explanation Bean.

    The error message box that appears says "SASM Error", "Unable to assemble due to errors in source code"

    Maybe it could be kinder and say "code exceeds instruction locations", as their are no errors in the source really?

    Anyway, at least its a tip to note that if 50mhz code will not assemble and you cannot see why... try at a lower speed.

    (There may be a smarter way to check this with the IDE, of which I am unaware. But as Bean has kindly mentioned the actual numbers of instruction locations involved, that might suggest it is possible to find that out, so I will have a look when I have some time.).

    Max.
  • JonnyMacJonnyMac Posts: 9,214
    edited 2008-10-22 15:34
    Keep in mind that any time-based function will generate a lot of code so your use of all the 1-Wire commands is what's doing you in. Let me suggest that you encapsulate these commands into custom subs/funcs so that SX/B only has to explode-out the instructions once -- this will save a lot of space in your program.

    FUNC OW_RESET1
      OWRESET Wire1, __PARAM1
      ENDFUNC
    
    
    SUB OW_WRITE1
      OWWRBYTE Wire1, __PARAM1
      ENDSUB
    
    
    FUNC OW_READ1
      OWRDBYTE Wire1, __PARAM1
      ENDFUNC
    
Sign In or Register to comment.