Rabbit 2000™ Microprocessor User's Manual

> ## 12. Rabbit Serial Ports

> The Rabbit has four on-chip serial ports designated A, B, C, and D. All the ports can perform asynchronous serial communications at high baud rates. Ports A and B have the additional capabilities of being able to operate as clocked ports and of being switchable to alternate I/O pins. Port A has the special capability of being usable to perform a cold boot of the microprocessor system.

> Figure 12-1 shows a block diagram of the serial ports.

> Figure 12-1. Block Diagram of Rabbit Serial Ports

> The individual serial ports are capable of operating at baud rates in excess of 500,000 bps in the asynchronous mode, and 8 times faster than that in the synchronous mode. Either 7 or 8 data bits may be transmitted and received in the asynchronous mode. The so-called "9th" bit or address bit mode of operation is also supported. Parity and multiple stop bits are not directly supported by the hardware, but may be accomplished with suitable programming techniques.

> ### 12.1 Register Layout Serial Port

> Figure 12-2 shows a functional block diagram of a serial port. Each serial port has a data register, a control register and a status register. Writing to the data register starts transmission. If the write is performed to an alternate data register address, the extra address bit or 9th bit is sent. When data bits have been received, they are read from the data register. The control register is used to set the transmit and receive parameters. The status register may be tested to check on the operation of the serial port.

> Figure 12-2. Functional Block Diagram of a Serial Port

> The clock input to the serial port unit must be 16 times the baud rate in the asynchronous mode and 2 times the baud rate for the clocked serial mode when the internal clock is used. Timers A4-A7 supply the input clock for Serial Ports A-D. These timers can divide the frequency by any number from 1 to 256 (see Chapter 11). The input frequency to the timers can be selected in different ways described in the documentation for the timers. One choice is the peripheral clock divided by 2—with that choice and a well-chosen crystal frequency for the main oscillator, the most commonly used baud rates can be obtained down to approximately 2400 bps at the highest Rabbit clock frequencies (see Section A.4 in Appendix A).

> Table 12-1 lists the serial port registers.

> Table 12-1. Serial Port Registers
> Register | Address xx = 00, 01, 10, 11 for A, B, C, D | Mnemonic x = A, B, C, D
> Data Register | 11xx0000 | SxDR
> Alternate Data Register to Send 9th (8th) Address Bit. | 11xx0001 | SxAR
> Status Register (read, write to clear transmit IRQ) | 11xx0011 | SxSR
> Control Register (write only) | 11xx0100 | SxCR

> The serial port interrupt vectors are shown in Table 7-9.

> Table 12-2 describes the serial port status registers.

> Table 12-2. Serial Port Status Registers (adr = 11xx0011, xx = A,B,C,D)
> Bit 7 | Bit 6 | Bit 5 | Bit 4 | Bit 3 | Bit 2 | Bit 1,0
> Receiver ready (there is a byte in the receive data register) | 9th bit received | Receive buffer overrun | 0 | Transmitter data register is full | Transmitter is sending a byte | 0,0

> Writing to the status register clears the transmit interrupt request FF, but has no other effect.

> Bit 7—Receiver ready. This bit is set when a byte is transferred from the receiver shift register to the receiver data register. The bit is cleared when the receiver data register is read. The transition from "0" to "1" sets the receiver interrupt request flip-flop.
> Bit 6—Address bit or 9th (8th) bit. This bit is set if the character in the receiver data register has a 9th (8th) bit. This bit is cleared and should be checked before reading a data register since a new data value with a new address bit may be loaded immediately when the data register is read.
> Bit 5—This bit is set if the receiver is overrun. This happens if the shift register and the data register are full and a start bit is detected. This bit is cleared when the receiver data register is read.
> Bit 3—Transmitter data buffer full. This bit is set when the transmit data register is full, that is, a byte is written to the serial port data register. It is cleared when a byte is transferred to the transmitter shift register or a write operation is performed to the serial port status register. This bit will request an interrupt on the transition from 1 to 0 if interrupts are enabled.
> Bit 2—Transmitter busy bit. This bit is set if the transmitter shift register is busy sending data. It is set on the falling edge of the start bit, which is also the clock edge that transfers data from the transmitter data register to the transmitter shift register. The transmitter busy bit is cleared at the end of the stop bit of the character sent. This bit will cause an interrupt to be latched when it goes from busy to not busy status after the last character has been sent (there are no more data in the transmitter data register).
> Bits 0,1,4—Always read as zero.

