Shop OBEX P1 Docs P2 Docs Learn Events
Problems with pcFullDuplexSerial4FC using port 0 as Debug Terminal — Parallax Forums

Problems with pcFullDuplexSerial4FC using port 0 as Debug Terminal

Steve LindengSteve Lindeng Posts: 6
edited 2009-05-06 17:28 in Propeller 1
Tim, if you're out there, HELP!

Seriously though, this is probably a simple problem of not understanding the object and what's passed.· I have an application where I'd like to use debug terminal to confirm the instructions and data are passed properly before I 'blindly' set the data stream.

Eventually, I will have two UART peripherals attached to the propeller - one uses #RTS/#CTS (RTS and CTS low handshake) for flow control and another with no flow control.· Looking at the pcFullDuplexSerial4FC, I see that I can invert RTS or invert CTS, but it combining the code for invert RTS and Invert CTS does not appear to be supported:

······· if_nz·········· xor···· start0,doifc2ifnc···· 'if_c jmp to if_nc
····················································· 'patch tx routine depending on whether cts is used
····················································· 'and if it is inverted
······················· or····· ctsmask,#0···· wz···· 'cts pin? z not set if in use
······· if_nz·········· test··· rxtx_mode,#INVERTCTS wc 'c set if inverted
······· if_nz_and_nc··· or····· ctsi0,doif_z_or_nc··· 'if_nc jmp
······· if_nz_and_c···· or····· ctsi0,doif_z_or_c···· 'if_c jmp
······· if_z··········· mov···· txcts0,transmit······ 'copy the jmpret over the cts test
······· if_z··········· movs··· ctsi0,#txcts0········ 'patch the jmps to transmit to txcts0·
······· if_z··········· add···· txcode,#1············ 'change co-routine entry to skip first jmpret
····················································· 'patch rx routine depending on whether rts is used
····················································· 'and if it is inverted
······················· or····· rtsmask,#0···· wz···· 'rts pin, z not set if in use
······· if_nz·········· test··· rxtx_mode,#INVERTRTS wc
······· if_nz_and_nc··· or····· rts0,domuxnc········· 'patch muxc to muxnc
······· if_z··········· mov···· norts0,rec0i········· 'patch to a jmp #receive
······· if_z··········· movs··· start0,#receive······ 'skip all rts processing if not used
····················································· 'patch all of tx routine out if not used·················
······················· or····· txmask,#0······ wz
'······· if_z··········· mov···· txcode,rxcode1······· 'use variable in case it has been changed
····················································· 'patch all of rx routine out if not used·················
······················· or····· rxmask,#0······ wz

Did I miss something?

