Download presentation
Presentation is loading. Please wait.
1
Transmitter Interrupts
Review of Receiver Interrupts How to Handle Transmitter Interrupts? Code to fix TX error Critical Regions Text: Tanenbaum 2.3.2
2
Review of Interrupts Com Port Bus
3
Review of x86 Receiver Interrupts
UART receives a character and signals an interrupt on a bus line. Programmable Interrupt Controller(PIC) detects the signal. If no pending interrupts are pending, it services the interrupt immediately. If another one is in progress or a higher priority one is pending, the device is ignored. It continues to assert the interrupt signal until it is serviced. To handle the interrupt, the controller puts an interrupt vector number (e.g 0x23 for COM2) on the data bus and asserts a signal (INTR) to interrupt the CPU.
4
x86 Receiver Interrupts (cont’d)
CPU stops what it is doing and starts doing something else. CPU uses the interrupt vector number to index the IDT (interrupt descriptor table) and find the interrupt vector (i.e. address of the interrupt service routine) CPU runs the service routine which includes writing a certain value(EOI) to the interrupt controller’s I/O port to ack the interrupt
5
Example Program for COM2 receiver interrupts
Look at Steps 1-5: initialization steps Step 6: wait forever loop Steps 10-13: shut down interrupts Steps 7-9: interrupt handler, need the envelope routine pic_end_int(), pic_enable_irq(), pic_disable_irq() are functions implemented in the SAPC library in directory $pclibsrc Look at $pcinc for include files
6
How About Transmitter Interrupts?
Details on programming UART registers slide 14 of 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
7
Transmitter 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?
8
How to Distinguish the Interrupts?
One interrupt service routine to perform both Tx and Rx functions Check the UART’s 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
9
What 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.
10
The 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.
11
Code Modifications to fix VM error
The virtual machine does not emulate exactly all the hardware functions For the transmitter, you have to constantly kick start the transmitter interrupt to generate more transmit interrupts, e.g. in the transmitter ISR code: c = this_buffer[cursor++]; /* get next character from app */ outpt(COM1_BASE+UART_IER,0); /* disable all interrupts */ outpt(COM1_BASE+UART_IER, UART_IER_THRI); /* kickstart TX interrupt */ outpt(COM1_BASE+UART_TX, c); /* output the character */
12
An 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
13
Timeline Representation
Outb: ISR: ttywrite: setup loop of enq’s testio: ttywrite rest of testio Note: 1. Still have a busy loop in ttywrite, i.e. loop of enq’s 2. OK for hw1. Fix it later using a scheduler 3. Could have a race condition due to concurrent activities on modifying the queues
14
The Race Condition 2 concurrent activities occur when executing ttywrite ttywrite looping on enqueues intermittent ISR executing a dequeue working with the same queue (tty->tbuf) Interrupt can occur between 2 machine instructions. in ttywrite if (enqueue( &(tty->tbuf), buf[i])) i++; during enqueue function, ISR calling dequeue function can mess up the queue data structure
15
How 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
16
Mutual Exclusion Using Critical Regions
17
Mutual Exclusion with Busy Waiting
Disabling Interrupts Locked Variables Strict Alternation Peterson’s Solution Test and Set Lock (TSL)
18
Turning 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 it: cli(); /* disable interrupts in CPU by setting IF=0 in EFLAGS*/ enqueue(…); /* critical region code */ sti(); /* or set_eflags(save_eflags) to re-enable interrupts */
19
Turning 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);
20
Echoes 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
Similar presentations
© 2024 SlidePlayer.com. Inc.
All rights reserved.