Email: Password: Remember Me | Create Account (Free)

Back to Subject List

Old thread has been locked -- no new posts accepted in this thread
???
07/04/04 01:27
Read: times


 
#73589 - RE: Polling -- long
Responding to: ???'s previous message
Hi Joseph,

I've read and deliberated your posting.

Thank you for taking the time to do so.

...I do not understand a couple of points....

On the one hand you have polling wherein you must use at least one instruction to decide whether to service the serial port buffer (e.g.,If RI == 1;). This compares to a hardware interrupt which requires zero instructions to decide that you need to service the serial port buffer.

Yes, but the hardware still has to perform an LCALL to get to the ISR (i.e., start execution at 0x0023), then even though the hardware determined (at no cost) that interrupt service was necessary, the ISR must still determine which of RI or TI generated the interrupt, since they both vector to the same location. The LCALL must be matched by an RETI, adding more overhead. Also, unless the entire ISR fits between one vector and the next, a jump must be performed to get to the longer ISR -- again, more overhead. Let's compare a contrived example of polling versus interrupts that is so simple that it ignores errors, timeouts, etc. First, the interrupt-driven approach, which will receive a 16-byte packet and then transmit a 16-byte packet using register bank 1 and avoids using ACC, all to keep the size of the processor context that must be saved down to a minimum ("#~" indicates the number of instruction cycles):
;***************************************************************
;*
;* Serial Port Interrupt Vector
;*
;***************************************************************

        CSEG    AT 0023H        ; 2~ for H/W's LCALL
        LJMP    SIO_ISR         ; 2~

        CSEG    AT 002BH
        LJMP    TBD_ISR

        ; ...

;***************************************************************
;*
;* Serial Port Interrupt Service Routine
;*
;***************************************************************

SIO_ISR:                        ; 4~ to get here
        PUSH    PSW             ; 2~ Save context
        MOV     PSW,#00001000B  ; 2~ Select register bank 1
        JBC     RI,RX_HDLR      ; 2~ If not RI, assume TI.
                                ;10~ For ISR entry and Rx/Tx dispatch

; TI_HDLR ---------------------- 10~ to get here
        CLR     TI              ; 1~ Relieve the interrupt
        CJNE    R1,#0,TX_EXIT   ; 2~ If done transmitting,
                                ;     ..TI clear prevents more interrupts.
        MOV     SBUF,@R0        ; 2~ Transmit a byte
        INC     R0              ; 1~ Advance buffer pointer
        DEC     R1              ; 1~ Count off one byte
TX_EXIT:
        POP     PSW             ; 2~ Restore context (and register bank)
        RETI                    ; 2~ *** 21 cycles/byte

RX_HDLR: ;---------------------- 10~ to get here
        MOV     @R0,SBUF        ; 2~ Buffer received byte
        INC     R0              ; 1~ Advance buffer pointer
        DJNZ    R1,RX_EXIT      ; 2~ If done receiving,
        CLR     REN             ;     ..REN clear prevents more interrupts.
RX_EXIT:
        POP     PSW             ; 2~ Restore context
        RETI                    ; 2~ *** 19 cycles/byte

;***************************************************************
;*
;* Concurrent "Work" and I/O
;*
;***************************************************************

; Receive a 16-byte packet.

        USING   1
        MOV     AR0,#RX_BUFFER  ; Point to the receive buffer
        MOV     AR1,#16         ; Number of bytes to receive
        CLR     RI              ; Enable the receiver, allowing the
        SETB    REN             ;  ..ISR to buffer the received bytes.
RX_WAIT:
        LCALL   DO_SOMETHING    ; Do something useful
        MOV     A,AR1           ;  ..until the ISR decrements the
        JNZ     RX_WAIT         ;  ..byte counter down to zero.

; Process the received packet.
;       ...
;       ...
;       ...

; Transmit a 16-byte packet.

        MOV     AR0,#TX_BUFFER  ; Point to the transmit buffer
        MOV     AR1,#16         ; Number of bytes to transmit
        SETB    TI              ; Enable the transmitter, allowing the
                                ;  ..ISR to transmit bytes from the buffer.
TX_WAIT:
        LCALL   DO_SOMETHING    ; Do something useful
        MOV     A,AR1           ;  ..until the ISR decrements the
        JNZ     TX_WAIT         ;  ..byte counter down to zero.

We've got 21 cycles and 19 cycles per byte for interrupt-driven transmit and receive, respectively. Now let's look at the polled version with the same scenario of receiving a 16-byte packet and then transmitting a 16-byte packet.
; Receive a 16-byte packet.

        MOV     R0,#RX_BUFFER   ; Point to the receive buffer
        MOV     R1,#16          ; Number of bytes to receive
        CLR     RI              ; Enable the receiver
        SETB    REN
RX_LOOP:
        JNB     RI,$            ; 2~ Wait for a byte to shift in
        CLR     RI              ; 1~
        MOV     @R0,SBUF        ; 2~ Buffer received byte
        INC     R0              ; 1~ Advance buffer pointer
        DJNZ    R1,RX_LOOP      ; 2~ If not done receiving, *** 8 cycles/byte
                                ;     ..loop for next byte.
                                ;    NOTE: Polling doesn't need REN cleared.
; Process the received packet.
;       ...
;       ...
;       ...

; Transmit a 16-byte packet.

        MOV     R0,#TX_BUFFER   ; Point to the transmit buffer
        MOV     R1,#16          ; Number of bytes to transmit
