Shop OBEX P1 Docs P2 Docs Learn Events
Multiple instances of Full Duplex Serial interacting — Parallax Forums

Multiple instances of Full Duplex Serial interacting

sstandfastsstandfast Posts: 39
edited 2011-02-10 18:10 in Propeller 1
I have an application that I am working on that the top level object uses the Full Duplex Serial object for debug/status purposes. The application also has a child object that uses its own instance of the Full Duplex Serial object. My prototype is built on the USB protoboard. Since the application will primarily run with the USB disconnected, I have set up the top object to first detect the state of the RX line of the FTDI chip at power up. This is used to determine if the unit is connected to the USB. If it detects a USB connection, then the top object starts/initializes its instance of the Full Duplex Serial object and then spits out debug/status data to the PC at certain key events. If the Prop does not detect the USB at power up, it waits up to 10 seconds before it skips the FDS initialization and sets a flag indicating that the USB is not present so the top object should skip all writes to that instance of the FDS object.

The child object's instance of Full Duplex Serial is always initialized and is independent of the top object's instance. The issue I am having is that when the USB is not connected, for some reason BOTH instances of FDS stop working. The rest of the application functions fine but all serial communication fails. As long as the USB is connected, all works fine. Has anyone seen something like this before? Just to be clear the setup is similar to this:
'file top.spin

obj
  mychild : "child.spin"
  debug : "FullDuplexSerial.spin"

var
  USB_Detect

