Back to home page

DOS ain't dead

Forum index page

Log in | Register

Back to the board
Thread view  Mix view  Order
maui(R)

11.11.2013, 11:14
 

uart interrupt tx rx in Dos32 bit open watcom (Developers)

Hi,
I'm trying to develop an application, that use interrupt for serial port, to manage the receive and transmit event in Freedos 1.0 and dos4gw.
At the moment, with the example of open watcom bimodal found in goodies of OW, the event of rx is correctly handled, and now I would like to manage the tx event.
This example is a mix between c and asm.
I'm trying to adapt the code to intercept also transmission interrupt, but the routine send only few characters.
I have enabled the bit of tx interrupt, and the event is generated when I try to transmit a byte in my main, but here it comes the problem.
I'd like to compile a buffer with my data to be sent, and let the transmit interrupt handle the sending, so the pc, is free to do other stuff in the main code. When I try to send the first byte in the main, I receive the interrupt call, but when I send another byte there(in the interrupt), I don't receive the next interrupt call for the next byte to transmit. Probably I'm not managing the register in the right way.

Anybody has an example of a serial transmission, using the tx interrupt of the uart?

Thanks in advance,

maui

RayeR(R)

Homepage

CZ,
11.11.2013, 19:34

@ maui

uart interrupt tx rx in Dos32 bit open watcom

Doesn't it need to clear some interrupt flag in PIC (send something to PIC IO port but I don't remember). I was trying only Rx ISR in DJGPP with Tx routine polled so I can't help more.

---
DOS gives me freedom to unlimited HW access.

RayeR(R)

Homepage

CZ,
12.11.2013, 01:50

@ RayeR

uart interrupt tx rx in Dos32 bit open watcom

> Doesn't it need to clear some interrupt flag in PIC (send something to PIC
> IO port but I don't remember). I was trying only Rx ISR in DJGPP with Tx
> routine polled so I can't help more.

EDIT I meant
//***************** PIC (Programmable Interrupt Controller) registers *******
#define UART_PIC_IMR 0x21 // PIC Interrupt Mask Register
#define UART_PIC_ITR 0x20 // PIC Interrupt Termination Register

outportb(UART_PIC_ITR, 0x20); // ISR end signal for PIC

---
DOS gives me freedom to unlimited HW access.

tom(R)

Homepage

Germany,
12.11.2013, 12:24
(edited by tom, 12.11.2013, 12:36)

@ maui

uart interrupt tx rx in Dos32 bit open watcom

I did that something like 20 years ago.
I remember that I needed several iterations until it worked reliable, it's MUCH easier to only use *receive* interrupts.
that said,

> When I try to send the first byte in the main, I receive the
> interrupt call, but when I send another byte there(in the interrupt), I
> don't receive the next interrupt call for the next byte to transmit.

most likely you don't read the status register (often enough)

pseudocode


void interrupt interrupt_service_routine()
  {

  for (;;){
    status = input(status_port);

    if (status & (tx_ready | rx_ready | overflow) == 0)
        break;

    if (status & tx_ready)
      if (more_characters_to_send)
        outport(dataport, next_character);

     if (status & rx_ready)
        buffer[next++] = inport(dataport);

     if (status & rx_overflow)
        transmission_errors++;
     }

    outport(0x20, EOI);   // only NOW acknowledge interrupt

   }


note: this was it AFAIR; no guarantees of any kind;)

RayeR(R)

Homepage

CZ,
12.11.2013, 12:30

@ tom

uart interrupt tx rx in Dos32 bit open watcom

> BTW: is it possible to write indented text in this forum ?

Try to use [ code ] [ /code ] tag (without spaces).

---
DOS gives me freedom to unlimited HW access.

bretjohn(R)

Homepage E-mail

Rio Rancho, NM,
12.11.2013, 16:55

@ tom

uart interrupt tx rx in Dos32 bit open watcom

I did something like that a LONG time ago, too (except in 16-bit DOS, not DPMI). I looked for the code, but can't find it any more.