TX_LOOP:
        JNB     TI,$            ; 2~ Wait for a byte (if any) to shift out
        CLR     TI              ; 1~
        MOV     SBUF,@R0        ; 2~ Transmit a byte from the buffer
        INC     R0              ; 1~ Advance buffer pointer
        DJNZ    R1,TX_LOOP      ; 2~ If done transmitting, *** 8 cycles/byte
                                ;     ..loop for next byte.

So we've got 8~/8~ for polled versus 21~/19~ for interrupt-driven. Now, in the extreme case, one could "unroll" the receive loop to achieve 5 cycles per byte, for example:
        JNB     RI,$            ; 2~
        CLR     RI              ; 1~
        MOV     A,SBUF          ; 1~
        MOV     #RX_BUFFER+0,A  ; 1~ *** 5 cycles/byte
;       .
;       .
;       .
;       14 more instances of the code sequence
;       .
;       .
;       .
        JNB     RI,$
        CLR     RI
        MOV     A,SBUF
        MOV     #RX_BUFFER+15,A

It seems to me that as the data throughput increases, the need for interrupts increases. But this is the opposite of your experience.

I hope my examples have cleared that up.

So, this is my interpretation/guess concerning your experience. Since your program did nothing else but service the serial port buffer ("And by the way, the system had absolutely nothing else to do until it received a packet."), your entire program was, in effect, the SPI routine.

In this case my program was a cellular radio control "server" to a much more powerful "client" processor. The radio control processor "served" the requests made by the client for things like controlling complex transmit and receive GSM signal processor chips (100's of registers each), programmable transmit and receive synthesizers, octal DACs, temperature sensors, EEPROM, etc. There was nothing to do until the client requests some kind of radio control, then control is performed and the results transmitted back -- a closed-loop, "interlocked" system. No need for interrupt-driven serial I/O and the data rate was fast.

So it seems that this is a good example of the circumstance I was asking about. If the main program is a dedicated serial port service routine, then there is no need for interrupt vectoring.

Or more clearly, if the main program is dedicated to awaiting something via the serial port, then does something with that something (i.e., has two [or more] mutually exclusive states), then there is no need for interrupt-driven serial I/O.

Moreover, using the hardware vectoring becomes a waste of cycles thereby making polling the preferable approach. Stated simpler, if the whole program is a serial port routine, using hardware interrupts is a waste.

A generalization, but yes.

But, would you say that if the program is not dedicated exclusively to servicing the serial port, it is probably better to use the interrupt?

Generally, yes. I would say that the majority of my designs over 26 years have used interrupt-driven I/O. Now I'd say that it's more like 80/20 or 90/10 rather than saying polling is the <5% exception.

Or, is it possible that there are circumstances wherein polling within a larger context (program) might still be preferable to using interrupts?

I hesitate to say it, but yes to that too. You see, it's all a matter of designing to fit requirements -- all types of requirements -- functional, performance, ease of future enhancements, portability, you name it.

And how would one quantify it?

Study all your requirements. If you don't have a clear pick which way to go, you haven't studied hard enough. Or, just go with interrupt-driven and deal with design changes later, if required. The top two benefits for polling (my list) are 1) performance and 2) simplicity (oh, bugger -- yes I know, interrupts aren't hard, yadda, yadda, yadda).

Just to give you another example, and this one only because I'm in the thick of it at the moment, is U-Boot. This is not an 8051 thing. It is arguably the most popular non-x86 (e.g., PowerPC, ARM, etc.) bootloader for 32-bit OS's, Linux included. It supports serial ports, ethernet, oodles of different flash devices, etc. on a whole bunch of different COTS boards and is tailored to being customized by the likes of me for custom boards. Does it use interrupts? Nope! Too much extra baggage portability-wise -- now there's a requirement.

The bottom line:

As you can see, I predominantly use interrupt driven I/O because of the overall flexibility it offers in complex systems, but I am often called upon to squeeze performance out of systems that would otherwise be unachievable if I didn't use polling in certain areas.


List of 29 messages in thread
TopicAuthorDate
UART Without Serial Interrupt?            01/01/70 00:00      
   Polling            01/01/70 00:00      
      RE: Polling            01/01/70 00:00      
         RE: Polling            01/01/70 00:00      
            RE: Polling            01/01/70 00:00      
               RE: Polling            01/01/70 00:00      
                  RE: Polling            01/01/70 00:00      
                     RE: Polling            01/01/70 00:00      
                        RE: Polling            01/01/70 00:00      
                           RE: Polling            01/01/70 00:00      
                              RE: one step further            01/01/70 00:00      
                                 RE: one step further            01/01/70 00:00      
                                 another step further            01/01/70 00:00      
                                    RE: another step further            01/01/70 00:00      
                                       RE: another step further caveats            01/01/70 00:00      
                                          RE: another step further caveats            01/01/70 00:00      
                     RE: Polling -- long            01/01/70 00:00      
            RE: Polling            01/01/70 00:00      
               RE: Polling            01/01/70 00:00      
   RE: UART Without Serial Interrupt?            01/01/70 00:00      
      RE: UART Without Serial Interrupt?            01/01/70 00:00      
         RE: UART Without Serial Interrupt?            01/01/70 00:00      
         RE: UART Without Serial Interrupt?            01/01/70 00:00      
            RE: UART Without Serial Interrupt?            01/01/70 00:00      
   RE: UART Without Serial Interrupt?            01/01/70 00:00      
   When is polling preferable?            01/01/70 00:00      
      RE: When is polling preferable?            01/01/70 00:00      
   RE: UART Without Serial Interrupt?            01/01/70 00:00      
   Advantage of polling            01/01/70 00:00      

Back to Subject List