Shop OBEX P1 Docs P2 Docs Learn Events
Method calls failing..... — Parallax Forums

Method calls failing.....

Sniper KingSniper King Posts: 221
edited 2008-09-20 00:07 in Propeller 1
I am having a huge problem with method calls working sometimes and crashing the code other times.· Below are the Objects I am using and the Variables I am using.· I have put in precations to prevent going outside my array values so i know that is not the case.· Sometimes if i change a method from public to private it will work.· But some other method will fail.· I can get the loop to work perfectly one time and then the second time around a method will fail and the software will crash.


I am using...

·········LED···· : "uOLED_Small"
········ GPS····: "GPS_IO_mini_PNAV"
········ Debug : "FullduplexSerial"·
········ Comm· : "FullduplexSerial"
········ FS····· : "Floatstring"
········ FP···· ·:· "Float32Full"
········ num··· :· "Numbers"

Variables

·long TMN
long TMCNTd
long TMCNTs
long TMS
Long TMCNTn
long TMD
long Count·
long Heading
byte buttons[noparse][[/noparse]1]
long stat911
byte BFTMode[noparse][[/noparse]1]··· 'N for Navigation , S for standard(Sleep)· E for emergency
byte Separation[noparse][[/noparse]1]
byte latitude[noparse][[/noparse]35]
byte longitude[noparse][[/noparse]35]·
byte lat[noparse][[/noparse]35]
byte lng[noparse][[/noparse]35]
byte answer[noparse][[/noparse]4]
byte Serial[noparse][[/noparse]10]
long lats
long lngs
long wlngs
long wlats
long TmCnt911
Long Tm911

▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
·- Ouch, thats not suppose to be hot!··


Michael King
Application Engineer
R&D

Check out Project: PSAV Persistent Sailing Autonomous Vehicle