I remember using the source code for an old PC Magazine utility called PCREMOTE as the starting point for that particular part of my program. I also used the source code for PCREMOTE as the starting point to set up circular buffers to store the transmit and receive data. PCREMOTE uses the IRQ for both transmit and receive, which is what you're trying to do. I personally agree that's the _right_ way to do it, even though it's a little more difficult than transmit polling.

I think uploading the PCREMOTE source code might be forbidden here because of copyright issues, but you can still find the files on the Internet if you look. PCREMOTE is in V9N01 of the PC Magazine archives.

Since you haven't shown any of your code, one thing I will say that you absolutely need to do is to make sure in the Interrupt Enable Register you set the Transmitter Holding Register interrupt bit.

maui(R)

12.11.2013, 19:23

@ bretjohn

uart interrupt tx rx in Dos32 bit open watcom

> I did something like that a LONG time ago, too (except in 16-bit DOS, not
> DPMI). I looked for the code, but can't find it any more.
>
> I remember using the source code for an old PC Magazine utility called
> PCREMOTE as the starting point for that particular part of my program. I
> also used the source code for PCREMOTE as the starting point to set up
> circular buffers to store the transmit and receive data. PCREMOTE uses the
> IRQ for both transmit and receive, which is what you're trying to do. I
> personally agree that's the _right_ way to do it, even though it's a little
> more difficult than transmit polling.
>
> I think uploading the PCREMOTE source code might be forbidden here because
> of copyright issues, but you can still find the files on the Internet if
> you look. PCREMOTE is in V9N01 of the PC Magazine archives.
>
> Since you haven't shown any of your code, one thing I will say that you
> absolutely need to do is to make sure in the Interrupt Enable Register you
> set the Transmitter Holding Register interrupt bit.

Hi,

thanks a lot for the info about the example, I manage to find it, and at the moment, merging it with my code, the uart is sending up to 16 bytes in interrupt, but after the 16th, no more data is transmitted, probably it is depending on enabling fifo on the FIFO Control Register.
I'll try to use the example, I'll post as soon as I have any news.

Thanks again.

maui

bretjohn(R)

Homepage E-mail

Rio Rancho, NM,
12.11.2013, 21:12

@ maui

uart interrupt tx rx in Dos32 bit open watcom

There are some more details on how the UART works, and even some info on some of the FIFO hardware, in RBIL. The info is listed under I/O Port 3F8-3FF.

tom(R)

Homepage

Germany,
13.11.2013, 11:22

@ maui

uart interrupt tx rx in Dos32 bit open watcom

and at
> the moment, merging it with my code, the uart is sending up to 16 bytes in
> interrupt, but after the 16th, no more data is transmitted, probably it is
> depending on enabling fifo on the FIFO Control Register.
> I'll try to use the example, I'll post as soon as I have any news.

post your code, and we can try to help.
if keep it to yourself, we can't.

see also http://www.ti.com/general/docs/lit/getliterature.tsp?literatureNumber=snls378b

maui(R)

13.11.2013, 15:49

@ tom

uart interrupt tx rx in Dos32 bit open watcom

> and at
> > the moment, merging it with my code, the uart is sending up to 16 bytes
> in
> > interrupt, but after the 16th, no more data is transmitted, probably it
> is
> > depending on enabling fifo on the FIFO Control Register.
> > I'll try to use the example, I'll post as soon as I have any news.
>
> post your code, and we can try to help.
> if keep it to yourself, we can't.
>
> see also
> http://www.ti.com/general/docs/lit/getliterature.tsp?literatureNumber=snls378b

Hi,

I'm waiting to post the code, cos it is not so clean to read, with the cut and paste it is not so easy to understand, I'll do soon a clear of the useless part, and then post it.

I enabled the fifo, so I can read up to 16 before the uart goes in failure, and up to store 16byte to be send.

At the moment, I managed to send more then 16 byte, when I get the interrupt request, I send max 16 bytes, if there are more bytes, I send the eoi and wait for the next call, invoked from my last tx of the 16th byte.

Thank for the support, I'll reply soon with the code.

maui.

Oso2k(R)

13.11.2013, 22:26

@ maui

uart interrupt tx rx in Dos32 bit open watcom

