CS444 UART Receiver interrupts.

Look at $pcex/typewr.c:  important points numbered here.

 

/* typewr.c: echo on COM2 using UART receiver interrupts                 */

/* The needed interrupt envelope routines irq3int, etc. are in           */

/*   the library, and sti, cli, pic_enable_irq, etc., are there too.     */

#include <stdio.h>

#include <serial.h>

#include <cpu.h>

#include <pic.h>

 

extern const IntHandler irq3inthand; /* the assembler envelope routine    */

void irq3inthandc(void);  /* the C core int handler, called from envelope */

int done;                       /* global for communication with int hand */

 

/* Note in our enviroment, interrupts are normally enabled in the CPU, so we

   use cli() as necessary even at the very start of the program */

void main()

{

  if (sys_get_console_dev() != COM2)

    printf("Warning: console not COM2, so echos won't show on console\n");

 

  /* init global explicitly, so program works properly on reruns */

  done = 0;

 

  cli();                        /* disable ints while setting them up */  <---(1)

  printf("Calling set_intr_gate (irq = 3, n = 0x23) to arm interrupt...\n");

  set_intr_gate(COM2_IRQ+IRQ_TO_INT_N_SHIFT, &irq3inthand);               <---(2)

 

  printf("Commanding PIC to interrupt CPU for irq 3 (COM2_IRQ)\n");

  pic_enable_irq(COM2_IRQ);                                               <---(3)

 

  printf("enabling receiver interrupts in UART...\n");

  outpt(COM2_BASE+UART_IER, UART_IER_RDI); /* RDI = receiver data int */  <---(4)

  /*  now hardware reg's are all set up, time to allow CPU ints-- */

  sti();                                                                  <---(5)

  printf("...done, entering almost-infinite loop\n");

 

  while (!done)                 /* loop almost forever...*/               <---(6)

    ;

  /* here when user types 'q': shutdown ints we started up */

  cli();                                                                  <---(10)

  pic_disable_irq(COM2_IRQ);    /* done with irq 3 in PIC */              <---(11)

  outpt(COM2_BASE+UART_IER, 0); /* stop UART ints */                      <---(12)

  sti();                        /* but other ints still there */          <---(13)

  return 0;

}

 

/* this is called from irq3inthand, the assembler interrupt envelope routine */

/* that saves the C scratch regs on the stack, restores them after this,  */

/* then does the iret instruction.                                        */

void irq3inthandc(void)

{

  char ch;

 

  pic_end_int();                /* notify PIC that its part is done */    <---(7)

  ch = inpt(COM2_BASE+UART_RX); /* read char (ACKs UART too) */           <---(8)

  if (ch == 'q')

    done = 1;                   /* set global flag to let main know */

  outpt(COM2_BASE+UART_TX,ch); /* echo char (Transmitter should be ready) */

}                                                                         <---(9)

 

 

The Assembly Language Interrupt Handler Envelope

In the following code, the bold lines are the essential ones you should understand.  The others date from 

(old version) Linux and are only needed to guard against bad user-level code.

 

Source is$pclibsrc/irq3.s

 

# like linux SAVE_MOST and RESTORE_MOST macros in irq.h

.text

.globl _irq3inthand

KERNEL_DS = 0x18

 

 

_irq3inthand: cld   # D bit gets restored by iret (this can be dropped)

        push %es    # in case user code changes data segs (this can be dropped)

        push %ds        # (this can be dropped)

        pushl %eax      # save C scratch regs      <---(1) register saves

        pushl %edx

        pushl %ecx

        movl $KERNEL_DS, %edx  # (this can be dropped)

        mov %dx, %ds    # (this can be dropped)

        mov %dx, %es    # (this can be dropped)

        call _irq3inthandc  # call C interrupt handler  <---(2) call into C

        popl %ecx                                  <---(3) register restores

        popl %edx

        popl %eax

        pop %ds         #(this can be dropped)

        pop %es         #(this can be dropped)

        iret                                       <---(4) iret instruction