> Table 12-3 describes the serial port control registers.

> Table 12-3. Serial Port Control Registers (adr = 11xx0100, xx = A,B,C,D)
> Bit 7,6 | Bit 5,4 | Bit 3,2 | Bit 1,0
> 00—no op 01—receive 1 byte clocked mode (A,B) 10—send one byte clocked mode (A,B) 11—reserved for future use | 00—use port C for serial input 01—use port D for serial input 1x—disable receiver input | 00—async mode, 8 bits 01—async mode 7 bits 10—clocked mode external clock (A,B) 11—clocked mode internal clock (A,B) | 00—no interrupt 01— priority 1 interrupt 10—priority 2 11—priority 3

> Bits 7,6—In asynchronous mode, always store zero in these bits. For Ports A and B, if the clocked serial mode is enabled, store the code here to start an operation, either receive or send. If the clock is internal, a burst of 8 clocks will drive the clock line. In external mode, the receiver or transmitter waits for an externally supplied burst of 8 clocks.
> Bits 5,4—This enables the standard or alternate pins for the ports. The parallel port output function for the specified Tx pin becomes disabled when the port is enabled. The settings in the parallel port C function register (PCFR) and the parallel port D function register (PDFR) are used to enable the Port C and Port D serial outputs (see Section 9.3, "Parallel Port C," and Section 9.4, "Parallel Port D," for more details).
> Bits 3,2—This sets the mode of operation. Modes 10 and 11 apply only to Ports A and B.
> Bits 1,0—These bits enable interrupts and set the interrupt priority.

> ### 12.2 Serial Port Interrupt

> A common interrupt vector is used for the receive and transmit interrupts. There is a separate interrupt request flip-flop for the receiver and transmitter. If either of these flip-flops is set, a serial port interrupt is requested. The flip-flops are set by a rising edge only. The flip-flops are cleared by a pulse generated by an I/O read or write operation as shown in Figure 12-3. When an interrupt is requested, it will take place immediately when priorities allow and an instruction execution is complete. The interrupt is lost if the request flip-flop is cleared before the interrupt takes place. If the flip-flop is not cleared in the interrupt, another interrupt will take place when priorities are lowered.

> Figure 12-3. Generation of Serial Port Interrupts

> The receive interrupt request flip-flop is set after the stop bit is sampled on receive, nominally 1/2 of the way through the stop bit. Data bits are transferred on this same clock from the receive shift register to the receive data register.

> The transmit interrupt request flip-flop is set on the leading edge of the stop bit for data register empty and at the trailing edge of the stop bit for shift register empty (transmitter idle). Unless the data register is empty on this trailing edge of the stop bit, the transmitter does not become idle. The transmitter becomes idle only if the data register is empty at the trailing edge of the stop bit.

> The serial port interrupt vectors are shown in Table 7-9.

> ### 12.3 Transmit Serial Data Timing