Look at mc323exa.zip from David Dunfield to see how this was done with 16-bit code. Specifically, 16550A - 16550A uart FIFO control. DLM (data line monitor), SERMON (multi-serial monitor), and SDT (serial debug terminal) might also be helpful as well. If you're trying to implement a data transfer app, Dunfield has many in mc323exa (see SAMPLE.TXT) and others available at his DOS Utils page. They all depend on his 16-bit Micro C Compiler if you decide to rebuild them from source which is very easy to do and he provides links to everything you need for that on his DOS Utils page.

maui(R)

15.11.2013, 19:43

@ Oso2k

uart interrupt tx rx in Dos32 bit open watcom

> Look at
> mc323exa.zip
> from David Dunfield to see how this was done with 16-bit code.
> Specifically, 16550A - 16550A uart FIFO control.
> DLM (data line
> monitor),
> SERMON
> (multi-serial monitor), and
> SDT (serial
> debug terminal) might also be helpful as well. If you're trying to
> implement a data transfer app, Dunfield has many in mc323exa (see
> SAMPLE.TXT)
> and others available at his
> DOS Utils
> page. They all depend on his 16-bit
> Micro C
> Compiler if you decide to rebuild them from source which is very
> easy to do and he provides links to everything you need for that on his DOS
> Utils page.

Thank for the link, I will get a look on that in these next days.

Here my code, it is a version from bimodal from open watcom goodies example:


.286

_TEXT16 SEGMENT BYTE PUBLIC 'CODE'
                                ASSUME  cs:_TEXT16

                                ;**
                                ;** The real-mode interrupt handler is in a 16-bit code segment
                                ;** so that the assembler will generate the right code.
                                ;**
                                ;** We will copy this code to a 16-bit segment in low memory
                                ;** and install it as a real mode interrupt handler before it
                                ;** gets executed.  (There's no distinction between code and
                                ;** data in real mode.)
                                ;**
                                ;** Since the handler doesn't get executed before it gets copied,
                                ;** putting it in this segment makes the C code simpler.
                                ;**
                                ;** The buffer into which we will store the data being sent
                                ;** to us is also in this segment, for simplicity.  (It's
                                ;** possible to read and write code segments in real mode.)
                                ;** We will lay out this segment using fixed offsets, so that
                                ;** we can omit the data in the executable file.  The symbolic
                                ;** offsets are only used to reference the segment BEFORE
                                ;** it has been copied low.
                                ;**
                                ;** Both the real mode and protected mode handlers will store
                                ;** their data in this same buffer (that is, in the copy in
                                ;** low memory).
                                ;**
                                ;** OFFSET    LENGTH     CONTENTS
                                ;**
                                ;** 0         <128       Real mode interrupt handler
                                ;** 128       4          Next available slot in buffer
                                ;** 132       1024       Data receive buffer
                                ;** 132+1024  1          Overflow indicator
                                ;**

maxbuf  EQU     1024

                                PUBLIC  rmhandler_, _com_port_low
rmhandler_:
                                push    ds
                                push    bx
                                mov     bx, 0B800h
                                mov     ds, bx                          ; DS = 0xB800
                                sub     bx, bx                          ; BX = 0
                                mov     WORD PTR [bx], 0720h            ; Clear 2 character cells
                                mov     WORD PTR [bx+2], 0720h

                                push    cx
                                push    ax
                                mov     cx, 10h
rmdelay:
                                mov     ax, 1
                                mul     cl
                                loop    rmdelay                         ; RM delay loop (flicker makes
                                pop     ax                              ;   screen effects understandable)
                                pop     cx

                                mov     BYTE PTR [bx],'R'               ; Write 'R' to memory map

                                db      0BBh                            ; mov bx,...
_com_port_low   DW      ?                       ;   com port base address
                                push    ax
                                push    dx
retry_int:
                                mov     bx,03E8h     ;base address of com 3
                                lea     dx, [bx+2]   ;pointing to interrupt identification
                                in      al, dx       ;getting the interrupt
                                and                     al, 02h      ;enabling only the tx bit
                                cmp     al, 02h      ;is it on?
                                je                      int_tx_rm    ;yes, go to the tx routine
                                jne             clear_int_rm ;else clear the interrupt
