the uart alternative l.
Download
Skip this Video
Loading SlideShow in 5 Seconds..
The UART alternative PowerPoint Presentation
Download Presentation
The UART alternative

Loading in 2 Seconds...

play fullscreen
1 / 31

The UART alternative - PowerPoint PPT Presentation


  • 207 Views
  • Uploaded on

The UART alternative. Substituting input from our PC’s serial-port for local keystrokes when we do ‘single-stepping’ . Problem background.

loader
I am the owner, or an agent authorized to act on behalf of the owner, of the copyrighted work described.
capcha
Download Presentation

PowerPoint Slideshow about 'The UART alternative' - hinda


An Image/Link below is provided (as is) to download presentation

Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author.While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server.


- - - - - - - - - - - - - - - - - - - - - - - - - - E N D - - - - - - - - - - - - - - - - - - - - - - - - - -
Presentation Transcript
the uart alternative

The UART alternative

Substituting input from our PC’s serial-port for local keystrokes when we do ‘single-stepping’

problem background
Problem background
  • Last time we saw how the x86’s trap-flag and debug-breakpoint registers could be used to support ‘single-stepping’ through program-code, to help us diagnose ‘bugs’
  • But a conflict arises when we attempt to debug code that handles keyboard-input (as in the ‘isrKBD’ routine for Project 2)
  • Our debugger also uses keyboard input!
use another control device
Use another control device?
  • To circumvent the contention for keyboard control, we ask: can some other peripheral device substitute for our PC’s keyboard as a convenient ‘debugger-input’ source?
  • Our classroom and CS Lab machines offer us a way to utilize their serial ports as an alternative device-interface for doing this type of debugger ‘single-stepping’ task
kudlick classroom
Kudlick Classroom

08

09

10

15

16

17

18

19

20

28

29

30

04

05

06

07

11

12

13

14

24

25

26

27

01

02

03

21

22

23

lectern

Indicates a “null-modem” PC-to-PC serial cable connection

pc to pc communications
PC-to-PC communications

student

workstation

student

workstation

KVM cable

KVM cable

rackmount

PC system

rackmount

PC system

‘null-modem’ serial cable

ethernet cables

using echo and cat
Using ‘echo’ and ‘cat’
  • Our device-driver module (named ‘uart.c’) is intended to allow unprivileged programs that are running on a pair of adjacent PCs to communicate via a “null-modem” cable

Transmitting…

Receiving…

$ echo Hello > /dev/uart

$ _

$ cat /dev/uart

Hello _

instructions in isrdbg
Instructions in ‘isrDBG’
  • Our ‘usedebug.s’ used these instructions to support user-control of ‘single-stepping’

isrDBG: .code32 # Our trap-handler for Debug Exceptions (interrupt-0x01)

# now await the ‘release’ of a user’s keypress

kbwait:

in $0x64, %al # poll keyboard-controller status

test $0x01, %al # a new scancode has arrived?

jz kbwait # no, continue polling controller

in $0x60, %al # else input the new scancode

test $0x80, %al # was it a key being released?

jz kbwait # no, wait for a keypress ‘break’

uart s line status
UART’s line-status
  • The PC’s 16550 serial-UART interface has a ‘status’ port and a ‘data’ port that behave in a manner that’s similar to those ports in the keyboard controller, so we can replace instructions in our ‘isrDBG’ procedure that accessed keyboard-controller ports with instructions that access the UART’s ports
  • This avoids ‘contention’ for the keyboard!
how to program the uart
How to program the UART?
  • Universal Asynchronous Receiver-Transmitter
  • Software controls the UART’s operations by accessing several registers, using the x86 processor’s ‘in’ and ‘out’ instructions

See our CS630 course website at:

<http://cs.usfca.edu/~cruse/cs630f08>

for links to the UART manufacturer’s documentation

and to an in-depth online programming tutorial

the 16550 uart registers
The 16550 UART registers

Base+0

Divisor Latch Register

16-bits (R/W)

Base+0

Transmit Data Register

8-bits (Write-only)

Base+0

Received Data Register

8-bits (Read-only)

Base+1

Interrupt Enable Register

8-bits (Read/Write)

Base+2

Interrupt Identification Register

8-bits (Read-only)

Base+2

FIFO Control Register

8-bits (Write-only)

Base+3

Line Control Register

8-bits (Read/Write)

Base+4

Modem Control Register

8-bits (Read/Write)

Base+5

Line Status Register