> On transmit, if the interrupts are enabled, an interrupt is requested when the transmit register becomes empty and, in addition, an interrupt occurs when the shift register and transmit register both become empty, that is, when the transmitter becomes idle. When the transmit data register contains data and the shift register finishes sending data, the data bits are clocked from the transmit register to the shift register, and the shift register is never idle. The interrupt request is cleared either by writing to the data register or by writing to the status register (which does not affect the status register). The data register normally is clocked into the shift register each time the shift register finishes sending data, leaving the data register empty. This causes an interrupt request. The interrupt routine normally answers the interrupt before the shift register runs dry (9 to 11 baud clocks, depending on the mode of operation). The interrupt routine stores the next data item in the data register, clearing the interrupt request and supplying the next data bits to be sent. When all the characters have been sent, the interrupt service routine answers the interrupt once the data register becomes empty. Since it has no more data, it clears the interrupt request by storing to the status register. At this point the routine should check if the shift register is empty; normally it won't be. If it is, because the interrupt was answered late, the interrupt routine should do any final cleanup and store to the status register again in case the shift register became empty after the pending interrupt is cleared. Normally, though, the interrupt service routine will return and there will be a final interrupt to give the routine a chance to disable the output buffers, as in the case for RS-485 transmission.

> ### 12.4 Receive Serial Data Timing

> When the receiver is ready to receive data, a falling edge indicates that a start bit must be detected. The falling edge is detected as a different Rx input between two different clocks, the clock being 16x the baud rate. Once the start bit has been detected, data bits are sampled at the middle of each data bit and are shifted into the receive shift register. After 7 or 8 data bits have been received, the next bit will be either a 9th (8th) address bit, or a stop bit will be sampled. If the Rx line is low, it is an address bit and the address bit received bit in the status register will be enabled. If an address bit is detected, the receiver will attempt to sample the stop bit. If the line is high when sampled, it is a stop bit and a new scan for a new start bit will begin after the sample point. At the same time, the data bits are transferred into the receive data register and an interrupt, if enabled, is requested.

> On receive, an interrupt is requested when the receiver data register has data. This happens when data bits are transferred from the receive shift register to the data register. This also sets bit 7 of the status register. The interrupt request and bit 7 are cleared when the data register is read.

> An interrupt is requested if bit 7 is high. The interrupt is requested on the edge of the transmitter data register becoming empty or the transmitter shift register becoming empty. The transmitter interrupt is cleared by writing to the status register or to the data register.

> On receive, the scan for the next start bit starts immediately after the stop bit is detected. The stop bit is normally detected at a sample clock that nominally occurs in the center of the stop bit. If there is a 9th (8th) address bit, the stop bit follows that bit.

> ### 12.5 Clocked Serial Ports

> Ports A and B can operate in clocked mode. The data line and clock line are driven as shown in Figure 12-4. The data and clock are provided as 8-bit bursts. The transmit shift register advances on the falling edge of the clock. The receiver samples the data on the rising edge of the clock. The serial port can generate the clock or the clock can be provided externally.

> Figure 12-4. Serial Port Synchronization

> Table 12-4 lists the synchronous serial port signals.

> Table 12-4. Synchronous Serial Port Signals
> Rabbit Signal Names | Pin Function
> CLKA or CLKB | Serial Clock
> TxA or TxB on Parallel Port C ATxA or ATxB on Parallel Port D | Data Transmit
> RxA or RxB on Parallel Port C ARxA or ARxB on Parallel Port D | Data Receive

> To enable the clocked serial mode, a code must be in bits (3,2) of the control register, enabling the clocked serial mode with either an internal clock or an external clock. The transition between the external and the internal clock should be performed with care. Normally a pullup resistor is needed on the clock line to prevent spurious clocks while neither party is driving the clock.

> In clocked serial mode the shift register and the data register work in the same fashion as for asynchronous communications. However, to initiate sending or receiving, a code must be stored in bits (7,6) of the control register for each byte sent or received. One code specifies sending a byte, a different code specifies receiving a byte. The effect of these codes is different, depending on whether the mode is internal clock or external clock.

> To transmit in internal clock mode, the user must first load the data register (which must be empty) and then store the send code. When the shift register finishes sending the current character, if any, the data register will be loaded into the shift register and transmitted by an 8-clock burst. One character can be in the process of transmitting while another character is waiting in the data register tagged with the send code. The send code is effectively double-buffered.