int_tx_rm:
                                ;my total char to send, and the index, are mapped in cs
                                mov     bl,cs:[2048+5];total of the char to send
                                mov     al,cs:[2048+6];index of char sent
                                cmp     al,bl        ;are there any char left?
                                jge                     clear_int_rm ;no, clear the interrupt
                                ;yes send the new char
                                inc             al           ;in the index
                                mov     cs:[2048+6],al;save in memory

                                mov     bx,03E8h                 ;base address of com 3
                                lea     dx,[bx]      ;pointing to the com
                                mov                     al,cs:[2048+6];sending the index +0x40(A)
                                add                     al,40h
                                out     dx,al        ;sending out

                                ;max 16 byte
                                mov                     al,cs:[2048+6];getting the index
                                and                     al,0fh        ;only the 4 lower bit
                                cmp                     al,0fh        ;equal to 15?
                                je      clear_int_rm  ;yes, exit the int
                                jmp     int_tx_rm

;                               lea     dx,[bx+2]     ;pointing to interrupt identification
;                               mov     ax,0          ;clearing ax
;                               in                      al,dx         ;getting the flags
;                               test            al,1
;                               jz      retry_int

clear_int_rm:
                                ;clearing slave
                                mov     dx,0a0h
                                mov     al,020h
                                out     dx,al                           ; Send EOI

                                ;clearing master
                                mov     dx,020h
                                mov     al,dl
                                out     dx,al                           ; Send EOI
;;;;;;;;;;;;;

                                pop     dx
                                pop     ax
                                pop     bx
                                pop     ds
                                iret
                                ASSUME  cs:NOTHING

; These variables only exist in the real mode copy of this segment
; (the one which actually gets executed)
;
;               ORG     128
;next           DD      0
;databuf        DB      maxbuf dup(0)
;overflow       DB      0

_TEXT16 ENDS



I know that it is not the best clearing code, with this the sending of all buffer it is not always processed, becouse sometime, I don't receive back the interrput of the 16th byte sent.
In the init com, i enable the fifo with outp(0x3E8+2,1), and only the interrupt tx in the outp(0x3E8+1,2)

Thanks for your time on this topic.

maui.

Brian_extended(R)

16.11.2013, 01:14
(edited by Brian_extended, 16.11.2013, 01:25)

@ maui

uart interrupt tx rx in Dos32 bit open watcom

> Hi,
> I'm trying to develop an application, that use interrupt for serial port,
> to manage the receive and transmit event in Freedos 1.0 and dos4gw.

>
> Anybody has an example of a serial transmission, using the tx interrupt of
> the uart?
>
> Thanks in advance,
>
> maui

I'm in the middle of converting my TX/RX serial code to Phar Lap/Microway 32-bit code. I'm debugging it still, so will post my 16-bit code that was written "in the day". I seem to recall some Bit needing to be set that was not in the Technical Reference manual and I had to disassemble ST240 to figure out how they did it. I have hand-written corrections to that section of the IBM Tech Ref Manual.

I have a version for C++ 1.52, real mode. New version is at a Clean assemble in 386asm, need to debug it.



Turns out to be too long to load into a thread...

Brian_extended(R)

16.11.2013, 01:15

@ Brian_extended

uart interrupt tx rx in Dos32 bit open watcom

Too long!

Brian_extended(R)

16.11.2013, 01:16

@ Brian_extended

uart interrupt tx rx in Dos32 bit open watcom

Too long to upload...

Brian_extended(R)

16.11.2013, 01:32

@ maui

uart interrupt tx rx in Dos32 bit open watcom

http://www.leicaplace.com/showthread.php?t=324&page=3&p=2755#post2755

I posted the full code in the Leica Place Forum...

I started a DOS rules thread there. I can do that...

If anyone is into Leica and rangefinder cameras, or old lenses, you can check out the "on topic". Turns out many of the members are software engineers.

tom(R)

Homepage

Germany,
16.11.2013, 19:02

@ maui

uart interrupt tx rx in Dos32 bit open watcom

> Thanks for your time on this topic.
after looking a while on it it *looks* ok

however the sender code is missing. therefore a few questions:

is the fifo empty when it stops?
is there some correlation to (index & 0x0f) ?