pub main
  if ina[rx_pin] == 0
    'no USB detected
    USB_Detect := false
  else
    'USB detected
    debug.start(TX,RX,MODE,BAUD)
    USB_Detect := true

  myChild.start(TX_Node, RX_Node)
  
  if USB_Detect == true
    debug.str(string("Some Debug Data ")

  result := myChild.getStatus

Then the child object looks similar to:
'file child.spin
obj
  serial : "FullDuplexSerial"
pub start(tx_pin, rx_pin)
  serial.start( tx_pin, rx_pin, 0, 9600)
  'Some more initializations.

pub GetStatus
  serial.tx(......Status Request Message)
  Status := serial.rx
  return Status

This is definitely not correct code, it is just merely intended to illustrate how the two objects are setup and why it is weird that by not initializing the top objects instance of FDS, the child's object ceases to function as well. Has anyone seen this before? If necessary I can post the actual code tomorrow, I just don't have access to it on this computer. Just let me know if you would like to look at it.

Shawn

Comments

  • Mike GreenMike Green Posts: 23,101
    edited 2011-02-09 21:46
    There is no reason why not initializing the top object's instance of FDS would affect the child object's instance of FDS unless the I/O pins were the same. Since that's not what you're observing, there must be some difference between what you've posted and the actual code that you're trying to run. If you do post that code, please please do not use the CODE blocks for something bigger than what you've posted, use the Attachment Manager that you get with the Reply button (not the + Reply to Thread).
  • sstandfastsstandfast Posts: 39
    edited 2011-02-09 22:12
    Thanks Mike. I thought that this was not expected behavior. I have attached a .ZIP file that contains the entire project directory, including any modified versions of standard includes. Which coincidentally Full Duplex Serial has been modified, but only by adding another subroutine (dec_), nothing else. The new dec_ routine allows me to print decimal numbers with leading zeros so that it always has a fixed number of digits. The top object is called Debug - Top Object.spin. The child object that uses Full Duplex Serial is Node_Interface.spin. As far as I can tell, the setup is exactly as I described it. What I am seeing when the USB is disconnected at power-up is the webpage shows 0's for all temperatures and there is no serial activity what-so-ever with the remote nodes (verified by O'Scope). If I connect the USB to my board, then everything functions as expected. I'm sure it is something simple and obvious that I am overlooking but I just can't see it. Any help would be appreciated.

    Thanks,

    Shawn

    Project.zip
  • Mike GreenMike Green Posts: 23,101
    edited 2011-02-10 08:35
    I've looked at how you're using FullDuplexSerial and I still cannot see anything that would explain the behavior that you're observing. You should be able to have any number of instances of FullDuplexSerial running (subject to the availability of a cog) without interaction. I've had two copies running at different object levels as you're doing ... works great. Others have had more instances. If you have a spare I/O pin or two, you might hook up some LEDs and trace through the child object looking at its interaction with FullDuplexSerial.
  • Dave HeinDave Hein Posts: 6,347
    edited 2011-02-10 09:16
    You have some places in your top object where you aren't checking ComConnected and you call debug.tx, debug.str, etc. Since the serial cog hasn't been started the transmit buffer will fill up after sending 15 characters. When you send the 16-th character the top object will get stuck waiting for space to open up in the transmit buffer. You should either ensure that ComConnected is checked before calling the debug methods throughout your top object, or just call the debug.start method even if the pin is not connected and don't bother with the ComConnected flag.
  • sstandfastsstandfast Posts: 39
    edited 2011-02-10 11:54
    Thanks Dave,

    I too found those few places this morning after posting, although some of those blocks are new additions that post-date the interaction issue. Namely the IF addr <> tmp block was added well after the USB problem was observed. The missing check in PrintNetworkConfig however, has been there from the beginning and is most likely where the problem is occurring, stalling the main loop and never initializing the remote nodes. I will retry the code when I get home from work.

    I wish I could simply always initialize the top-level serial port but since this project is built on the Parallax USB Protoboard that is unfortunately not an option if this is to run with the USB disconnected. Otherwise I get constant resets caused by the FTDI chip.

    Thanks for the heads up, I will post back with the results.

    Shawn
  • Mike GreenMike Green Posts: 23,101
    edited 2011-02-10 12:12
    Another option would be to modify FullDuplexSerial adding a mode bit that causes the cog starting to be skipped. The tx routine is the only one that references the output buffer and could check whether a cog has been started. You could also modify the input routines to behave consistently if there's no input port.
    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
    '' mode bit 4 = don't start the I/O routines
    
      stop
      longfill(@rx_head, 0, 4)
      longmove(@rx_pin, @rxpin, 3)
      bit_ticks := clkfreq / baudrate
      buffer_ptr := @rx_buffer
      if mode & %10000
        okay := true   ' Result shows no errors
        cog := 0   ' No cog started though
      else
        okay := cog := cognew(@entry, @rx_head) + 1
    
    and
    PUB tx(txbyte)
    
    '' Send byte (may wait for room in buffer)
    
      if cog > 0   ' Do nothing if a cog isn't running
        repeat until (tx_tail <> (tx_head + 1) & constant(tx_size-1))
        tx_buffer[tx_head] := txbyte
        tx_head := (tx_head + 1) & constant(tx_size-1)
    
        if rxtx_mode & %1000
          rx
    
  • Dave HeinDave Hein Posts: 6,347
    edited 2011-02-10 12:17
    Or you could specify and unused pin as output when calling the start function.
  • sstandfastsstandfast Posts: 39
    edited 2011-02-10 13:31
    @Mike - I think I like that idea best as a permanent solution. Right now things are still in the early development stages; still just trying to get basic code structure on how it's going to look figured out. By moving the check into the serial routine itself, this will result in smaller and faster code since there will be far fewer conditional expressions.

    @Dave - Using an unassigned pin is also an option, just not for this project since when it is all done, there will not be any unassigned pins. In fact, I am going to have to add a small PIC to the board with a serial interface to the Prop just to control a small HD44780 LCD because I don't have enought I/O on the Prop. There should be plenty of CPU power available, just not enough I/O, unless I get really creative with some multiplexing schemes.

    I'll post back once I've had a chance to try out the new code changes.

    Thanks for the feedback,

    Shawn
  • sstandfastsstandfast Posts: 39
    edited 2011-02-10 18:10
    It works! I made the changes suggested by Mike to FullDuplexSerial and then removed all checks for ComConnected in the top object file and it now works as expected with the USB disconnected. The program also used 38 fewer longs as well. I knew it had to be something simple but sometimes it takes a second or third pair of eyes to see it. Thanks to Mike and Dave for your help!

    Shawn
Sign In or Register to comment.