Shop OBEX P1 Docs P2 Docs Learn Events
high speed UART transmitting — Parallax Forums

high speed UART transmitting

Keith MKeith M Posts: 102
edited 2007-02-05 21:30 in General Discussion
I have an application that requires a high data rate from the SX to a PC. I'm currently using the USB2SER, which is very nice. I'm using SX/B's SEROUT commands which work fine up 230.4kbps. I had originally implemented my own bit-banging UART at 2mbps in asm, and it worked pretty good, but not perfect. While I never fully debugged the routines, I think my problems were related to varying execution length based on using multiple cycle instructions that varied with the data content. The time between bits were simply a bunch of NOPs. While I didn't check the amount of variation, it was obviously enough to cause bit errors, at a rate of perhaps 1/3000.

I have very little experience with UARTs, but I do understand how they work, for the most part, what they do, and so on.

I'm running the SX28 at 50mhz. I'm confident the SX is fast enough given the required slow-down between bits. 2mbps bit period is 500ns. 25 single cycle instructions between bits.

Is it possible to make a high-speed reliable non-ISR based UART?

When it comes time to transfer the data, the SX's sole job is to transfer the data from SRAM. I will have interrupts disabled during transfer. If only ISR-based solutions make sense, I don't need any time in my main loop while transmitting the byte. So an ISR that consumes all the SX's time(for the duration of the byte) is fine with me.

Most of the pre-packaged UART VPs and examples I've seen have much lower baud rate limits.

Note that I'm only worried about transmitting here, my receive code seems to work well enough, and there is VERY little data coming the other direction.

Thanks.

Keith

P.S. while my target data rate is 2mbps, I'd take 1mbps in a pinch. [noparse];)[/noparse]