when transmission stops because no more data to be send,
how do you restart transmission?

is this a PCI bus machine, or some *real* old machine ?

lastly: what purpose has the rmloop ?

Brian_extended(R)

17.11.2013, 04:21

@ tom

uart interrupt tx rx in Dos32 bit open watcom

> > Thanks for your time on this topic.
> after looking a while on it it *looks* ok
>
> however the sender code is missing. therefore a few questions:
>
> is the fifo empty when it stops?
> is there some correlation to (index & 0x0f) ?
>
> when transmission stops because no more data to be send,
> how do you restart transmission?
>
> is this a PCI bus machine, or some *real* old machine ?
>
> lastly: what purpose has the rmloop ?

I found it necessary to prime the transmit buffer. I assume a standard AT style serial port.

Excerpt from the code linked to:

_WRCOM1Q LABEL FAR
; WRITE A STRING TO THE COM1 QUEUE AND SEND USING INTERRUPTS.
PUSH BP
MOV BP,SP
PUSH DS ; PUSH DS.
PUSH ES
PUSH CX
PUSH DX
PUSH SI
PUSH DI
MOV CX,WORD PTR SS:[BP+CHARS] ; GET NUMBER OF BYTES.
LES SI,DWORD PTR SS:[BP+STRING] ; GET ADDRESS OF BUFFER.
MOV AX,CMWRT1Q ; GET COM1 TRANSMIT COMMON BLOCK.
MOV DS,AX
MOV DX,MDCNTL
MOV AL,OUT2 OR RTS OR DTR ; ENABLE DATA TERMINAL READY AND READY TO SEND
OUT DX,AL
; IS THE QUEUE EMPTY?
CLI ; DISABLE INTERRUPTS WHILE CHECKING QUEUE SIZE.
MOV DI,DS:[WRTQSPACE] ; GET WRITE QUEUE INDICATOR.
CMP DI,WRTQSIZ ; IS IT EMPTY?
JNE QUEDTA
; THE TRANSMIT BUFFER IS EMPTY AND MUST BE "PRIMED" BY SENDING OUT THE FIRST BYTE.
; CHECK THAT THE PHYSICAL TX BUFFER IS EMPTY.
MOV DX,LNSTAT ; WAIT TILL ITS GONE.
TXTST3 LABEL NEAR ; TRANSMIT FINISH LOOP.
IN AL,DX ; GET LINE STATUS.
AND AL,TXEMTY
JZ TXTST3 ; LOOP UNITL NON-ZERO.
MOV DX,MDCNTL
MOV AL,OUT2 OR RTS OR DTR ; ENABLE DATA TERMINAL READY AND REQUEST TO SEND
OUT DX,AL
MOV DX,LNCNTL ; SET TO LINE CONTROL.
IN AL,DX ; GET THE VALUE.
MOV AH,AL ; SAVE ORIGINAL VALUE.
AND AL,NOT SETBAUD ; AND OFF THE SET BAUD BIT.
OUT DX,AL ; SEND IT.
MOV AL,ES:[SI] ; GET THE FIRST BYTE TO SEND.
INC SI ; POINT TO THE NEXT BYTE.
MOV DX,DATABF ; SEND THE FIRST BYTE TO THE DATA PORT.
OUT DX,AL
MOV AL,AH ; RESTORE LINE CONTROL.
MOV DX,LNCNTL
OUT DX,AL ; BACK IT GOES.
DEC CX ; DECREMENT THE COUNT.
MOV AX,DI ; IF NEXT BRANCH OCCURS, ALL SPACE IS AVAILABLE.
CMP CX,0 ; DID WE ONLY HAVE TO SEND ONE BYTE?
STI ; ENABLE INTERRUPTS.
JE TXDONE ; WAHOO!
QUEDTA LABEL NEAR
STI ; ENABLE INTERRUPTS
NOP
MOV AX,DS:[WRTQSPACE] ; DO WE HAVE SPACE ON THE QUEUE?
CLI ; DISABLE INTERRUPTS TO UPDATE QSPACE.
CMP AX,0
JE QUEDTA ; WAIT FOR SOME SPACE TO CLEAR UP.
DEC AX ; UPDATE AVAILABLE QUEUE SPACE, PREVENT INTERRUPT HANDLER FROM
MOV DS:[WRTQSPACE],AX ; MODIFYING IT AT THE SAME TIME
STI ; ENABLE INTERRUPTS.
MOV DI,DS:[WRTHEAD] ; GET THE HEAD OF THE QUEUE.
MOV AL,ES:[SI] ; GET NEXT BYTE TO QUEUE UP.
INC SI ; POINT TO NEXT BYTE
MOV DS:[DI+WRTQUE],AL ; PUT IT ON THE QUEUE.
INC DI ; POINT TO NEXT SPOT IN QUEUE
CMP DI,WRTQSIZ
JNE HEADINC
XOR DI,DI ; RESET IT TO ZERO.
HEADINC LABEL NEAR
MOV DS:[WRTHEAD],DI
LOOP QUEDTA
MOV AX,DS:[WRTQSPACE]
TXDONE LABEL NEAR
POP DI
POP SI
POP DX
POP CX
POP ES
POP DS
POP BP
RET ; RETURN