> To receive a character in internal clock mode, the receive shift register should be idle. The user then stores the receive code in the control register. A burst of 8 clocks will be generated and the sender must detect the clocks and shift output data to the data line on the falling edge of each clock. The receiver will sample the data on the rising edge of each clock. The receive mode cannot double-buffer characters when using the internal clock. The shift register must be idle before another character receive can be initiated. However, the interrupt request and character ready takes place on the rising edge of the last clock pulse. If the next receive code is stored before the natural location of the next falling edge, another receive will be initiated without pausing the clock. To do this, the interrupt has to be serviced within 1/2 clock.

> To transmit each byte in external clock mode, the user must load the data register and then store the send code. When the shift register is idle and the receiver provides a clock burst, the data bits are transferred to the shift register and are shifted out. Once the transfer is made to the shift register, a new byte can be loaded into the transmit register and a new send code can be stored.

> To receive a byte in external clock mode, the user must set the receive code for the first byte and then store the receive code for the next byte after each byte is removed from the data register. Since the receive code must be stored before the transmitter sends the next byte, the receiver must service the interrupt within 1/2 baud clock to maintain full-speed transmission. This is usually not practical unless a flow control arrangement is made or the transmitter inserts gaps between the clock bursts.

> In order to carry on high-speed communication, the best arrangement will usually be for the receiver to provide the clock. When the receiver provides the clock, the transmitter should always be able to keep up because it is double-buffered and has a full character time to answer the transmitter data register empty interrupt. The receiver will answer interrupts that are generated on the last clock rising edge. If the interrupt can be serviced within 1/2 clock, there will be no pause in the data rate. If it takes the receiver longer to answer, then there will be a gap between bytes, the length of which depends on the interrupt latency. For example, if the baud rate is 400,000 bps, then up to 50,000 bytes per second could be transmitted, or a byte every 20 µs. No data will be lost if the transmitter can answer its interrupts within 20 µs. There will be no slow down if the receiver can answer its interrupt within 1/2 clock or 1.25 µs. If it can answer within 1.5 clocks, or 2.75 µs, the data rate will slow to 44,444 bytes per second. If it can answer in 2.5 clocks or 6.25 µs, the data rate slows to 40,000 bytes per second. If it can answer in 3.5 clocks or 8.75 µs, the data rate will slow to 36,363 bytes per second, and so forth.

> If two-way half-duplex communication is desired, the clock can be turned around so that the receiver always provides the clock. This is slightly more complicated since the receiver cannot initiate a message. If the receiver attempts to receive a character and the transmitter is not transmitting, the last bit sent will be received for all eight bits.

> ### 12.6 Clocked Serial Timing

> #### 12.6.1 Clocked Serial Timing With Internal Clock

> For synchronous serial communication, the serial clock can be either generated by the Rabbit or by an external device. The timing diagram in Figure 12-5 below can be applied to both full-duplex and half-duplex clocked serial communication where the serial clock is generated internally by the Rabbit. With an internal clock, the maximum serial clock rate is perclk/4.

> Figure 12-5. Full-Duplex Clocked Serial Timing Diagram with Internal Clock

> #### 12.6.2 Clocked Serial Timing with External Clock

> In a system where the Rabbit serial clock is generated by an external device, the clock signal has to be synchronized with the internal peripheral clock (perclk) before data can be transmitted or received by the Rabbit. Depending on when the external serial clock is generated, in relation to perclk, it may take anywhere from 2 to 3 clock cycles for the external clock to be synchronized with the internal clock before any data can be transferred. Figure 12-6 shows the timing relationship among perclk, the external serial clock, and data transmit.

> Figure 12-6. Synchronous Serial Data Transmit Timing with External Clock

> Figure 12-7 shows the timing relationship among perclk, the external serial clock, and data receive. Note that RxA is sampled by the rising edge of perclk.

> Figure 12-7. Synchronous Serial Data Receive Timing with External Clock

> When clocking the Rabbit externally, the maximum serial clock frequency is limited by the amount of time required to synchronize the external clock with the Rabbit perclk. If we sum the maximum number of perclk cycles required to perform clock synchronization for each of the receive and transmit cases, then the fastest external serial clock frequency would be limited to perclk/6.

