[Flashforth-devel] UART delay for TeraTerm, CoolTerm
Brought to you by:
oh2aun
From: Mike M. <mi...@mo...> - 2015-05-19 19:59:07
|
I have been casually following the thread about TeraTerm. I use TeraTerm on Windows, CoolTerm on OSX. I have been using hardware handshake, with NO delay. I use a USB-to-serial adapter using the FTDI chipset, which seems to get the handshake right. I has been a couple of years since I wrote these, so I hope I am including all of the changes. To do this, I have modified the UART driver. I use UART #2, FC_TYPE=2 I also have FC_TYPE=0 defined using the PIC's handshake control, but that does not work very well. I am using FF 4.8 on the PIC24FJ256GB110, so I map I/O pins: <snip> in config file: ;;; UART2 configuration ;.equ BAUDRATE2, 38400 ; Serial baudrate UART2, comment if not used .equ BAUDRATE2, 115200 ; Serial baudrate UART2, comment if not used .equ FC2_TYPE, 2 ; ; 0 = UART CTS/RTS, 1 = XON/XOFF, 2=(CTS)/RTS software .equ AUTOBAUD2, 0 ; 0 = to use fixed baudrate ; 1 = Autobaud, First char after reset must be 'U' (0x55) ;;; UART2 Peripheral pin mapping .ifdecl RPINR19 .equ U2TXPIN, 17 ; RP17 pin 50 ;.equ U2RXPIN, 10 ; RP10 PIN 49 .if FC2_TYPE == 0 ; UART controls RTS, CTS .equ RPINR19VAL, 0x200a ; msb: U2CTS RP32, lsb: U2RXPIN RP10 .equ U2RTSPIN, 31 ; RP31 (RF13) pin 39 output .else ; we control RTS, CTS .equ RPINR19VAL, 0xff0a ; msb: (U2CTS RP32), lsb: U2RXPIN RP10 ; we are controlling RTS, CTS .equ U2RTSPORT, LATF .equ U2RTSTRIS, TRISF .equ U2RTSPIN, 13 ;RF13 (RF31) pin 39 output .equ U2CTSPIN, 12 ;RF12 (RPI32) pin 40 input (not implemented) .endif .endif <snip> in FF.s: .ifdecl BAUDRATE2 ; UART2 .ifdecl _U2RXREG __U2RXInterrupt: push.s .ifdef CMAIN lnk #ISTKSIZ .endif ; CMAIN .ifdef PEEPROM push TBLPAG .endif inc2 W14, W14 __U2RXInterrupt0: bclr IFS1, #U2RXIF bset iflags, #istream ; Indicate UART activity. mlit handle(U2RXQUEUE_DATA)+PFLASH rcall CQUEUE_TOQ ; Space available ? false = queue is full cp0 [W14--] bra z, U2RX_ERR1 bclr U2STA, #OERR mov U2RXREG, W0 ; get chr .if (CTRL_O_WARM_RESET == 1); Console only cp W0, #15 bra z, RESET_FF_1 .endif .if FC2_TYPE == 1 btsc iflags, #fFC2 bra U2_SKIP_FC_1 cp W0, #XOFF bra z, __U2RXInterrupt3 .endif U2_SKIP_FC_1: mov W0, [++W14] mlit handle(U2RXQUEUE_DATA)+PFLASH rcall CQUEUE_TO ; Put to character queue btsc iflags, #fFC2 bra U2_SKIP_FC_2 .if FC2_TYPE == 1 mov rbuf_wr2, W0 and W0, #0xf, W0 bra nz, __U2RXInterrupt3 __U2RXInterrupt2: btsc U2STA, #UTXBF ; buffer full? bra __U2RXInterrupt2 mov #XOFF, W0 mov W0, U2TXREG ; send chr bset iflags, #ixoff2 .else .if FC2_TYPE == 2 mov #RX2_OFF_FILL, W0 cp rbuf_lv2 bra n, __U2RXInterrupt3 bset U2RTSPORT, #U2RTSPIN ; RTS low .endif .endif U2_SKIP_FC_2: __U2RXInterrupt3: btsc U2STA, #URXDA ; bit #0, data available bra __U2RXInterrupt0 __U2RXTXIRQ_END: bra __U1RXTXIRQ_END U2RX_ERR1: btss U2STA, #TRMT bra U2RX_ERR1 mov U2RXREG, W0 mov #'|', W0 mov W0, U2TXREG ; send bra __U2RXInterrupt3 __U2TXInterrupt: push.s .ifdef CMAIN lnk #ISTKSIZ .endif ; CMAIN .ifdef PEEPROM push TBLPAG .endif add W14, #2, W14 bclr IFS1, #U2TXIF ; clear interrupt flag __U2TXInterrupt0: btsc U2STA, #UTXBF ; uart buffer full? bra __U2TXInterrupt3 ; buffer full mlit handle(U2TXQUEUE_DATA)+PFLASH ; yes buffer ready rcall CQUEUE_FROMQ ; Character available ? false = no cp0 [W14--] bra z, __U2TXInterrupt3 ; queue empty mlit handle(U2TXQUEUE_DATA)+PFLASH rcall CQUEUE_FROM ; Get from character queue mov [W14--], W0 mov W0, U2TXREG ; Send chr __U2TXInterrupt3: bra __U1RXTXIRQ_END .endif .endif <snip> wait_silence: rcall LOCKED .if FC2_TYPE == 1 btsc U2STA, #UTXBF ; buffer full? bra wait_silence mov #XOFF, W2 mov W2, U2TXREG ; send chr bset iflags, #ixoff2 .else .if FC2_TYPE == 2 bset U2RTSPORT, #U2RTSPIN ; RTS low .endif .endif .if FC2_TYPE == 1 wbtil: bclr iflags, #istream ; The delay here should be 10 character times long ; times = Fcy/baud*40 ; MJM mov #(FCY/BAUDRATE1*40), W2 ; This loop takes about 5 milliseconds @ 27 Mips mov #13333, W2 ; This loop takes about 5 milliseconds @ 27 Mips wbtil2: btsc iflags, #istream ; Check for UART activity. bra wbtil ; dec W2, W2 ; bra nz, wbtil2 ; .endif return <snip> ;;; Initialise UART2 .ifdecl BAUDRATE2 .ifdecl _U2RXREG .if FC2_TYPE == 2 ; remap pins override tris bclr U2RTSTRIS, #U2RTSPIN bclr U2RTSPORT, #U2RTSPIN ; RTS high .endif .ifdecl RPINR19 mov #RPINR19VAL, W0 ; lsb is RX mov W0, RPINR19 ; msb: (U2CTS), lsb: U2RX mov #0x0005, W0 ; U2TX #5 mov.b WREG, RPOR0+U2TXPIN .if FC2_TYPE == 0 ; UART RTS control MJM mov #0x0006, W0 ; U2RTS #6 mov.b WREG, RPOR0+U2RTSPIN ; enable hdwe CTS/RTS bset U2MODE, #UEN1 ; enable hdwe CTS/RTS MJM .endif .endif ;// Assign U2TX to pin RP17 (pin #50, RF5) MJM ; RPOR15bits.RP30R = 5; // 5 is code for U2TX ;// Assign U2RX to pin RP10 (pin #49, RF4) ; RPINR19bits.U2RXR = 10; bclr PMD1, #U2MD ; enable UART2 clk bset U2MODE, #UARTEN ; enable UART2 .ifdecl BRGH bset U2MODE, #BRGH ; fast baud rates .endif mov #BAUD_DIV2, W0 mov W0, U2BRG bset U2STA, #UTXEN .ifdecl AUTOBAUD2 .if (AUTOBAUD2 == 1) bset U2MODE, #ABAUD WARM_ABAUD2: btsc U2MODE, #ABAUD bra WARM_ABAUD2 bclr IFS1, #U2RXIF .endif .endif bset IEC1, #U2RXIE ; enable U2 interrupts bset IEC1, #U2TXIE .endif .endif <snip> .pword paddr(RX1Q_L)+PFLASH .ifdecl BAUDRATE2 ; UART2 .ifdecl _U2RXREG U2TXQUEUE_L: ; ( -- queue-addr ) Leave the address of the queue for UART2 .byte NFA|INLINE|5 .ascii "u2txq" .align 2 U2TXQUEUE: mlit handle(U2TXQUEUE_DATA)+PFLASH return U2TXQUEUE_DATA: .word txqueue2 .word TX2_BUF_SIZE-1 .pword paddr(U2TXQUEUE_L)+PFLASH U2RXQUEUE_L: .byte NFA|INLINE|5 .ascii "u2rxq" .align 2 U2RXQUEUE: mlit handle(U2RXQUEUE_DATA)+PFLASH return U2RXQUEUE_DATA: .word rxqueue2 .word RX2_BUF_SIZE-1 .pword paddr(U2RXQUEUE_L)+PFLASH TX2_L: ; ( c -- ) Put a character to U2TXQ .byte NFA|3 .ascii "tx2" .align 2 TX2: rcall PAUSE rcall IDLE_ rcall TX2Q cp0 [W14--] bra z, TX2 rcall BUSY_ rcall U2TXQUEUE rcall CQUEUE_TO ; Put to character queue rcall U2TXQUEUE rcall CQUEUE_FROMQ ; Character available ? false = no mov [W14--], W0 sub #2, W0 ; If there are less than 2 chars bra nn, TX2_2 ; in TX queue, bset IFS1, #U2TXIF ; clr interrupt flag TX2_2: return .pword paddr(TX2_L)+PFLASH TX2Q_L: ; ( -- flag ) Leave false flag if U2TXQ is full. .byte NFA|4 .ascii "tx2?" .align 2 TX2Q: mlit handle(U2TXQUEUE_DATA)+PFLASH goto CQUEUE_TOQ ; Space available ? false = queue is full .pword paddr(TX2Q_L)+PFLASH RX2_L: .byte NFA|3 .ascii "rx2" .align 2 RX2: rcall PAUSE rcall RX2Q cp0 [W14--] .if FC2_TYPE == 2 ; MJM bra nz, RX2_1 ; MJM bclr U2RTSPORT, #U2RTSPIN ; RTS high bra RX2 RX2_1: .else bra z, RX2 ; MJM .endif mlit handle(U2RXQUEUE_DATA)+PFLASH rcall CQUEUE_FROM ; Get from character queue return .pword paddr(RX2_L)+PFLASH RX2Q_L: .byte NFA|4 .ascii "rx2?" .align 2 RX2Q: rcall BUSY_ mlit handle(U2RXQUEUE_DATA)+PFLASH rcall CQUEUE_FROMQ ; Character available ? false = no cp0 [W14] bra nz, RX2Q1 rcall IDLE_ btss iflags, #fFC2 bra RX2Q1 .if FC2_TYPE == 1 btst iflags, #ixoff2 bra z, RX2Q1 bclr iflags, #ixoff2 mlit XON rcall TX2 .else .if FC2_TYPE == 2 cp0 rbuf_lv2 ; buffer empty? bra nz, RX2Q1 bclr U2RTSPORT, #U2RTSPIN ; RTS high .else ; FC2_TYPE == 0 UART handshake cp0 rbuf_lv2 ; buffer empty? bra nz, RX2Q1 mov U2RXREG, W0 ; get chr, dump .endif .endif RX2Q1: return .pword paddr(RX2Q_L)+PFLASH .endif .endif <snip> .pword paddr(RX1Q_L)+PFLASH .ifdecl BAUDRATE2 ; UART2 .ifdecl _U2RXREG U2TXQUEUE_L: ; ( -- queue-addr ) Leave the address of the queue for UART2 .byte NFA|INLINE|5 .ascii "u2txq" .align 2 U2TXQUEUE: mlit handle(U2TXQUEUE_DATA)+PFLASH return U2TXQUEUE_DATA: .word txqueue2 .word TX2_BUF_SIZE-1 .pword paddr(U2TXQUEUE_L)+PFLASH U2RXQUEUE_L: .byte NFA|INLINE|5 .ascii "u2rxq" .align 2 U2RXQUEUE: mlit handle(U2RXQUEUE_DATA)+PFLASH return U2RXQUEUE_DATA: .word rxqueue2 .word RX2_BUF_SIZE-1 .pword paddr(U2RXQUEUE_L)+PFLASH TX2_L: ; ( c -- ) Put a character to U2TXQ .byte NFA|3 .ascii "tx2" .align 2 TX2: rcall PAUSE rcall IDLE_ rcall TX2Q cp0 [W14--] bra z, TX2 rcall BUSY_ rcall U2TXQUEUE rcall CQUEUE_TO ; Put to character queue rcall U2TXQUEUE rcall CQUEUE_FROMQ ; Character available ? false = no mov [W14--], W0 sub #2, W0 ; If there are less than 2 chars bra nn, TX2_2 ; in TX queue, bset IFS1, #U2TXIF ; clr interrupt flag TX2_2: return .pword paddr(TX2_L)+PFLASH TX2Q_L: ; ( -- flag ) Leave false flag if U2TXQ is full. .byte NFA|4 .ascii "tx2?" .align 2 TX2Q: mlit handle(U2TXQUEUE_DATA)+PFLASH goto CQUEUE_TOQ ; Space available ? false = queue is full .pword paddr(TX2Q_L)+PFLASH RX2_L: .byte NFA|3 .ascii "rx2" .align 2 RX2: rcall PAUSE rcall RX2Q cp0 [W14--] .if FC2_TYPE == 2 ; MJM bra nz, RX2_1 ; MJM bclr U2RTSPORT, #U2RTSPIN ; RTS high bra RX2 RX2_1: .else bra z, RX2 ; MJM .endif mlit handle(U2RXQUEUE_DATA)+PFLASH rcall CQUEUE_FROM ; Get from character queue return .pword paddr(RX2_L)+PFLASH RX2Q_L: .byte NFA|4 .ascii "rx2?" .align 2 RX2Q: rcall BUSY_ mlit handle(U2RXQUEUE_DATA)+PFLASH rcall CQUEUE_FROMQ ; Character available ? false = no cp0 [W14] bra nz, RX2Q1 rcall IDLE_ btss iflags, #fFC2 bra RX2Q1 .if FC2_TYPE == 1 btst iflags, #ixoff2 bra z, RX2Q1 bclr iflags, #ixoff2 mlit XON rcall TX2 .else .if FC2_TYPE == 2 cp0 rbuf_lv2 ; buffer empty? bra nz, RX2Q1 bclr U2RTSPORT, #U2RTSPIN ; RTS high .else ; FC2_TYPE == 0 UART handshake cp0 rbuf_lv2 ; buffer empty? bra nz, RX2Q1 mov U2RXREG, W0 ; get chr, dump .endif .endif RX2Q1: return <snip> QUIT1: rcall check_sp rcall CR rcall TIB mov [W14++], [W14] ; dup rcall TIBSIZE mlit HOLD_SIZE ; Reserve for hold buffer rcall MINUS rcall ACCEPT .if WRITE_METHOD == 2 .if FC2_TYPE == 1 mov #XOFF, W2 mov W2, U2TXREG ; send chr bset iflags, #ixoff2 .endif .endif rcall SPACE_ rcall INTERPRET rcall STATE cp0 [W14--] bra nz, QUIT1 .if WRITE_METHOD == 2 btss iflags1, #edirty ; If dirty then write after timeout in PAUSE .endif rcall DP_TO_EEPROM rcall XSQUOTE .byte 3 .ascii "ok " .align 2 rcall TYPE rcall PROMPT bra QUIT0 return Mike Miller WB6TMH Moon Valley Circuits Glen Ellen, CA 95442 |