Shop OBEX P1 Docs P2 Docs Learn Events
FullDuplexSerial hiccups? — Parallax Forums

FullDuplexSerial hiccups?

pullmollpullmoll Posts: 817
edited 2010-03-16 20:21 in Propeller 1
I'm using Chip Gracey's FullDuplexSerial.spin in my project. I'm interfacing with it by PASM code filling FDS's txbuff.
When I put pressure on it by doing a hex/ASCII dump of 64K memory as fast as I can, I experienced a garbage character at around once per second. Now looking for a possible reason in the code, I saw the following timing bits:
                        ...
: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
                        ...



Similar code is to be found in the tx section. It occured to me that the compare was unnecessary, because the subtraction t1 - cnt would already indicate a timer expiry. So I changed the code to:
                        ...
: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          wc
        if_nc         jmp     #:wait
                        ...



and the one-per-second hiccups seem to be gone. There are still some garbage characters transmitted to my terminal, but they occur at a slower rate.
Edit: Observing for a little longer it seems they occur nearly as often, just not at that determined rate.

Does anyone have used FDS to transmit large amounts of data at 115kbps and seen these hiccups, or is it on my (receiver's) side?

TIA,
Juergen

▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
He died at the console of hunger and thirst.
Next day he was buried. Face down, nine edge first.

Post Edited (pullmoll) : 3/15/2010 1:49:00 PM GMT

Comments

  • MagIO2MagIO2 Posts: 2,243
    edited 2010-03-15 13:50
    Hmm ... not sure if a simple sub will work correctly in the area of CNT-wraparound. That's maybe why chip has this code in place. This needs a silent moment or a test-system ... both of which I currently do not have because I'm at work ;o)
  • pullmollpullmoll Posts: 817
    edited 2010-03-15 13:55
    MagIO2 said...
    Hmm ... not sure if a simple sub will work correctly in the area of CNT-wraparound. That's maybe why chip has this code in place. This needs a silent moment or a test-system ... both of which I currently do not have because I'm at work ;o)

    Wrapping case:
    rxcnt = $fffffff0
    bitticks = $20

    new rxcnt = $00000010
    CNT = $fffffff8
    sub t1, CNT = $18 okay - doesn't generate a carry.
    CNT = $ffffffff
    sub t1, CNT = $11 okay - doesn't generate a carry.
    CNT = $0000000f
    sub t1, CNT = $01 okay - doesn't generate a carry.
    CNT = $00000011
    sub t1, CNT = $ffffffff carry flag set, gotcha.

    Looks okay to me!?

    I think the wrapping case would occur roughly once per minute at 80MHz.

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    He died at the console of hunger and thirst.
    Next day he was buried. Face down, nine edge first.

    Post Edited (pullmoll) : 3/15/2010 2:11:57 PM GMT
  • kuronekokuroneko Posts: 3,623
    edited 2010-03-15 14:25
    pullmoll said...
    new rxcnt = $00000010
    CNT = $fffffff8
    sub t1, CNT = $18 okay - doesn't generate a carry.
    

    In fact it does generate a carry. sub treats its operands as unsigned int's and carry is unsigned borrow.
  • pullmollpullmoll Posts: 817
    edited 2010-03-15 15:01
    kuroneko said... In fact it does generate a carry. sub treats its operands as unsigned int's and carry is unsigned borrow.

    Err, I can't test that just now, because I'm unable to write a little test program that would verify it... Perhaps you can do.
    Just blink with a LED on P16 if your statement holds true.

    The way an ALU subtracts a value is it builds the one's complement of the subtrahend, does an addition and then adds 1 to the result. A one's complement + 1 is also called a two's complement, anyway...
    So $10 - $fffffff8 would be executed as $10 + $00000007 + 1 = $18 and no carry or borrow is involved here.

    But you made me a little nervous now, I have to go and think about the very basics of binary computation again.

    Edit: Darn! You are right! I wouldn't have expected this, but the simple SUB does set the carry in this case. The SUBS does not, but I don't know how this would work for the cases around $7fffffff / $80000000.
    Edit2: Tested for $80000010 - $7fffffff with SUBS this generates a carry (or borrow).
    Conclusion: Chip's code is right in doing what it did - and I have learned my lesson smile.gif

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    He died at the console of hunger and thirst.
    Next day he was buried. Face down, nine edge first.

    Post Edited (pullmoll) : 3/15/2010 3:45:18 PM GMT
  • Dave HeinDave Hein Posts: 6,347
    edited 2010-03-15 15:59
    The CMP and SUB instructions are identical, except that CMP defaults to NR and SUB defaults to WR.· The description for CMP states that the carry is set if the unsigned value of value1 is less than value2.· CMPS and SUBS also work the same, exept they use signed values.

    It would be useful if you posted all your code.· The glitch you are seeing could occur if you update tx_head just before you put the byte in tx_buffer.· In that case FDS could print an old character in the buffer from 16 bytes earlier.

    Dave
  • pullmollpullmoll Posts: 817
    edited 2010-03-15 16:05
    Dave Hein said...
    It would be useful if you posted all your code.

    Hi Dave,
    here's the code I use:
    '*******************************************
    '
    ' Write data to the FullDuplexSerial
    ' tx_buffer
    '
    tx
            rdlong    t1, tx_head
            mov    t3, t1
            add    t1, #1
            rdlong    t2, tx_tail
            and    t1, #15
            cmp    t1, t2 WZ
        if_z    jmp    #tx            ' wait until there's room in the buffer
            mov    t1, t3
            add    t1, tx_buffer
            wrbyte    data, t1
            sub    t1, tx_buffer
            add    t1, #1
            and    t1, #15
            wrlong    t1, tx_head        ' increment the tx_head
    tx_ret
            ret
    
    



    I just realized that this one would be much shorter:
    '*******************************************
    '
    ' Write data to the FullDuplexSerial tx_buffer
    '
    tx
            rdlong    t1, tx_head
            mov    t3, t1
            add    t1, #1
            rdlong    t2, tx_tail
            and    t1, #15
            cmp    t1, t2 WZ
        if_z    jmp    #tx            ' wait until there's room in the buffer
            add    t3, tx_buffer
            wrbyte    data, t3
            wrlong    t1, tx_head        ' increment the tx_head
    tx_ret
            ret
    
    

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    He died at the console of hunger and thirst.
    Next day he was buried. Face down, nine edge first.

    Post Edited (pullmoll) : 3/15/2010 4:18:22 PM GMT
  • pullmollpullmoll Posts: 817
    edited 2010-03-15 22:23
    New observation: It looks like not a garbage character is transmitted, but as if a whole 16 byte block is missing. Some lines are missing a section of 16 characters, and if the CR char is in the missing block, then two lines are joined and this appeared as if some garbage was sent. It looks like I'm the only one with this problem, so perhaps it's on the receiver's side.

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    He died at the console of hunger and thirst.
    Next day he was buried. Face down, nine edge first.
  • Dave HeinDave Hein Posts: 6,347
    edited 2010-03-15 23:18
    If you are missing 16 characters at a time it sounds like the write index is over running the read index.· Instead of having 16 characters in the buffer it·would look like it is empty because the head and tail values match.· Your code should protect against this, but it hard to tell what's going on without seeing all the code.

    You could try sending a known pattern and looping it back to the rx pin.· If you sent an incrementing byte pattern you could detect a break in the pattern and print out a message.· You would need another instance of FDS to be able to print it out.· Or maybe you could use a video display to show the debug messages.
  • Dr_AculaDr_Acula Posts: 5,484
    edited 2010-03-16 00:21
    115k is pretty fast. Even though I understand the propeller is programmed at that rate, I've not managed to get any comms at 115k using the same hardware. I just kept slowing things down till they worked. And by the time you have pasm emulating a Z80 running xmodem, the max speed where it would all work is only 19200 baud. So I suspect that is why I have never seen this problem. Sorry that isn't much help. I've got a few long cables around the place and had problems with anything more than 38k. Indeed, back in the olden days when I had a serial terminal computer and 4 metres of bare wires doing the RS232, 9600 was the max rate. So for me, anything more than 9600 is a bonus!

    I think Kye has some serial code. And there is the 4 port serial object in the obex (64 byte buffers). I wonder if they can replicate this problem?

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    www.smarthome.viviti.com/propeller

    Post Edited (Dr_Acula) : 3/16/2010 2:21:07 AM GMT
  • Phil Pilgrim (PhiPi)Phil Pilgrim (PhiPi) Posts: 23,514
    edited 2010-03-16 00:38
    pullmoll said...
    So $10 - $fffffff8 would be executed as $10 + $00000007 + 1 = $18 and no carry or borrow is involved here.
    That's the way a PIC handles a carry on subtract, but not the Prop. The Prop's carry on subtract is an unsigned borrow. So, in your example, there would be a carry when wc is specified.

    -Phil
  • Peter JakackiPeter Jakacki Posts: 10,193
    edited 2010-03-16 00:49
    It looks like you are only running with the basic 16 byte buffers, I always run much higher, even 512 bytes for rx and tx. Of course you have to modify FDX for anything above 256 bytes. The wrap-around mask should be defined as a constant and not as it is now $0f, it is just as easy to say bufsz-1 so for a 512 byte buffer that becomes the magic $1FF mask. You didn't say (I think) what was receiving the characters so that they should be dropping them, are you saying it's a Prop?

    I also run my serial coms at 115.2K constantly but there are irregularities with the timing that can cause problems at higher speeds that I have observed and this is also due to the jmpret trick of handling rx and tx in one cog. Late last year I was threatening to release a universal serial coms object (UNICOM) but I have been a bit slack, so kick me. http://forums.parallax.com/showthread.php?p=867266

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    *Peter*
  • localrogerlocalroger Posts: 3,452
    edited 2010-03-16 01:24
    16 characters is really a very small buffer, and I've had to hack fdserial to increase it for just about every project I've used it on. It's really best to have enough buffer to contain at least one entire message of whatever maximum length you will ever expect to receive without acknowledgement; this goes doubly with high baud rates such as anything over 9600. I've been doing serial comms for over 20 years and there is absolutely no doubt in my mind that this is a buffer overrun. The easy and reliable solution to that is more buffer.
  • Cluso99Cluso99 Posts: 18,069
    edited 2010-03-16 05:14
    pullmoll: I posted FDX_rr004 on OBEX. It has the buffer length decalred as a constant at the top of the code. You can vary in powers of 2 up to 512 bytes.

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    Links to other interesting threads:

    · Home of the MultiBladeProps: TriBlade,·RamBlade,·SixBlade, website
    · Single Board Computer:·3 Propeller ICs·and a·TriBladeProp board (ZiCog Z80 Emulator)
    · Prop Tools under Development or Completed (Index)
    · Emulators: CPUs Z80 etc; Micros Altair etc;· Terminals·VT100 etc; (Index) ZiCog (Z80) , MoCog (6809)·
    · Prop OS: SphinxOS·, PropDos , PropCmd··· Search the Propeller forums·(uses advanced Google search)
    My cruising website is: ·www.bluemagic.biz·· MultiBlade Props: www.cluso.bluemagic.biz
  • pullmollpullmoll Posts: 817
    edited 2010-03-16 12:40
    Cluso99 said...
    pullmoll: I posted FDX_rr004 on OBEX. It has the buffer length decalred as a constant at the top of the code. You can vary in powers of 2 up to 512 bytes.

    After some searching I found it. Unfortunately the problem persists, so it's most probably on my end of things. I tried with a 256 byte buffer.

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    He died at the console of hunger and thirst.
    Next day he was buried. Face down, nine edge first.
  • Zap-oZap-o Posts: 452
    edited 2010-03-16 13:09
    Cluso99

    I tried your object and it wont run with any thing higher than 256. I get an error when compiled at 512.
  • Cluso99Cluso99 Posts: 18,069
    edited 2010-03-16 13:26
    Zap-o: Thinking about it, there would be no way to detect overflow on 512 since we are really using 9 bits. So guess 256 is the limit. Sorry. I need to correct the OBEX description :-(

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    Links to other interesting threads:

    · Home of the MultiBladeProps: TriBlade,·RamBlade,·SixBlade, website
    · Single Board Computer:·3 Propeller ICs·and a·TriBladeProp board (ZiCog Z80 Emulator)
    · Prop Tools under Development or Completed (Index)
    · Emulators: CPUs Z80 etc; Micros Altair etc;· Terminals·VT100 etc; (Index) ZiCog (Z80) , MoCog (6809)·
    · Prop OS: SphinxOS·, PropDos , PropCmd··· Search the Propeller forums·(uses advanced Google search)
    My cruising website is: ·www.bluemagic.biz·· MultiBlade Props: www.cluso.bluemagic.biz
  • Zap-oZap-o Posts: 452
    edited 2010-03-16 14:00
    No worries, Just wanted to let you know.
  • Dave HeinDave Hein Posts: 6,347
    edited 2010-03-16 15:46
    pullmoll,

    The size of the transmit buffer is irrelevant for your test.· Once you fill up the buffer the back-pressure should cause you to run at the transmit rate.· Since your test is sending 64K of data it will quickly back up even if you used an 8K buffer.· The main question is whether your PASM routine is working correctly.· You could modify your PASM routine to generate an incrementing pattern of bytes, and then read it back to verify if it is correct.· I think the following Spin·method would work to check the stream.

    PUB CheckStream | errorcount, value, expected
    · errorcount := 0
    ··value := serial.rx
    · repeat 65535
    ··· expected := (value + 1) & 255
    ··· value := serial.rx
    ··· if (value <> expected)
    ···· errorcount++
    · return errorcount

    errorcount should return with a value of 0 if everything is OK.· It would really be a lot easier for us to help you if you posted all your code.· Otherwise, we're just guessing.

    Dave
  • pullmollpullmoll Posts: 817
    edited 2010-03-16 16:21
    Dave Hein said...
    It would really be a lot easier for us to help you if you posted all your code. Otherwise, we're just guessing.



    Dave

    I know what you intend, but right now I have just 1 Propeller to test with. The other end is a PC running Linux in my case.
    All my code is in the first entry in the thread Proposed Z80 DRC CPU core. The serial i/o functions are in io.spin. A modified version of FullDuplexSerial 1.1 is included. It exports the address of rx_head to allow interfacing from PASM.

    Juergen

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    He died at the console of hunger and thirst.
    Next day he was buried. Face down, nine edge first.

    Post Edited (pullmoll) : 3/16/2010 4:45:01 PM GMT
  • Dave HeinDave Hein Posts: 6,347
    edited 2010-03-16 20:21
    I looked at your code from the other thread, and I don't see any obvious problems.· There are two routines that I could see that write out to the serial port -- conout_chr and wr_port_alu.· They both set up io_port, io_data and io_command, and then wait for io_command to be cleared.· I assume you used one of those routines for your test.

    You don't need two Props to run the test I suggested.· You would just jumper the serial tx pin to the rx pin.

    Dave
Sign In or Register to comment.