> ### 12.7 Serial Port Software Suggestions

> The receiver and transmitter share the same interrupt vector, but it is possible to make the receive and transmit interrupt service routines (ISRs) separate by dispatching the interrupt to either of two different routines. This is desirable to make the ISR less complex and to reduce the interrupt off time. No interrupts will be lost since distinct interrupt flip-flops exist for receive and transmit. The dispatcher can test the receiver data register full bit to dispatch. If this bit is on, the interrupt is dispatched for receive, otherwise for transmit. The receiver receives first consideration because it must be serviced attentively or data could be lost.

> The dispatcher might look as follows.

>     interrupt:

>     push af          ; 10
>     ioi ld a,(SCSR)  ; 7 get status register serial port C
>     or a             ; 2 test sign bit
>     jp m,receive     ; 7 go service the receive interrupt
>     jp transmit      ; 7 (41 clocks to here) go service transmit interrupt

> The individual interrupts would assume that register AF has been saved and the status register has been loaded into register A.

> The interrupt service routines can, as a matter of good practice and obtaining optimum performance, remove the cause of the interrupt and re-enable the interrupts as soon as possible. This keeps the interrupt latency down and allows the fastest transmission speed on all serial ports.

> All the serial ports will normally generate priority level 1 interrupts. In exceptional circumstances, one or more serial ports can be configured to use a higher priority interrupt. There is an exception to be aware of when a serial port has to operate at an extremely high speed. At 115,200 bps, the highest speed of a PC serial port, the interrupts must be serviced in 10 baud times, or 86 µs, in order not to lose the received characters. If all four serial ports were operating at this receive speed, it would be necessary to service the interrupt in less than 21.5 µs to assure no lost characters. In addition, the time taken by other interrupts of equal or higher priority would have to be considered. A receiver service routine might appear as follows below. The byte at bufptr is used to address the buffer where data bits are stored. It is necessary to save and increment this byte because characters could be handled out of order if two receiver interrupts take place in quick succession.

>     receive:

>     push hl         ; 10 save hl
>     push de         ; 10 save de
>     ld hl,struct    ; 6
>     ld a,(hl)       ; 5 getin-pointer
>     ld e,a          ; 2 save in pointer in e
>     inc hl          ; 2 point to out-pointer
>     cmp a,(hl)      ; 5 see if in-pointer=out-pointer (buffer full)
>     jr z,roverrun   ; 5 go fix up receiver over run
>     inc a           ; 2 incement the in pointer
>     and a,mask      ; 4 mask such as 11110000 if 16 buffer locs
>     dec hl          ; 2
>     ld (hl),a       ; 6 update the in pointer
>     ioi ld a,(SCDR) ; 11 get data register port C, clears interrupt request
>     ipres	            ; 4 restore the interrupt priority

>     ; 68 clocks to here
>     ; to level before interrupt took place
>     ; more interrupts could now take place,
>     ; but receiver data is in registers
>     ; now handle the rest of the receiver interrupt routine
>     ld hl,bufbase   ; 6
>     ld d,0          ; 6
>     add hl,de       ; 2 location to store data
>     ld (hl),a       ;  6 put away the data byte
>     pop de          ;7
>     pop hl          ; 7
>     pop af          ; 7
>     ret             ; 8 from interrupt

>     ; 117 clocks to here

> This routine gets the interrupts turned on in about 68 clocks or 3.5 µs at a clock speed of 20 MHz. Although two characters may be handled out of order, this will be invisible to a higher level routine checking the status of the input buffer because all the interrupts will be completed before the higher level routine can perform a check on the buffer status.

> A typical way to organize the buffers is to have an in-pointer and an out-pointer that increment through the addresses in the data buffer in a circular manner. The interrupt routine manipulates the in-pointer and the higher level routine manipulates the out-pointer. If the in-pointer equals the out-pointer, the buffer is considered full. If the out-pointer plus 1 equals the in-pointer, the buffer is empty. All increments are done in a circular fashion, most easily accomplished by making the buffer a power of two in length, then anding a mask after the increment. The actual memory address is the pointer plus a buffer base address.