maui(R)

19.11.2013, 12:42

@ Brian_extended

uart interrupt tx rx in Dos32 bit open watcom

> > > Thanks for your time on this topic.
> > after looking a while on it it *looks* ok
> >
> > however the sender code is missing. therefore a few questions:
> >
> > is the fifo empty when it stops?
> > is there some correlation to (index & 0x0f) ?
> >
> > when transmission stops because no more data to be send,
> > how do you restart transmission?
> >
> > is this a PCI bus machine, or some *real* old machine ?
> >
> > lastly: what purpose has the rmloop ?
>
> I found it necessary to prime the transmit buffer. I assume a standard AT
> style serial port.
>
> Excerpt from the code linked to:
>
> _WRCOM1Q LABEL FAR
> ; WRITE A STRING TO THE COM1 QUEUE AND SEND USING INTERRUPTS.
> PUSH BP
> MOV BP,SP
> PUSH DS ; PUSH DS.
> PUSH ES
> PUSH CX
> PUSH DX
> PUSH SI
> PUSH DI
> MOV CX,WORD PTR SS:[BP+CHARS] ; GET NUMBER OF BYTES.
> LES SI,DWORD PTR SS:[BP+STRING] ; GET ADDRESS OF BUFFER.
> MOV AX,CMWRT1Q ; GET COM1 TRANSMIT COMMON BLOCK.
> MOV DS,AX
> MOV DX,MDCNTL
> MOV AL,OUT2 OR RTS OR DTR ; ENABLE DATA TERMINAL READY AND READY TO SEND
> OUT DX,AL
> ; IS THE QUEUE EMPTY?
> CLI ; DISABLE INTERRUPTS WHILE CHECKING QUEUE SIZE.
> MOV DI,DS:[WRTQSPACE] ; GET WRITE QUEUE INDICATOR.
> CMP DI,WRTQSIZ ; IS IT EMPTY?
> JNE QUEDTA
> ; THE TRANSMIT BUFFER IS EMPTY AND MUST BE "PRIMED" BY SENDING OUT THE
> FIRST BYTE.
> ; CHECK THAT THE PHYSICAL TX BUFFER IS EMPTY.
> MOV DX,LNSTAT ; WAIT TILL ITS GONE.
> TXTST3 LABEL NEAR ; TRANSMIT FINISH LOOP.
> IN AL,DX ; GET LINE STATUS.
> AND AL,TXEMTY
> JZ TXTST3 ; LOOP UNITL NON-ZERO.
> MOV DX,MDCNTL
> MOV AL,OUT2 OR RTS OR DTR ; ENABLE DATA TERMINAL READY AND REQUEST TO
> SEND
> OUT DX,AL
> MOV DX,LNCNTL ; SET TO LINE CONTROL.
> IN AL,DX ; GET THE VALUE.
> MOV AH,AL ; SAVE ORIGINAL VALUE.
> AND AL,NOT SETBAUD ; AND OFF THE SET BAUD BIT.
> OUT DX,AL ; SEND IT.
> MOV AL,ES:[SI] ; GET THE FIRST BYTE TO SEND.
> INC SI ; POINT TO THE NEXT BYTE.
> MOV DX,DATABF ; SEND THE FIRST BYTE TO THE DATA PORT.
> OUT DX,AL
> MOV AL,AH ; RESTORE LINE CONTROL.
> MOV DX,LNCNTL
> OUT DX,AL ; BACK IT GOES.
> DEC CX ; DECREMENT THE COUNT.
> MOV AX,DI ; IF NEXT BRANCH OCCURS, ALL SPACE IS AVAILABLE.
> CMP CX,0 ; DID WE ONLY HAVE TO SEND ONE BYTE?
> STI ; ENABLE INTERRUPTS.
> JE TXDONE ; WAHOO!
> QUEDTA LABEL NEAR
> STI ; ENABLE INTERRUPTS
> NOP
> MOV AX,DS:[WRTQSPACE] ; DO WE HAVE SPACE ON THE QUEUE?
> CLI ; DISABLE INTERRUPTS TO UPDATE QSPACE.
> CMP AX,0
> JE QUEDTA ; WAIT FOR SOME SPACE TO CLEAR UP.
> DEC AX ; UPDATE AVAILABLE QUEUE SPACE, PREVENT INTERRUPT HANDLER FROM
>
> MOV DS:[WRTQSPACE],AX ; MODIFYING IT AT THE SAME TIME
> STI ; ENABLE INTERRUPTS.
> MOV DI,DS:[WRTHEAD] ; GET THE HEAD OF THE QUEUE.
> MOV AL,ES:[SI] ; GET NEXT BYTE TO QUEUE UP.
> INC SI ; POINT TO NEXT BYTE
> MOV DS:[DI+WRTQUE],AL ; PUT IT ON THE QUEUE.
> INC DI ; POINT TO NEXT SPOT IN QUEUE
> CMP DI,WRTQSIZ
> JNE HEADINC
> XOR DI,DI ; RESET IT TO ZERO.
> HEADINC LABEL NEAR
> MOV DS:[WRTHEAD],DI
> LOOP QUEDTA
> MOV AX,DS:[WRTQSPACE]
> TXDONE LABEL NEAR
> POP DI
> POP SI
> POP DX
> POP CX
> POP ES
> POP DS
> POP BP
> RET ; RETURN