8-bits (Read-only)

Base+6

Modem Status Register

8-bits (Read-only)

Base+7

Scratch Pad Register

8-bits (Read/Write)

uart s i o port interface
UART’s I/O-port interface

The PC uses eight consecutive I/O-ports to access the UART’s registers

0x03F8 0x03F9 0x03FA 0x03FB 0x03FC 0x03FD 0x03FE 0x03FF

RxD/TxD

IER

IIR/FCR

LCR

MCR

LSR

MSR

SCR

interrupt

enable

register

line

status

register

modem

status

register

line

control

register

modem

control

register

receive buffer register and

transmitter holding register

(also Divisor Latch register)

scratchpad

register

interrupt identification register

and FIFO control register

comparing status ports
Comparing ‘STATUS’ ports

Keyboard-controller’s status-register (i/o-port 0x64)

7 6 5 4 3 2 1 0

Parity

error

Timeout

error

Data is

from

Mouse

Keyboard

locked

Last byte

went to

0x64

System

initialized

Input

Buffer

Full

Output

Buffer

Full

Serial-UART’s line-status register (i/o-port 0x03FD)

7 6 5 4 3 2 1 0

Error in

Rx FIFO

Transmitter

idle

THR

empty

Break

interrupt

Framing

error

Parity

error

Overrun

error

Received

Data

Ready

changes to isrdbg
Changes to ‘isrDBG’

keyboard controls single-stepping

serial-UART controls single-stepping

isrDBG:

kbwait: # poll for OUTB==1

in $0x64, %al

test $0x01, %al

jz kbwait

# input new scancode

in $0x60, %al

# ignore ‘make’ codes

test $0x80, %al

jz kbwait

isrDBG:

inwait: # poll for RDR==1

mov $0x03FD, %dx

in %dx, %al

test $0x01, %al

jz inwait

# input new data-byte

mov $0x03F8, %dx

in %dx, %al

# send back a reply

mov $’#’, %al

out %al, %dx

using a linux application
Using a Linux application
  • To control our debugger from another PC, we’ve written an application-program that runs under Linux, and it uses our ‘uart.c’ device-driver to circumvent privilege-level restrictions that Linux imposes on access to i/o-ports by code which runs in ‘ring3’
  • Our application is named ‘kb2cable.cpp’
  • It also illustrates use of ‘i/o multiplexing’
slide15

Linux Kernel Modules

Linux allows us to write our own

installable kernel modules

and add them to a running system

Runs in ring3

application

Runs in ring0

device-driver

module

call

ret

ret

call

syscall

standard

“runtime”

libraries

Operating System

kernel

sysret

user space

kernel space

slide16

Linux char-driver components

Device-driver LKM layout

module’s ‘payload’

is a collection of

callback-functions

having prescribed

prototypes

function

function

function

AND

a ‘package’ of

function-pointers

fops

. . .

the usual pair of

module-administration

functions

init

registers the ‘fops’

exit

unregisters the ‘fops’

write and read
‘write()’ and ‘read()’
  • Obviously your driver-module’s ‘payload’ will have to include ‘methods’ (functions) which perform the ‘write()’ and ‘read()’ operations that applications will invoke
  • You may decide your driver needs also to implement certain additional ‘methods’
  • For example, to support ‘i/o multiplexing’ our driver needed to implement ‘poll()’
uart initialization
UART initialization
  • For two PC’s to communicate via the serial null-modem cable, their UART’s must be configured to use identical baudrates and data-formats (i.e., 115200 bps, 8-N-1)
  • Our ‘uart.c’ driver performs this essential configuration in its ‘module_init()’ function
  • Our ‘remotedb.s’ application does it in an extra ‘real-mode’ subroutine we’ve added
the sequence of steps
The sequence of steps

(steps are described below in pseudo-code)

# initializing the UART communication parameters for 115200 bps, 8-N-1

outb 0x00, UART_BASE+1 # Interrupt Enable register

outb 0xC7, UART_BASE+2 # FIFO Control register

outb 0x83, UART_BASE+3 # Line Control (DLAB=1)

outw 0x0001, UART_BASE+0 # Divisor Latch register

outb 0x03, UART_BASE+3 # Line Control (DLAB=0)

outb 0x03, UART_BASE+4 # Modem Control

l

inb UART_BASE+6 # Modem Status

inb UART_BASE+5 # Line Status

inb UART_BASE+0 # Received Data

inb UART_BASE+2 # Interrupt Identification