> #### 12.7.1 Controlling an RS-485 Driver and Receiver

> RS-485 uses a half-duplex method of communication. One station enables its driver and sends a message. After the message is complete, the station disables the driver and listens to the line for a reply. The driver must be enabled before the start bit is sent and not disabled until the stop bit has been sent. The transmitter idle interrupt is normally used to disable the RS-485 driver and possibly enable the receiver.

> #### 12.7.2 Transmitting Dummy Characters

> It may be desired to operate the serial transmitter without actually sending any data. "Dummy" characters are transmitted to pass time or to measure time.

> The output of the transmitter may be disconnected from the transmitter output pin by manipulating the control registers for parallel port C or D, which are used as output pins. For example, if serial port B is to be temporarily disconnected from its output pin, which is bit 4 of parallel port C, this can be done as follows.

> 1. Store a "1" in bit 4 of the parallel port data output register to provide the quiescent state of the drive line.
> 2. Clear bit 4 of the parallel port C function register so that the output no longer comes from the serial port. Of course, this should not be done until the transmitter is idle.

> A similar procedure can be used if the serial port is set up to use alternate output pins on port D. Only serial ports A and B can use alternate outputs on parallel port D.

> If an RS-485 driver is being used, dummy characters can be transmitted by disabling the driver after the stop bit has been sent. This is an alternative to the above procedure.

> #### 12.7.3 Transmitting and Detecting a Break

> A break is created when the output of the transmitter is driven low for an extended period. If a break is received, it will appear as a series of characters filled with zeros and with the 9th bit detected low. This could only be confused with a legitimate message if a protocol using the 9th bit was in effect. Break is not usually used as a message in such protocols.

> A break can be transmitted by transmitting a byte of zeros at a very slow baud rate. Another and probably better method is to disconnect the transmitter from the output pin, and use the parallel port bit to set the line low while sending dummy characters to time out the break.

> The use of break as a signaling device should be avoided because it is slow, erratically supported by different types of hardware, and usually creates more problems than it solves.

> #### 12.7.4 Using A Serial Port to Generate a Periodic Interrupt

> A serial port may be used to generate a periodic interrupt by continuously transmitting characters. Since the Tx output via parallel port C or D can be disabled, the transmitted characters are transmitted to nowhere. Because the character output path is double-buffered, there will be no gaps in the character transmission, and the interrupts will be exactly periodic. The interrupts can happen every 9, 10 or 11 baud times, depending on whether 7 or 8 bits are transmitted and on whether the 9th (8th) bit is sent.

> #### 12.7.5 Extra Stop Bits, Sending Parity, 9th Bit Communication Schemes

> Some systems may require two stop bits. In some cases, it may be necessary to send a parity bit. Certain systems, such as some 8051 based multidrop communications systems, use a 9th data bit to mark the start of a message frame. The Rabbit 2000 can receive parity or message formats that contain a 9th bit without problem. Transmitting messages with parity or messages that always contain a 9th bit is also possible. It is quite easy to do so for byte formats that use only 7 data bits, in which case the 9th bit or parity bit is actually an 8th bit. Things are a little bit messy for the transmitter software if there are 8 data bits and a 9th parity or signaling bit is needed. Sending a 9th low bit is supported by hardware. Sending a 9th bit as a high value requires delaying the transmission of the next character by 1 baud time, effectively providing the 9th bit high and a stop bit, which is the same as two stop bits.

> Figure 12-8 illustrates the standard asynchronous serial output patterns.

> Figure 12-8. Asynchronous Serial Output Patterns

> ##### 12.7.5.1 Parity, Extra Stop Bits with 7 Data Bit Characters