Comments

  • BeanBean Posts: 8,129
    edited 2007-02-04 23:32
    2Mbps is quite fast, I'm thinking that maybe your errors are caused by the electrical connection.
    If the rise/fall time is too high, that could cause errors.
    Do you have a scope to look at the signal ?
    If you post your 2Mbps code we can have a look at it.

    Bean.

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    Cheap used 4-digit LED display with driver IC·www.hc4led.com

    Low power SD Data Logger www.sddatalogger.com
    SX-Video Display Modules www.sxvm.com
    Stuff I'm selling on ebay http://search.ebay.com/_W0QQsassZhittconsultingQQhtZ-1

    "USA Today has come out with a new survey - apparently, three out of every four people make up 75% of the population." - David Letterman
  • Keith MKeith M Posts: 102
    edited 2007-02-05 08:43
    I rewrote my UART code tonight because I was unhappy with the older version. I think I've got better results, but a little peer review can't hurt. (be gentle)

    A couple things

    1> I can't help but feel that using JMP $+1 and NOP's are simply ugly. If anyone has a better(cleaner, more simple, easy to read) way of doing this, I'd be happy to listen.

    2> My initial post refers to "multicycle instructions taking different execution lengths" -- I'm specifically talking about the MOVB instruction, which either clears the bit on 2nd of 4 instructions, or sets the bit on the 4th or 4 instructions. If I'm reading this right. This produces a 2-cycle difference between a '0' and a '1'. Note this is the way Parallax's UART code(uart_vp.src) does it (although they use the machine coded "expanded" version instead of using the MOVB mnemonic)

    3> This is serial, but its not 232, so nothing here is inverted.

    4> LA image attached shows I'm achieving a 99% baud rate match. 4950ns for 10 bits @ 500ns each, so I'm 50ns off across 5000ns.

    5> This is hardcoded to 2mbps, 500ns per bit as I mentioned in the OP.

    6> This actually works. To what extent, or how long error free, etc -- I have not tested.

    
            MOV NSB, #8
    
        CLRB TXDATA        'transmit start bit
    
        JMP $+1            '100ns delay
        NOP
        NOP
    
    nextbit:
    
        JMP $+1            '280ns delay
        JMP $+1
        JMP $+1
        JMP $+1
        NOP
        NOP
    
        CLC
        RR datatosend        'right rotate and put lsb into C
        MOVB TXDATA, C        'put C on the port
        DEC NSB            'decrement bit counter
        JNZ nextbit        'if jnz>0 then nextbit
    
        JMP $+1            '380ns delay
        JMP $+1
        JMP $+1
        JMP $+1
        JMP $+1
        JMP $+1
        NOP
    
        SETB TXDATA        'transmit stop bit
        JMP $+1            '500ns delay        
        JMP $+1
        JMP $+1
        JMP $+1
        JMP $+1
        JMP $+1
        JMP $+1
        JMP $+1
        NOP
    
    



    Questions or comments welcomed.

    Thanks.

    Keith

    P.S. Have I mentioned I love my new LogicPort 34-channel 500mhz LA?
    730 x 177 - 93K
  • BeanBean Posts: 8,129
    edited 2007-02-05 12:28
    The cycle count looks okay to me.

    1) Yes, they are. But unless you use another variable to make DJNZ loops (plus you will still need to pad with NOPS) it about the best anyone can do (NOTE that IREAD takes 4 cycles, but destroys W and M).

    2) You are correct here too. Two cycle in 25 (8%) is a bit much, but a good receiver (that samples in the MIDDLE of the bit time) should not have any problems with it. But you could try this code instead:

        MOV NSB, #8    ' 2
        CLRB TXDATA    ' 1   transmit start bit
        JMP $+1        ' 3   160ns delay
        JMP $+1        ' 3
        NOP            ' 1
        NOP            ' 1
    
    Nextbit:
        JMP $+1        ' 3   200ns delay
        JMP $+1        ' 3
        JMP $+1        ' 3
        NOP            ' 1
        CLC            ' 1
        RR datatosend  ' 1   right rotate and put lsb into C
    
        JB C, $+6      ' 2/4 
        NOP            ' 1   
        NOP            ' 1   
        CLRB TXDATA    ' 1   This section always takes 8 cycles
        JMP $+3        ' 3   
        SETB TXDATA    ' 1   
        JMP $+1        ' 3
        
        DEC NSB        ' 1   decrement bit counter
        JNZ nextbit    ' 2/4 if jnz>0 then nextbit
    
        JMP $+1        ' 3   300ns delay
        JMP $+1        ' 3
        JMP $+1        ' 3
        JMP $+1        ' 3
        JMP $+1        ' 3
        JMP $+1        ' 3
    
        SETB TXDATA    ' 1   transmit stop bit
    
        JMP $+1        ' 3   500ns delay        
        JMP $+1        ' 3
        JMP $+1        ' 3
        JMP $+1        ' 3
        JMP $+1        ' 3
        JMP $+1        ' 3
        JMP $+1        ' 3
        JMP $+1        ' 3
        NOP            ' 1
    


    Bean.


    ·

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    Cheap used 4-digit LED display with driver IC·www.hc4led.com

    Low power SD Data Logger www.sddatalogger.com
    SX-Video Display Modules www.sxvm.com
    Stuff I'm selling on ebay http://search.ebay.com/_W0QQsassZhittconsultingQQhtZ-1

    "USA Today has come out with a new survey - apparently, three out of every four people make up 75% of the population." - David Letterman

    Post Edited (Bean (Hitt Consulting)) : 2/5/2007 12:58:10 PM GMT
  • Keith MKeith M Posts: 102
    edited 2007-02-05 21:30
    Thanks Bean for taking a look at this for me, and for the follow up code.

    I also rewrote my receive UART, and was looking at the data coming out of the USB2SER, and it, too, isn't 100% perfect on all bits all the time.

    I've probably run about 20 megabytes of data through my UART code, and it seems reliable enough. I haven't seen a single bit error across the traffic, although there were multiple transfers, etc. While my testing wasn't very scientific, it's working well in the final application. I have a checksum on the transfer, and in the event of an error, it automatically re-transmits the "floppy track", in my case. So even if there was a hiccup, it would be caught.

    I'm pretty happy to be running 2mbps into the USB2SER from the SX. I think this speaks volumes both for the capability(speed) of the SX, and for the USB2SER. I think it's GREAT that I have to slow down the SX, just to get to 2mbps. [noparse]:)[/noparse]

    My application, an external amiga floppy drive controller, that I'm sure you've seen me post numerous times about, really requires high speeds because I'm handling 160 tracks total. This is a 160-multiplier on any operation I do. So if the transfer takes only one second(reasonable in most applications), this adds 160 seconds to the total read time. This added time is completely unacceptable. So the ability to do fast transfers is important.

    I have PC software that transmits a "READ track command" to my SX, which turns on the motor, reads the data via an ISR and stores it into FRAM. Then I send a "DUMP command", which causes the SX to transfer the contents of the FRAM to the PC via USB. Then I send other commands like "STEP the drive", or "Upper track", or "Lower track" and so on.

    After I implemented my UART, I went from 230.4k - 2mbps, and my transfer times went from 3:06 per disk to 1:16 per disk.

    TTYL,

    Keith
Sign In or Register to comment.