Title: Transmitter Interrupts
1Transmitter Interrupts
- Reference on Critical RegionsText Tanenbaum
2.3.2
2How to Output Character Strings
- Details on programming UART registers
- slide 14 of http//www.cs.umb.edu/bobw/CS341/Data
Book/c8652.pdf - Use Programmed I/O Set up a loop for the number
of characters in the string check the
transmit-ready(THRE) bit of the LSR Register if
on, write the char to UART_TX register otherwise
, loop - Use Interrupt-driven I/O
3Transmitter Interrupts
- Each interrupt signals readiness to output
another byte of data - The transmitter ISR gives another byte to output
- Issues to consider
- How to distinguish the Tx from Rx interrupts
since they share one interrupt line(e.g. IRQ3 for
COM2)? - what to do when data runs out?
- How to start/restart the Tx interrupt?
4How to Distinguish the Interrupts?
- One interrupt service routine to perform both Tx
and Rx functions - Check the UARTs LSR to see if Data Ready (DR)
bit or the Transmit Holding Register(THRE) bit is
set. Then execute the corresponding function. - Any one of the 3 situations can happen
- Both Tx and Rx interrupts are ready
- Only Tx interrupt is ready
- Only Rx interrupt is ready
5What to Do when Tx Data Runs Out ?
- THRE bit set to 1 when the UART hardware is ready
to accept a new character for transmission. - THRE bit set to 0 after UART_Tx register is
loaded with a new character. - If there is a Tx interrupt, dequeue a character
and output it. - Shut down the Tx interrupt when queue is empty.
- Rx interrupts need to be on continuously. Tx
interrupts go on and off depending on output
availability.
6The Transmitter Strategy
- Set up interrupt gate in IDT, but leave Tx
interrupt off in the UART. - To load a string (n chars) into queue
- 1. Load the first part of the string into the
output buffer (i.e. enqueue the chars until the
queue is full (Qmax)). - 2. Turn Tx interrupt on in the UART_IER.
- 3. While the interrupt is ongoing, loop over the
enqueuing of the rest of the chars. - 4. Return when all chars have been enqueued.
- To output the chars in the queue
- 1. Check if the queue is empty.
- 2. If there are chars, dequeue one and output it
to UART_TX. - 3. If there none, shut down Tx interrupt in the
UART_IER.
7An Example
- write(TTY1, 123456789, 9) with nchar 9 and
Qmax 6 - 1. 123456 put in queue during the setup in
ttywrite - 2. 123 output ,one by one, by ISR
- 3. 789 get loaded in the queue in ttywrite
- 4. ttywrite returns after all nchar in queue
- 5. ttywrite has returned, but 6 chars 456789
are still in the queue. They are outputted one by
one by ISR
8Timeline Representation
Note 1. Still have a busy loop in ttywrite,
i.e. loop of enqs 2. OK for hw1. Fix it later
using a scheduler 3. Could have a race condition
due to concurrent activities on modifying the
queues
9The Race Condition
- 2 concurrent activities occur when executing
ttywrite - ttywrite looping on enqueues
- intermittent ISR executing a dequeue
- working with the same queue (tty-gttbuf)
- Interrupt can occur between 2 machine
instructions. - in ttywrite if (enqueue( (tty-gttbuf),
bufi)) i - during enqueue function, ISR calling dequeue
function can mess up the queue data structure
10How to Avoid the Race Condition
- This part of program is called critical region or
critical section when it accesses shared memory. - Use mutual exclusion to make sure one part of
program is using the shared variable while the
other part is excluded from doing the same thing. - Four conditions to provide mutual exclusion
- No two processes simultaneously in critical
region - No assumptions made about speeds or numbers of
CPUs - No process running outside its critical region
may block another process - No process must wait forever to enter its
critical region
11Mutual Exclusion Using Critical Regions
12Mutual Exclusion with Busy Waiting
- Disabling Interrupts
- Locked Variables
- Strict Alternation
- Petersons Solution
- Test and Set Lock (TSL)
13Turning off Interrupts in ttywrite
- We can turn off interrupts during the execution
of enqueue and turn them on when enqueue is done - How to do itcli() / disable interrupts in
CPU by setting IF0 in EFLAGS/enqueue() /
critical region code /sti() / or
set_eflags(save_eflags) to re-enable interrupts /
14Turning off Interrupts in printf
- Important to turn off interrupts before using
printf - Prevent part of the code to do programmed I/O and
another one doing interrupt-driven I/O using the
Tx of the UART - kprintf() is the printf routine that turns off
interrupts int saved_eflags save_eflags
get_eflags() cli() printf() /
SAPC-library printf uses programmed I/O /
set_eflags(saved_eflags)
15Echoes
- Characters to be echoed are generated in the
input interrupt handler - One copy is enqueued in the input queue and
another in an output echo queue - When the Tx ISR runs, it should look first in the
echo queue. The user sees the echo as soon as
possible