> If only 7 data bits are being sent, the problem of sending an additional parity or signal bit is easily solved by sending 8 bits and always setting bit 7 (the eighth bit) of the byte to "1" or "0" depending on what is desired. No special precautions are needed if two stop bits are to be received. If parity is received with 7 data bits, receive the data as 8 bits, and the parity will be in the high bit of the byte.

> ##### 12.7.5.2 Parity, Extra Stop Bits with 8 Data Bit Characters

> In order to receive parity with 8 data bits, a check is made on each character for a 9th bit low. The 9th bit, or parity bit, is low if bit 6 of the serial port status register is set to a "1" after the character is received. If the 9th bit is not a zero, then the serial port treats it as an extra stop bit. So if the 9th bit low flag is not set, it should be assumed that the parity bit is a "1."

> No special precautions are necessary to receive extra stop bits, nor does the serial port check for stop bits beyond one. If the first stop bit is missing, it is treated as a 9th (or 8th) bit low and will be received as a 9-bit (8-bit) character.

> It is somewhat difficult to transmit an extra stop bit or a parity bit of value "1." The difficulty arises because there is no one solution that applies to every case, although there is a solution for every case. To send an extra stop bit or parity bit of value "1," it is necessary to delay sending the next character so that the stop bit will be extended to a length of at least 2 baud times. In order to delay the next character by an additional baud time, the program has to wait for the transmitter idle interrupt, which takes place after the data register empty interrupt. The data register ready interrupt request is terminated by writing to the status register. After the transmitter idle interrupt, which takes place at the trailing edge of the stop bit, the interrupt routine must not load the next character for another baud time, for example, 8.6 µs at 115,200 bps or 104 µs at 9600 bps. At the highest baud rates it makes sense to use a busy wait loop in the interrupt routine to time out a baud step before loading the data register with the next character. The busy wait loop may be very brief since the delay can be partially made up from the time used to save the registers on entry to the interrupt and the time used in fetching the next character to be sent from the transmit buffer. Of course the busy wait loop runs on the processor clock, which is subject to being throttled up and down, so the loop count must be coordinated with the current processor speed.

> A busy wait loop can still be used at slower baud rates, but then there will be a deleterious effect on the interrupt latency unless interrupts are re-enabled in the interrupt routine. This can certainly be done provided that the receiver and transmitter interrupts are properly dispatched to separate routines because the receiver and transmitter interrupts share the same interrupt vector. In addition, when interrupts are re-enabled in the interrupt routine, there must be coordination with the real-time kernel or the operating system (if there is one). This coordination typically involves a nesting count of interrupt routines that much be adjusted by each interrupt routine that re-enables interrupts before it returns. If a busy wait loop is used, it can be expected to consume around 10% of the processors compute time while characters are being transmitted, since it is doing busy waiting for 1 baud out of 11 baud times for each character sent. Using the transmitter idle interrupt to request the next character will result in gaps between characters that can be as long as the worst-case interrupt latency. Most applications are not bothered by gaps between characters, but certain applications such as Modbus require controlling gaps between characters. Thus, it would be inadvisable to attempt Modbus with parity at a high data rate.

> Other ways to add a 1-baud delay are listed below:

> - Use another serial port as a timer. Disable the interrupts on the port being used to transmit and, at the same time the data register is loaded, load a dummy character and a 9th bit in the other serial port. The interrupt in the auxiliary port will occur after 11 baud times rather than 10 baud times, thus guaranteeing the stop bit its full time.
> - Send a full dummy character to create a very long stop bit. To avoid the long stop bit, the baud timer can be speeded up while the dummy character is sent to reduce the length of the extra stop bit. The synchronous nature of timers A4-A7 allows the divide ratio to be increased or decreased at will without generating irregular clock pulses.
> - Use a timer interrupt to generate the extra 1-baud delay between characters. The interrupts can be enabled for the same timer that was used to generate the baud clock, and the timer can be slowed down so that one cycle is equal to the delay length needed.
> - Use serial ports A and B, which have synchronous capability, to send a character in synchronous mode (output Tx disabled). The synchronous character is sent at a baud rate 8 times greater than the asynchronous baud rate, giving an additional baud time. For this to work, the pin used for the synchronous clock out (port B bits 0 or 1) must either be unconnected or connected to something that can tolerate a burst of 8 clock pulses.

