CS644 Polling I/O using the PC COM ports, from C

% more $pcex/echo.c

 

/* echo.c: use low-level i/o to echo console input */

/* build with makefile in $pcex:  make C=echo      */

 

#include <stdio.h>   <---This means the $pcinc/stdio.h

#include <serial.h>   <--- This is $pcinc/serial.h, see below

 

void main()

{

  int console = sys_get_console_dev(); /* find out current sys console */

  int conport;

  int c = 0;

 

  switch (console) {

  case COM1: conport = COM1_BASE;

    break;

  case COM2: conport = COM2_BASE;

    break;

  default: printf("Expected serial port for console, exiting\n");

    return;

  }

 

  while (c != 'q') {

 

    /* "poll" the DR (data-ready) bit until it goes on */

    while ((inpt(conport+UART_LSR)&UART_LSR_DR)==0)

      ;                         /* busy-wait for char */

    c = inpt(conport+UART_RX);

    outpt(conport+UART_TX, c);  /* should be ready */

  }

}

blade63(3)% more $pcinc/serial.h (important parts to get started)

/* serial.h: adapted from Linux serial.h:

...

/* For the PC's use of these UARTs, the base i/o port for each COM device

 * (these are quite standard)

 */

#define COM1_BASE 0x3f8

#define COM2_BASE 0x2f8

#define COM3_BASE 0x3e8

#define COM4_BASE 0x2e8

#define COM1_IRQ 4

#define COM2_IRQ 3

/* the following are not standard, but are valid for 2 boards in use at UMB */

#define COM3_IRQ 15

#define COM4_IRQ 14

 

/* The rest of the file is from Linux's serial.h */

/*

 * These are the UART port assignments, expressed as offsets from the base

 * register.  These assignments should hold for any serial port based on

 * a 8250, 16450, or 16550(A).

 */

#define UART_RX         0       /* In:  Receive buffer (DLAB=0) */

#define UART_TX         0       /* Out: Transmit buffer (DLAB=0) */

#define UART_DLL        0       /* Out: Devisor Latch Low (DLAB=1) */

#define UART_DLM        1       /* Out: Devisor Latch High (DLAB=1) */

#define UART_IER        1       /* Out: Interrupt Enable Register */

#define UART_IIR        2       /* In:  Interrupt ID Register */

#define UART_FCR        2       /* Out: FIFO Control Register */

#define UART_LCR        3       /* Out: Line Control Register */

#define UART_MCR        4       /* Out: Modem Control Register */

#define UART_LSR        5       /* In:  Line Status Register */

#define UART_MSR        6       /* In:  Modem Status Register */

#define UART_SCR        7       /* I/O: Scratch Register */

 

...

/*

 * These are the definitions for the Line Status Register

 */

#define UART_LSR_TEMT   0x40    /* Transmitter empty */

#define UART_LSR_THRE   0x20    /* Transmit-hold-register empty */

#define UART_LSR_BI     0x10    /* Break interrupt indicator */

#define UART_LSR_FE     0x08    /* Frame error indicator */

#define UART_LSR_PE     0x04    /* Parity error indicator */

#define UART_LSR_OE     0x02    /* Overrun error indicator */

#define UART_LSR_DR     0x01    /* Receiver data ready */

...

Compiling, Loading, and Execution:

#define UART_Lblade57(1)% cp $pcex/echo.c .

blade57(2)% cp $pcex/makefile .

blade57(3)% make C=echo

/groups/ulab/bin/i386-gcc -g -Wall -Wno-implicit -Wshadow -I/groups/ulab/pcdev/include -I/groups/ulab

/pcdev/include -c -o echo.opc echo.c

/groups/ulab/bin/i386-ld -N -Ttext 1000e0 -o echo.lnx \

        /groups/ulab/pcdev/lib/startup0.opc /groups/ulab/pcdev/lib/startup.opc \

        echo.opc /groups/ulab/pcdev/lib/libc.a

rm -f syms;/groups/ulab/bin/i386-nm -n echo.lnx>echo.syms;ln -s echo.syms syms

blade57(4)% mtip -f echo.lnx

For command help, type ~?

For help on args, rerun without args

Code starts at 0x100100

Using board # 1

 

Tutor> ~downloading echo.lnx

....Done.

 

Download done, setting EIP to 100100.

Tutor> go 100100

abcqException 3 at EIP=00100110: Breakpoint

Tutor>

Tutor>

Quit handler:

killing process 9341 Leaving board #1

blade57(5)% exit

script done on Tue Mar  2 11:15:00 2010SR_OE     0x02    /* Overrun error indicator */

#define UART_LSR_DR     0x01    /* Receiver data ready */

 

...

ls $pcinc/*.h        Look at all hardware-related header files

/groups/ulab/pcdev/include/cpu.h        /groups/ulab/pcdev/include/pic.h

/groups/ulab/pcdev/include/ctype.h      /groups/ulab/pcdev/include/serial.h

/groups/ulab/pcdev/include/gates.h      /groups/ulab/pcdev/include/stdio.h

/groups/ulab/pcdev/include/lp.h         /groups/ulab/pcdev/include/sysapi.h

/groups/ulab/pcdev/include/mmu.h        /groups/ulab/pcdev/include/timer.h

 

Devices: lp = parallel port, serial = com ports, timer, pic = programmable interrupt controller

CPU related: cpu.h, mmu.h, gates.h

Tutor environment related: stdio.h, sysapi.h, ctype.h