Hi,

sorry for the delay in the reply, I'm trying to understand your code, to make it work with mine.
Your code is checking for if the transmitter buffer has space to send the new data right?
When I trying it, I get from the register status line, that the Empty Transmitter Holding Register is up, but after I put another byte in queue, the bit turns off, returning at that point, doesn't not always come in the getting a next call from the byte sent.
To implement the interrupt, I have to use 2 block of code, one for protect mode, and another one for real mode, the code i posted before, was the real mode, the tx interrupt has never entered the protect mode.

I'm trying to understand, if there is a way to keep loading byte in the fifo, till the queue is full, then clearing the interrupt and return, so wait for the next call.

Thanks again for your support.

maui.

Brian_extended(R)

19.11.2013, 20:59

@ maui

uart interrupt tx rx in Dos32 bit open watcom

My code was too long to post here in it's entirety, so I linked to the full code.

The routine shown here loads a string into the buffer and is outside the interrupt handler. The code to load the string into the buffer must check if the hardware is Currently Transmitting. If it is done, the code must start the first byte to the transmitter. Once that byte is sent, the interrupt handler will take over and transmit another byte.

The code shown is real-mode, for Microsoft C++ V1.52. I'm currently porting it to Phar Lap, but is not working yet.

Brian_extended(R)

22.11.2013, 15:22

@ maui

uart interrupt tx rx in Dos32 bit open watcom

The fun of staying up late last night and debugging code...

I found that checking the Interrupt ID register of the serial port in the Handler "did not work as well as it did decades ago"... I'm used to reading this register at the beginning of the handler and checking the conditions individually.

Changed Strategy: Using the Line Status Register to check the Receive Buffer Ready and Transmit buffer empty no matter WHAT condition causes the interrupt works. Checking the Interrupt ID register: highest priority sets it, and a lower priority interrupt coming in while in the handler was lost.