In any case, I can start the debug as port 0 and it appears to kind of work, but starting the inverted RTS/CTS UART as Port 1 'loses' Port 0.· Do I need to restart (COGINIT) the cog identified for port 0 when initializing port 1 (use init method + addport method?

Any advice would be illuminating.

·

Comments

  • MagIO2MagIO2 Posts: 2,243
    edited 2009-05-05 03:57
    Without knowing the object, I have the following guesses:

    This is self modifying code, which uses different jmp and mux instructions for the different flags set. If you want to have low RTS and CTS you simply do an OR with both flags, when you initialize the object (start? function)
    INVERTCTS | INVERTRTS and it should work.

    As mentioned, I don't know the object yet, but I think if you want to run 2 serial ports with it, you need two objects as well:
    obj
    ser1: "FullDuplexSerial4FC"
    ser2: "FullDuplexSerial4FC"

    pub
    ser1.start(....)
    ser2.start(....)
  • Mike GreenMike Green Posts: 23,101
    edited 2009-05-05 04:07
    MagIO,
    You only need one object to support up to 4 serial ports.

    Steve,
    I know you have to initialize the ports (Addport) that you're going to use prior to starting the cog (Start) so the proper code can be generated.

    I haven't tried what you want, but it looks like each port's settings affect a different instruction, so it should work.
  • MagIO2MagIO2 Posts: 2,243
    edited 2009-05-05 05:13
    Hi Mike,

    from a first glance I thought 4 stands for 'for FC'. Who could imagine that 4 stands for 4? ;o) Nice driver then. Are the serial IOs completely independend in FC and speed?
    Then it seems to be a sophisticated piece of code. Need to have a look at it.
  • Mike GreenMike Green Posts: 23,101
    edited 2009-05-05 05:22
    Read the comments at the beginning. They're pretty complete.
  • Steve LindengSteve Lindeng Posts: 6
    edited 2009-05-05 17:15
    Mike, MagIO, Thanks for the input.

    If I understand the asm code correctly now, the 'test rxtx_mode,#INVERTCTS (or #INVERTRTS, they work the same) wc'·will do a bitwise AND of rxtx_mode against the CON #INVERT??? and as long as the bitwise AND is an odd number, set the c flag to 1.· Now, I can see if c is set to 1, a particular patch is applied, but I still haven't figured out how that sets FC high or low - or if I need to figure that out.

    The implication is that if I set rxtx_mode to $11000 (bitwise·#INVERTCTS | #INVERTRTS), then I should get both inverted RTS and CTS.· I've tried this, but it may also be a slip in the code on setting the ports properly.

    BTW, from my testing, 'pcFullDuplexSerial4FC' may stand for 'propeller code Full Duplex Serial 4 Port Flow Control.'· The code is POWERFUL, though confusing (it's been nearly 30 years since I seriously programmed in assembly, so I'm rusty).

    If this works, I'll attach the modified object (code added to SimpleDebug.spin) for your review.
  • TimmooreTimmoore Posts: 1,031
    edited 2009-05-05 20:07
    Steve, There are a couple of places to look, the initialization code, patches the runtime rx/tx routines, both for rtc/cts on/off based on whether there is a pin assigned to cts/rts and invert rtc/cts.
    At the start of tx look for txctsX(0-3) to ctsiX, that code is patched, to bypass the cts testing or to invert the test - if_z in ctsi0 is patched to if_z_or_c or if_z_or_nc. Similar code at the end of tx - txjmp0 is patched to skip the cts test. Also in rx look for nortsX to rtsX that code is patched for rts.
    I did have the cts/rts logic inverted originally. I uploaded the fixed code - the comments should have 8/14 as the fix date for cts/rts invert.
  • Steve LindengSteve Lindeng Posts: 6
    edited 2009-05-05 20:15
    Thanks Tim for the comments.

    The version of 'pcFullDuplexSerial4FC' has the last comment as 7/24/08 (I downloaded this 5/1/09), so its possible that the latest updated object is not properly in the object forum. I'd appreciate if you could upload the latest version again or attach to another reply.

    Steve.

    P.S. Have you thought of using COGINIT to allow restarts of the UART cog? I tried a small mod to your program, but i haven't tried to run it:

    PUB restart(SameCog)
    '' Restarts the cog initialized before
    '' Returns false if Cog is already utilized.
    Coginit(SameCog,@entry,@rx_head)
  • TimmooreTimmoore Posts: 1,031
    edited 2009-05-06 05:47
    I just call init, addport and start to restart the cog, heres an example that I use - start debug and a gps port, change the baud rate of the gps and then restart with a 3rd port and a different baud rate for the GPS

      uarts.Init
      uarts.AddPort(0,config.GetPin(CONFIG#DEBUG_RX),config.GetPin(CONFIG#DEBUG_TX),{
    }   UARTS#PINNOTUSED,UARTS#PINNOTUSED,UARTS#DEFAULTTHRESHOLD, {
    }   UARTS#NOMODE,UARTS#BAUD115200)                      'Add debug port
      uarts.AddPort(1,config.GetPin(CONFIG#GPS_RX),config.GetPin(CONFIG#GPS_TX),{
    }   UARTS#PINNOTUSED,UARTS#PINNOTUSED,UARTS#DEFAULTTHRESHOLD, {
    }   UARTS#NOMODE,UARTS#BAUD4800)                        'Add gps port
      uarts.Start                                           'Start the ports
      
      uarts.str(0,string("Starting",13))
      gps.Init(1)                                           'use Init and then uses BackGround cog
                                                            'to process GPS receive characters
                                                            'Note the background cog isn't running
                                                            'but it doesn't seem to affect us sending
                                                            'commands to gps
      gps.configbaud                                        'Change GPS baudrate
      waitcnt(clkfreq + cnt)
      uarts.Init                                            'Restart serial ports to change baudrate
      uarts.AddPort(0,config.GetPin(CONFIG#DEBUG_RX),config.GetPin(CONFIG#DEBUG_TX),{
    }   UARTS#PINNOTUSED,UARTS#PINNOTUSED,UARTS#DEFAULTTHRESHOLD, {
    }   UARTS#NOMODE,UARTS#BAUD115200)                      'Add debug port
      uarts.AddPort(1,config.GetPin(CONFIG#GPS_RX),config.GetPin(CONFIG#GPS_TX),{
    }   UARTS#PINNOTUSED,UARTS#PINNOTUSED,UARTS#DEFAULTTHRESHOLD, {
    }   UARTS#NOMODE,UARTS#BAUD38400)                       'Add gps port
      uarts.AddPort(2,config.GetPin(CONFIG#CMUCAM_RX),config.GetPin(CONFIG#CMUCAM_TX),{
    }   UARTS#PINNOTUSED,UARTS#PINNOTUSED,UARTS#DEFAULTTHRESHOLD, {
    }   UARTS#NOMODE,116500)                                'Add camera port
    
    

    I have attached my latest version to this reply.
  • Steve LindengSteve Lindeng Posts: 6
    edited 2009-05-06 16:01
    Thanks Tim:

    I'll work with the new pcFullDuplexSerial4FC and your suggested entry code.· Your entry code appears to imply we have to completely re-initialize the parameters for all ports when we change any port - this is because we do not store which cog is running UART?· Or does the stop/init methods clear all pointers?

    Attached is a re-write of SimpleDebug to start a debug in a cog using pcFullDuplexSerial4FC.· I've reworked from your comments, but it worked previously (in terms of passing port info and starting the cog correctly).

    Steve.
  • TimmooreTimmoore Posts: 1,031
    edited 2009-05-06 17:28
    I think you are trying to setup DebugRedux so it contains its own port config rather than having to centralize it in the app startup code.
    If you do the changes below, and then change DebugRedux to use ReInit and before initializing DebugRedux call uarts.init once at start of your app. I think it will do what you are trying to do.
    I would make one suggestion, pass the port number for uart into DebugRedux rather than have it hardcoded as 0. It would allow easier combination of objects that use different ports.

    The simplest change would be to add a routine
    PUB ReInit
    '' Stop serial driver - frees a cog
      if cog
        cogstop(cog~ - 1)
    
    

    Then modify AddPort to (since it assumes the variables are initialized to 0 and ReInit will not)
    PUB AddPort(port,rxpin,txpin,ctspin,rtspin,rtsthreshold,mode,baudrate)
    '' Call AddPort to define each port
    '' port 0-3 port index of which serial port
    '' rx/tx/cts/rtspin pin number                          XXX#PINNOTUSED if not used
    '' rtsthreshold - buffer threshold before rts is used   XXX#DEFAULTTHRSHOLD means use default
    '' mode bit 0 = invert rx                               XXX#INVERTRX
    '' mode bit 1 = invert tx                               XXX#INVERTTX
    '' mode bit 2 = open-drain/source tx                    XXX#OCTX
    '' mode bit 3 = ignore tx echo on rx                    XXX#NOECHO
    '' mode bit 4 = invert cts                              XXX#INVERTCTS
    '' mode bit 5 = invert rts                              XXX#INVERTRTS
    '' baudrate
      if cog OR (port > 3)
        abort
      if rxpin <> -1
        long[noparse][[/noparse]@rxmask][noparse][[/noparse]port] := |< rxpin
      else 
        long[noparse][[/noparse]@rxmask][noparse][[/noparse]port] := 0
      if txpin <> -1
        long[noparse][[/noparse]@txmask][noparse][[/noparse]port] := |< txpin
      else 
        long[noparse][[/noparse]@txmask][noparse][[/noparse]port] := 0
      if ctspin <> -1
        long[noparse][[/noparse]@ctsmask][noparse][[/noparse]port] := |< ctspin
      else 
        long[noparse][[/noparse]@ctsmask][noparse][[/noparse]port] := 0
      if rtspin <> -1
        long[noparse][[/noparse]@rtsmask][noparse][[/noparse]port] := |< rtspin
        if (rtsthreshold > 0) AND (rtsthreshold < 64)
          long[noparse][[/noparse]@rtssize][noparse][[/noparse]port] := rtsthreshold
        else
          long[noparse][[/noparse]@rtssize][noparse][[/noparse]port] := 48                        'default rts threshold 3/4 of buffer
      else 
        long[noparse][[/noparse]@rtsmask][noparse][[/noparse]port] := 0
      long[noparse][[/noparse]@rxtx_mode][noparse][[/noparse]port] := mode
      if mode & INVERTRX
        byte[noparse][[/noparse]@rxchar][noparse][[/noparse]port] := $ff
      else 
        byte[noparse][[/noparse]@rxchar][noparse][[/noparse]port] := 0
      long[noparse][[/noparse]@bit_ticks][noparse][[/noparse]port] := (clkfreq / baudrate)
      long[noparse][[/noparse]@bit4_ticks][noparse][[/noparse]port] := long[noparse][[/noparse]@bit_ticks][noparse][[/noparse]port] >> 2
    
    
    
    
     
    

    Then my init code would change to (note the reinit call and the removed addport(0...)

    uarts.Init
      uarts.AddPort(0,config.GetPin(CONFIG#DEBUG_RX),config.GetPin(CONFIG#DEBUG_TX),{
    }   UARTS#PINNOTUSED,UARTS#PINNOTUSED,UARTS#DEFAULTTHRESHOLD, {
    }   UARTS#NOMODE,UARTS#BAUD115200)                      'Add debug port
      uarts.AddPort(1,config.GetPin(CONFIG#GPS_RX),config.GetPin(CONFIG#GPS_TX),{
    }   UARTS#PINNOTUSED,UARTS#PINNOTUSED,UARTS#DEFAULTTHRESHOLD, {
    }   UARTS#NOMODE,UARTS#BAUD4800)                        'Add gps port
      uarts.Start                                           'Start the ports
      
      uarts.str(0,string("Starting",13))
      gps.Init(1)                                           'use Init and then uses BackGround cog
                                                            'to process GPS receive characters
                                                            'Note the background cog isn't running
                                                            'but it doesn't seem to affect us sending
                                                            'commands to gps
      gps.configbaud                                        'Change GPS baudrate
      waitcnt(clkfreq + cnt)   uarts.ReInit                                          'Restart serial ports to change baudrate
      uarts.AddPort(1,config.GetPin(CONFIG#GPS_RX),config.GetPin(CONFIG#GPS_TX),{
    }   UARTS#PINNOTUSED,UARTS#PINNOTUSED,UARTS#DEFAULTTHRESHOLD, {
    }   UARTS#NOMODE,UARTS#BAUD38400)                       'Add gps port
      uarts.AddPort(2,config.GetPin(CONFIG#CMUCAM_RX),config.GetPin(CONFIG#CMUCAM_TX),{
    }   UARTS#PINNOTUSED,UARTS#PINNOTUSED,UARTS#DEFAULTTHRESHOLD, {
    }   UARTS#NOMODE,116500)                                'Add camera port
    
    
    

    I can go further and do the equalivalent that you have done to the camera and gps code and move hte port config/baud rate modification code into those objects.

    You can also disable a port by calling AddPort and set tx/rx pins to PINNOTUSED

    Note: It still has some effect on other ports, during the reconfiguration, you can't receive/transmit on ports that are not being changed, since they are being re-initialized, just to the same values. So you have to be sure that all the port configuration is done when the other ports are not sending/receiving.
    ·
Sign In or Register to comment.