the i o multiplexing problem
The i/o-multiplexing problem
  • Normally when an application ‘reads’ from a device-file, that process will ‘sleep’ until some data is available from that device
  • So if data becomes available on another device, it will not get processed because the application is ‘blocked’ from being given any CPU time by the OS scheduler
  • This would spoil our ‘kb2cable’ application
read causes blocking
‘read()’ causes ‘blocking’

‘kb2cable’

application

Keyboard

read

write

Serial UART

write

read

Whichever device this application attempts to read from, it

will get ‘blocked’ until that device has some data to deliver

do multiprocessing
Do multiprocessing?
  • One idea for getting around this ‘blocking’ problem would be to just use the ‘fork()’ system-call to create separate processes for reading from the different device-files
  • Each process can sleep, and whichever process receives any new data will be awakened and scheduled for execution
  • No changes needed to device-driver code
different processes do read
Different processes do ‘read()’

‘kb2cable’

parent- process

write

read

Keyboard

Serial UART

‘kb2cable’

child-process

read

write

Using multiple processes can overcome the ‘blocking-read’

problem, but complicates the code for program termination

non blocking read
Non-blocking ‘read’
  • It is possible for the application to request ‘non-blocking’ read-operations – i.e., any ‘read()’ calls will immediately return with 0 as return-value in case no data is available
  • The standard-input device-driver already has support for this non-blocking option, and it can be easily added to the ‘read()’ function in our serial UART’s device driver
driver code modification
Driver-code modification

ssize_t my_read( struct file *file, char *buf, size_t len, loff_t *pos )

{

static int rxhead = 0;

// in case no new data has been received, then either

// return immediately if non-blocking mode is in effect

// or else sleep until some new data arrives (or until

// the user hits <CONTROL>-C to cancel execution)

if ( rxhead == ioread32( io + E1000_RDH ) {

if ( file->f_flags & O_NONBLOCK ) return 0;

if ( wait_event_interruptible( wq_recv,

inb( UART_LINE_STATUS ) & 0x01 )

return –EINTR;

}

uses busy waiting loop
Uses ‘busy-waiting’ loop

‘kb2cable’

application

Keyboard

read

write

write

Serial UART

read

Using the ‘nonblocking-read’ option overcomes the problem

of a sleeping task, but it wastefully consumes the CPU time

the elegant solution
The ‘elegant’ solution
  • The ‘select()’ system-call provides a very general scheme for doing i/o-multiplexing in a manner that avoids wasting CPU time or making the program-code complicated
  • But it does require adding an extra driver ‘method’ – the so-called ‘poll()’ function
the select arguments
The ‘select()’ arguments
  • Using ‘select()’ requires an application to setup an ‘fd_set’ object, which defines the set of file-descriptors whose activity needs to be monitored by the Linux kernel (in our ‘kb2cable’ application this would be just the two device-files’ handles (the keyboard and the serial UART)
  • This ‘fd_set’ object becomes an argument
using select in kb2cable
Using ‘select()’ in ‘kb2cable’

int kbd = STDIN_FILENO; // keyboard ID

int uart = open( “/dev/uart”, O_RDWR ); // device-file ID

fd_set permset; // create an ‘fd_set’ object

FD_ZERO( &permset ); // initialize it to ‘empty’

FD_SET( kbd, &permset ); // add keyboard to set

FD_SET( uart, &permset ); // and add the nic to set

while (1) {

fd_set readset = permset;

if ( select( 1+uart, &readset, NULL, NULL, NULL ) < 0 ) break;

if ( FD_ISSET( kbd, &readset ) ) { /* process keyboard input */ }

if ( FD_ISSET( uart, &readset ) ) { /* process network input */ }

}

how it works
How it works
  • The ‘readset’ argument to the ‘select()’ system-call lets the kernel know which device-drivers should have their ‘poll()’ method invoked
  • Then each device-driver’s ‘poll()’ method will perform a test to determine if any new data is ready to be read from that device
  • So the application calls ‘read()’ only when a device is ready with data immediately!
in class demo
In-class demo
  • As a proof-of-concept demonstration, we adding a “trivial” Interrupt Service Routine for keyboard interrupts to our ‘remotedb.s’ program (we called it ‘addkbisr.s’)
  • Then we used our ‘kb2cable’ application running on an adjacent Linux machine to do ‘single-stepping’ through ‘linuxapp.o’ -- and through the added ‘isrKBD’ handler