Comments

  • Phil Pilgrim (PhiPi)Phil Pilgrim (PhiPi) Posts: 23,514
    edited 2008-09-19 20:48
    Michael,

    This is the second thread you've begun on the selfsame topic in as many days. It would be helpful if you could respond to comments/suggestions in yesterday's thread rather than starting over. For example, did you check out any stack allocation issues that might exist? Did it help?

    -Phil

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    'Still some PropSTICK Kit bare PCBs left!
  • Sniper KingSniper King Posts: 221
    edited 2008-09-19 20:52
    I not using any cogs that i start myself in my software.· The cogs that are started are the ones in the objects that I use.· Those Objects are from the object exchange.· Maybe they are crashing but i think we would have heard something by now.

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    ·- Ouch, thats not suppose to be hot!··


    Michael King
    Application Engineer
    R&D

    Check out Project: PSAV Persistent Sailing Autonomous Vehicle
  • Mike GreenMike Green Posts: 23,101
    edited 2008-09-19 21:09
    As has been mentioned before, the primary reason for programs to "crash", to stop behaving or responding as expected, is that of one portion of a program changing the memory used by another portion of the program either because arrays are accessed with an invalid subscript or because a stack is overflowing the space allocated for it. You've indicated that invalid array subscripting is not an issue. FullDuplexSerial and Float32Full initiate separate cogs running assembly which doesn't use a stack. I don't think FloatString or Numbers use a separate cog, therefore there's no separate stack involved. I'm not familiar with uOLED_Small or GPS_IO_mini_PNAV, so I couldn't say anything about them.

    Nothing that you've said is very helpful in sorting this kind of thing out. This is the sort of thing that only painstaking tracing and debugging output will help narrow it down to the area of the program involved and the state of the program when the problem occurs.

    Although things are never "impossible", it is very unlikely that the problem has anything to do with the compiler or the interpreter or the library objects. You may have checks for subscripts out of range or invalid pointers, but it's very difficult to separate out what you intended for the program to do vs. what you actually coded.

    Post Edited (Mike Green) : 9/19/2008 9:14:25 PM GMT
  • Sniper KingSniper King Posts: 221
    edited 2008-09-19 21:12
    Thats the problem Mike. I have been inside this for 3 days and get the same problem and I am going to freak out!(LOL)

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    ·- Ouch, thats not suppose to be hot!··


    Michael King
    Application Engineer
    R&D

    Check out Project: PSAV Persistent Sailing Autonomous Vehicle
  • Mike GreenMike Green Posts: 23,101
    edited 2008-09-19 21:15
    I've certainly been there. Again, the way through this is to "instrument" the program little by little, perhaps using the programming serial port since that's almost always available. You want to narrow down the circumstances where the program fails and get enough information out to help identify that without glacially slowing the program down. You can also focus on where the program succeeds instead, logging those success points. You're obviously stuck. Get a little data to help yourself. Something you're assuming is just not true.
  • Sniper KingSniper King Posts: 221
    edited 2008-09-19 21:17
    I have been using the a debug out of the programming port. I have debugs one every method call. The weird thing is that it will stop at different methods. No rhyme no reason that I have found yet....

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    ·- Ouch, thats not suppose to be hot!··


    Michael King
    Application Engineer
    R&D

    Check out Project: PSAV Persistent Sailing Autonomous Vehicle
  • Mike GreenMike Green Posts: 23,101
    edited 2008-09-19 21:20
    Sure sounds like a stack problem or array subscript problem because it's data or timing dependent.
  • Sniper KingSniper King Posts: 221
    edited 2008-09-19 21:41
    Where is a good place to look for this problem?· Could I send you my code for some help.· I don't feel comfortable posting it public.

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    ·- Ouch, thats not suppose to be hot!··


    Michael King
    Application Engineer
    R&D

    Check out Project: PSAV Persistent Sailing Autonomous Vehicle
  • StefanL38StefanL38 Posts: 2,292
    edited 2008-09-19 22:10
    Hello Michael,

    it's true what Mike says:
    if you want to narrow down the problem you have to check EVERY single line which uses OR changes an array-value and other lines of code

    looking through the code guessing "- no there it isn't " - makes you run over the interessting point a thousand times until you decide to check it too

    to make it faster to find the place make lines of code that check array-boundaries and if the boundaries are broken send a debugstring with information of
    which method which line of code inside the method

    As you refuse to send your complete code you have to do most of the work yourself

    Did you increase stackspace always for one object and then test again ?
    then increase stackspace for the next object and test again ?

    did you check every parameter is treated as long
    every result given back from methods is a long
    all local variables are longs

    another way of narrow it down is to comment out one object
    if results processed by this object is needed many times in other objects
    make a constant dummyresult instead

    this all is NOT "just add three lines of code and we will find it"
    but as complex as yor project is the effort to find the fault has its size

    In general for developing software in the long run a strictly modular style of programming pays off
    by much lesser time spend on debugging.

    This means: every method does ONE senseful thing
    use parameters instead of global variables whereever possible

    Be careful about changing global variables
    especially if more than one cog changes tis variable
    then the order of the setting of a variable can vary a lot
    if YOU think this method in cog 1 will be always finished before cog 2
    is doing something with it I bet this is NOT true in the long run.
    there will be crossover changing the value

    You can avoid this be using semaphores and locks

    In my former company i was coding in delphi for maschinecontrols
    We used a strictly sequential way of code-execution for critical sections to make 100% sure
    that things will be executed in the order we wanted it to
    this makes it much easier to track on errors

    We coded so called statemachines to realize that


    test every method of this style on it's own

    test the behaviour if it with VERY strange parameters
    test it with zero, test it with 254, 255, 65535, 65536 with 2^32 2^32-1 test it with -100
    etc. etc. if an error occurs and you have done all this testing you can be 99.9% sure
    the error is caused in your actual new tested method (and not in previuos tested methods

    best regards

    Stefan
  • Sniper KingSniper King Posts: 221
    edited 2008-09-19 22:48
    Here is a routine that may be questionable...
    CON
      CR = 13                                               ' ASCII <CR>
      LF = 10                                               ' ASCII <LF>
      
    VAR  
       long gps_stack[noparse][[/noparse]18] 
       byte GPRMCb[noparse][[/noparse]120]
       long GPRMCa[noparse][[/noparse]120]  
       byte gps_buff[noparse][[/noparse]120],Rx',cksum
       long cog,cptr,ptr,arg,j
       long Null[noparse][[/noparse]1]
    OBJ
      uart :  "fullduplexserial_mini"
      
    PUB start(serRecv,serXmit) : okay
    '' Starts uart object (at baud specified) in a cog
    '' -- returns false if no cog available
      okay := uart.start(serRecv,serXmit,0,4800)            ' for USGlobeSat model 408 mode is 0 
                                                            ' for serial PC simulator  mode is 1
      return cog := cognew(readNEMA,@gps_stack) + 1 
        
    PUB stop
    '' Stop serial driver - frees a cog
      if cog
        cogstop(cog~ - 1)
      
     
     
    PUB readNEMA 
      Null[noparse][[/noparse]0] := 0
      repeat
       bytefill(@gps_buff,0,79)     ' zeroes the memory space
       repeat while Rx <>= "$"      ' wait for the $ to insure we are starting with
         Rx := uart.rx              ' a complete NMEA sentence 
       cptr := 0
       repeat while Rx <>= CR       '  continue to collect data until the end of the NMEA sentence 
         Rx := uart.rx              '  get character from Rx Buffer
         if Rx == ","
           gps_buff[noparse][[/noparse]cptr++] := 0    '  If "," replace the character with 0
         else
           gps_buff[noparse][[/noparse]cptr++] := Rx   '  else save the character   
       
       
       if gps_buff[noparse][[/noparse]2] == "R"             
         if gps_buff[noparse][[/noparse]3] == "M"            
           if gps_buff[noparse][[/noparse]4] == "C"           
               copy_buffer(@GPRMCb, @GPRMCa)
                       
       
                    
    pub copy_buffer ( buffer,args)
             bytemove(buffer,@gps_buff,cptr) '  copy received data to buffer
             ptr := buffer
             arg := 0
             repeat j from 0 to 78           ' build array of pointers
              if byte[noparse][[/noparse]ptr] == 0               ' to each
                 if byte[noparse][[/noparse]ptr+1] == 0           ' record
                    long[noparse][[/noparse]args][noparse][[/noparse]arg] := Null     ' in 
                 else                            ' the
                    long[noparse][[/noparse]args][noparse][[/noparse]arg] := ptr+1      ' data buffer
                 arg++
              ptr++
              
    ' now we just need to return the pointer to the desired record
              
    pub valid
       return GPRMCa[noparse][[/noparse]1]
          
    pub speed
       return GPRMCa[noparse][[/noparse]6]
    pub heading
       return GPRMCa[noparse][[/noparse]7]
       
    pub date
       return GPRMCa[noparse][[/noparse]8]
        
     
     
    
    pub latitude
       return GPRMCa[noparse][[/noparse]2]
        
    pub N_S
       return GPRMCa[noparse][[/noparse]3]
         
    pub longitude
       return GPRMCa[noparse][[/noparse]4]
        
    pub E_W
       return GPRMCa[noparse][[/noparse]5]
     
    pub noGPSData
       GPRMCa.long[noparse][[/noparse]1] := string("X")
    PUB crc8bitwise(pBuf, buflen, poly, initial): crc | i,k
    'pBuf is the string to be CRCs
    'buflen is thelength of th ebuffer to be CRCd
    'poly is the ?
    'initial is the inital value of CRC
     
      crc := initial
      repeat i from 0 to buflen - 1
        crc ^= (BYTE[noparse][[/noparse]pBuf][noparse][[/noparse]i] >< 8)
        repeat k from 0 to 7
          if crc & $80
            crc := (crc << 1) ^ poly
          else
            crc <<= 1
      crc &= $ff
      crc ><= 8
    

    ··· This is creating an array of strings that can be read by calling each method.· The stack portion I am not sure about.

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    ·- Ouch, thats not suppose to be hot!··


    Michael King
    Application Engineer
    R&D

    Check out Project: PSAV Persistent Sailing Autonomous Vehicle
  • Mike CookMike Cook Posts: 829
    edited 2008-09-19 22:55
    Since you have the following object defined:
    OBJ
      uart : "fullduplexserial_mini"
    
    

    Can we also have a look at that? Since the name has been changed from fullduplexserial to fullduplexserial_mini I'm ***UMING you have made modifications to that object. This is necessary so we can see what your code is ACTUALLY doing. Since this object was renamed we would like to know if, if anything was changed, so we don't have to waste time running a 'diff' on the code.

    ·
    Also since it was not included can we see what:
     
    _clkmode = 
    _xinfreq = 
     
    
    

    Are set for?

    It would be a whole lot easier if you would post an 'archive' of code that exhibits the problem so those that are willing to look, and help, would have all of the resources available to debug.

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    Mike

    Post Edited (Mike Cook) : 9/19/2008 11:14:28 PM GMT
  • Sniper KingSniper King Posts: 221
    edited 2008-09-19 23:05
    FullDuplexSerial_mini


    VAR
      long  cog                     'cog flag/id
      long  rx_head                 '9 contiguous longs
      long  rx_tail
      long  tx_head
      long  tx_tail
      long  rx_pin
      long  tx_pin
      long  rxtx_mode
      long  bit_ticks
      long  buffer_ptr
                         
      ' buffers need to be a power of 2
      byte  rx_buffer[noparse][[/noparse]128]           'transmit and receive buffers
    '  byte  tx_buffer[noparse][[/noparse]16]  
    
    PUB start(rxpin, txpin, mode, baudrate) : okay
    '' Start serial driver - starts a cog
    '' returns false if no cog available
    ''
    '' mode bit 0 = invert rx
    '' mode bit 1 = invert tx
    '' mode bit 2 = open-drain/source tx
    '' mode bit 3 = ignore tx echo on rx
    '  stop
      longfill(@rx_head, 0, 4)
      longmove(@rx_pin, @rxpin, 3)
      bit_ticks := clkfreq / baudrate
      buffer_ptr := @rx_buffer
     
      okay := cog := cognew(@entry, @rx_head) + 1
    
    'PUB stop
    '' Stop serial driver - frees a cog
    '  if cog
    '    cogstop(cog~ - 1)
    '  longfill(@rx_head, 0, 9)
    
    'PUB rxflush
    '' Flush receive buffer
    '  repeat while rxcheck => 0
      
        
    PUB rxcheck : rxbyte
    '' Check if byte received (never waits)
    '' returns -1 if no byte received, $00..$FF if byte
      rxbyte--
      if rx_tail <> rx_head
        rxbyte := rx_buffer[noparse][[/noparse]rx_tail]
        rx_tail := (rx_tail + 1) & $F
    
    'PUB rxtime(ms) : rxbyte | t
    '' Wait ms milliseconds for a byte to be received
    '' returns -1 if no byte received, $00..$FF if byte
    '  t := cnt
    '  repeat until (rxbyte := rxcheck) => 0 or (cnt - t) / (clkfreq / 1000) > ms
      
    PUB rx : rxbyte
    '' Receive byte (may wait for byte)
    '' returns $00..$FF
      repeat while (rxbyte := rxcheck) < 0
    
    'PUB tx(txbyte)
    '' Send byte (may wait for room in buffer)
    '  repeat until (tx_tail <> (tx_head + 1) & $F)
    '  tx_buffer[noparse][[/noparse]tx_head] := txbyte
    '  tx_head := (tx_head + 1) & $F
    '  if rxtx_mode & %1000
    '    rx
     
    DAT
    '***********************************
    '* Assembly language serial driver *
    '***********************************
                            org
    '
    '
    ' Entry
    '
    entry                   mov     t1,par                'get structure address
                            add     t1,#4 << 2            'skip past heads and tails
                            rdlong  t2,t1                 'get rx_pin
                            mov     rxmask,#1
                            shl     rxmask,t2
                            add     t1,#4                 'get tx_pin
                            rdlong  t2,t1
                            mov     txmask,#1
                            shl     txmask,t2
                            add     t1,#4                 'get rxtx_mode
                            rdlong  rxtxmode,t1
                            add     t1,#4                 'get bit_ticks
                            rdlong  bitticks,t1
                            add     t1,#4                 'get buffer_ptr
                            rdlong  rxbuff,t1
                            mov     txbuff,rxbuff
                            add     txbuff,#128
                            test    rxtxmode,#%100  wz    'init tx pin according to mode
                            test    rxtxmode,#%010  wc
            if_z_ne_c       or      outa,txmask
            if_z            or      dira,txmask
                            mov     txcode,#transmit      'initialize ping-pong multitasking
    '
    '
    ' Receive
    '
    receive                 jmpret  rxcode,txcode         'run a chunk of transmit code, then return
                            test    rxtxmode,#%001  wz    'wait for start bit on rx pin
                            test    rxmask,ina      wc
            if_z_eq_c       jmp     #receive
                            mov     rxbits,#9             'ready to receive byte
                            mov     rxcnt,bitticks
                            shr     rxcnt,#1
                            add     rxcnt,cnt                          
    :bit                    add     rxcnt,bitticks        'ready next bit period
    :wait                   jmpret  rxcode,txcode         'run a chuck of transmit code, then return
                            mov     t1,rxcnt              'check if bit receive period done
                            sub     t1,cnt
                            cmps    t1,#0           wc
            if_nc           jmp     #:wait
                            test    rxmask,ina      wc    'receive bit on rx pin
                            rcr     rxdata,#1
                            djnz    rxbits,#:bit
                            shr     rxdata,#32-9          'justify and trim received byte
                            and     rxdata,#$FF
                            test    rxtxmode,#%001  wz    'if rx inverted, invert byte
            if_nz           xor     rxdata,#$FF
                            rdlong  t2,par                'save received byte and inc head
                            add     t2,rxbuff
                            wrbyte  rxdata,t2
                            sub     t2,rxbuff
                            add     t2,#1
                            and     t2,#$0F
                            wrlong  t2,par
                            jmp     #receive              'byte done, receive next byte
    '
    '
    ' Transmit
    '
    transmit                jmpret  txcode,rxcode         'run a chunk of receive code, then return
                            mov     t1,par                'check for head <> tail
                            add     t1,#2 << 2
                            rdlong  t2,t1
                            add     t1,#1 << 2
                            rdlong  t3,t1
                            cmp     t2,t3           wz
            if_z            jmp     #transmit
                            add     t3,txbuff             'get byte and inc tail
                            rdbyte  txdata,t3
                            sub     t3,txbuff
                            add     t3,#1
                            and     t3,#$0F
                            wrlong  t3,t1
                            or      txdata,#$100          'ready byte to transmit
                            shl     txdata,#2
                            or      txdata,#1
                            mov     txbits,#11
                            mov     txcnt,cnt
    :bit                    test    rxtxmode,#%100  wz    'output bit on tx pin according to mode
                            test    rxtxmode,#%010  wc
            if_z_and_c      xor     txdata,#1
                            shr     txdata,#1       wc
            if_z            muxc    outa,txmask        
            if_nz           muxnc   dira,txmask
                            add     txcnt,bitticks        'ready next cnt
    :wait                   jmpret  txcode,rxcode         'run a chunk of receive code, then return
                            mov     t1,txcnt              'check if bit transmit period done
                            sub     t1,cnt
                            cmps    t1,#0           wc
            if_nc           jmp     #:wait
                            djnz    txbits,#:bit          'another bit to transmit?
                            jmp     #transmit             'byte done, transmit next byte
    '
    '
    ' Uninitialized data
    '
    t1                      res     1
    t2                      res     1
    t3                      res     1
    rxtxmode                res     1
    bitticks                res     1
    rxmask                  res     1
    rxbuff                  res     1
    rxdata                  res     1
    rxbits                  res     1
    rxcnt                   res     1
    rxcode                  res     1
    txmask                  res     1
    txbuff                  res     1
    txdata                  res     1
    txbits                  res     1
    txcnt                   res     1
    txcode                  res     1
    

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    ·- Ouch, thats not suppose to be hot!··


    Michael King
    Application Engineer
    R&D

    Check out Project: PSAV Persistent Sailing Autonomous Vehicle
  • Phil Pilgrim (PhiPi)Phil Pilgrim (PhiPi) Posts: 23,514
    edited 2008-09-19 23:18
    Pursuant to my first comment, 18 longs might be a bit stingy for gps_stack. Try setting it to 50 and see if anything changes.

    -Phil

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    'Still some PropSTICK Kit bare PCBs left!
  • Sniper KingSniper King Posts: 221
    edited 2008-09-19 23:50
    i set it to 100 and nothing...

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    ·- Ouch, thats not suppose to be hot!··


    Michael King
    Application Engineer
    R&D

    Check out Project: PSAV Persistent Sailing Autonomous Vehicle
  • Mike GreenMike Green Posts: 23,101
    edited 2008-09-19 23:54
    I can see that it's really easy to overflow gps_buff. I would be very careful with anything using an X++ type of subscript. An innocuous error somewhere else can lead to overwriting other variables.
  • Sniper KingSniper King Posts: 221
    edited 2008-09-19 23:58
    So, if I put a cap on that.· I might make this go away.· I'll give that a try.

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    ·- Ouch, thats not suppose to be hot!··


    Michael King
    Application Engineer
    R&D

    Check out Project: PSAV Persistent Sailing Autonomous Vehicle
  • Mike GreenMike Green Posts: 23,101
    edited 2008-09-20 00:07
    Just as a pedagogical point ... You DID say that you had put in checks for invalid array subscripts, yet in this one posted example, they're missing. One of the things I learned about programming (debugging especially) is that you have to be honest with yourself about what you've done or not done, you have to be willing to look dispassionately at your own code, and you can't add reliability to your program, you have to design it in. You can have consistency checks where they won't cost too much space or execution time.
Sign In or Register to comment.