> #### 12.7.6 Supporting 9th Bit Communication Protocols

> This section describes how 9th bit communication protocols work. 9th bit communication protocols are supported by processors such as the 8051 and the Z180, and by companies such as Cimentrics Technology. The data bytes have an extra 9th bit appended where a parity bit would normally be placed. Requests from the network master to one of its slaves consist of a frame of bytes—the first byte has the 9th bit set to "1" (as the signal is observed at the Tx pin of the processor) and the following bytes have the 9th bit set to "0." The first byte is identified as the address byte, which specifies the slave unit where the message is directed. This enables a slave to find the start of a message, which is the byte with the 9th bit set, and to determine if the message is directed to it. If the message is directed to a particular slave, the slave will then read the characters in the rest of the message; otherwise the slave will continue to scan for a start of message character containing its address.

> Normally the 9th bit is set to "1" only on the first byte of a request transmitted by the network master. The subsequent bytes and the slave replies have the 9th bit set to zero. Since the majority of the traffic has a 9th bit set low, it is only necessary to stretch the stop bit for the first bytes or address bytes. This can be done without sacrificing performance by sending a dummy character (transmitter disconnected) after the address byte.

> Some microprocessor serial ports have a "wake up" mode of operation. In this mode, characters without the 9th bit set to "1" are ignored, and no interrupt is generated. When the start of a frame is detected, an interrupt takes place on that byte. If the byte contains the address of the slave, then the "wake up" mode is turned off so that the remaining characters in the frame can be read. This scheme reduces the overhead associated with messages directed to other slaves, but it does not really help with the worst-case load. In most cases, the worst-case compute load is the governing factor for embedded systems. In addition, it is quite easy for the interrupt driver to dismiss characters not directed to the system. For these reasons, the "wake up" mode was not implemented for the Rabbit.

> The 9th bit protocols suffer from a major problem that the IBM-PC uarts can support the 9th bit only by using special drivers.

> #### 12.7.7 Rabbit-Only Master/Slave Protocol

> If only Rabbit microprocessors are connected, the 9th bit low can be set on the address byte, and the remaining bytes can be transmitted in the normal 8-bit mode. This is more efficient than other 9th bit protocols because only the first byte requires 11 baud times; the remaining bytes are transmitted in 10 baud times.

> #### 12.7.8 Data Framing/Modbus

> Some protocols, for example, Modbus, depend on a gap in the data frame to detect the beginning of the next frame. The 9th bit protocol is another way to detect the start of a data frame.

> The Modbus protocol requires that data frames begin with a minimum 3.5-character quiet time. The receiver uses this 3.5-character gap to detect the start of a frame. In order for the receiving interrupt service routine to detect this gap, it is suggested that dummy characters be transmitted to help detect the gap. This can be done in the following manner. The transmitter starts transmitting dummy characters when the first character interrupt is received. Each time there is an interrupt, either receiver data register full or transmitter data register empty, a dummy character is transmitted if the transmitter data register is empty. Although the transmitter and receiver operate at approximately the same baud rate, there can be a difference of up to about 5% between their baud rates. Thus the receiver full and transmitter empty interrupts will become out of phase with each other, assuming that the remote station transmits without gaps between characters. A counter is zeroed each time a character is received, and the counter is incremented each time a character is transmitted. If this counter holds (n), this indicates that a gap has been detected in the frame; the length of the gap is (n - 1) to (n) characters. The start of frame could be marked by (n) reaching 3, indicating that the existence of a gap at least two characters long.

Rabbit Semiconductor http://www.rabbitsemiconductor.com Voice: (530) 757-8400 FAX: (530) 757-8402 sales@rabbitsemiconductor.com