Turns out I started a protected mode interrupt handler in 1994 for Phar Lap. I could not find any of my code that actually used it. I stuck with real-mode for the RS232, and switched to a different interface for protected mode. TWENTY years later, "comio386.asm" is working. New version using circular queues for both TX and RX coming up. I need this thing to work for a new piece of hardware.

Brian_extended(R)

23.11.2013, 03:09

@ Brian_extended

uart interrupt tx rx in Dos32 bit open watcom

Phar Lap provides "Shadow Interrupt Vectors" that routes both real-mode and protected mode interrupts to your handler. This made life easy. I have the queue driven RX/TX handler working using shadow vector table. For the embedded application, the software will be in protected mode just after boot-up.

If you are interested in the code, let me know. Arguments are passed on the stack, by reference and string descriptor. Common blocks hold the structures.

maui(R)

24.11.2013, 13:45

@ Brian_extended

uart interrupt tx rx in Dos32 bit open watcom

hi brian,
if you can post the code (e.g. pastebin dropbox wikisend) I will be happy to test it :)
thank you very much
maurice


> Phar Lap provides "Shadow Interrupt Vectors" that routes both real-mode and
> protected mode interrupts to your handler. This made life easy. I have the
> queue driven RX/TX handler working using shadow vector table. For the
> embedded application, the software will be in protected mode just after
> boot-up.
>
> If you are interested in the code, let me know. Arguments are passed on the
> stack, by reference and string descriptor. Common blocks hold the
> structures.

Brian_extended(R)

26.11.2013, 23:25

@ maui

uart interrupt tx rx in Dos32 bit open watcom

> hi brian,
> if you can post the code (e.g. pastebin dropbox wikisend) I will be happy
> to test it :)
> thank you very much
> maurice

Is there a way to upload a 30KByte file on this site?

RayeR(R)

Homepage

CZ,
27.11.2013, 03:26

@ Brian_extended

uart interrupt tx rx in Dos32 bit open watcom

> Is there a way to upload a 30KByte file on this site?

Probably not good idea, try http://pastebin.com/ and post link here :)

---
DOS gives me freedom to unlimited HW access.

Brian_extended(R)

05.01.2014, 20:42

@ RayeR

uart interrupt tx rx in Dos32 bit open watcom

> > Is there a way to upload a 30KByte file on this site?
>
> Probably not good idea, try http://pastebin.com/ and post link
> here :)

I ended up bypassing the BIOS calls for screen output and keyboard input to reduce the number of mode switches between protected mode and real mode. The mode switches were taking up a lot of time, and interrupts were getting lost. Wrote a couple of routines to access screen memory directly and the keyboard FIFO in real mode. At this point, I have interrupt driven RX and TX, all to some larger queues and working with the 16550. If there is interest, send me a PM with an Email address and i will provide the code.

The code is working on several machines, but not the WINsystems PPM800 PC104 board- they have some extra features that allow multiple com ports to share one interrupt. They left out some steps in the documentation, "am in pursuit" of it. ST240 does not work on their board, either- so it's them, not me.

Phar Lap maps the 1MByte real-mode memory as Segment 34h. Makes it easy to access real-mode memory while in protected mode.

Brian_extended(R)

26.01.2014, 02:06

@ Brian_extended

uart interrupt tx rx in Dos32 bit open watcom

Learned an important lesson about the 16550 FIFO- once in the Interrupt Handler, keep looping until all conditions are clear. Can't just service one byte and expect the interrupt to be clear. At this point, running reliably at 115Kb/s.

tom(R)

Homepage

Germany,
27.01.2014, 22:46

@ Brian_extended

uart interrupt tx rx in Dos32 bit open watcom

> Learned an important lesson about the 16550 FIFO- once in the Interrupt
> Handler, keep looping until all conditions are clear. Can't just service
> one byte and expect the interrupt to be clear. At this point, running
> reliably at 115Kb/s.

see my post from 12.11.2013. might have saved some time ;)

Back to the board
Thread view  Mix view  Order
15112 Postings in 1359 Threads, 249 registered users, 21 users online (0 registered, 21 guests)
DOS ain't dead | Admin contact
RSS Feed
powered by my little forum