CS452 - Real-Time Programming - Fall 2010

Lecture 14 - Clock Server, Task Structure

Public Service Announcements

  1. Marked Assignments

The Hardware in the Trains Lab

Interrupt Control Unit (ICU)

Basic Operation

Registers for Basic Operation
Register Name Offset R/W Description
VICxIRQStatus 0x00 R One bit for each interrupt source

1 if interrupt is asserted and not masked

VICxFIQStatus 0x04 R As above, for FIQ
VICxRawIntr 0x08 R As above, not masked
VICxIntSelect 0x0c R/W 0: IRQ, 1: FIQ
VICxIntEnable 0x10 R/W 0: Masked, 1: Enabled
VICxIntEnClear 0x14 W Clears bits in VICxIntEnable
VICxSoftInt 0x18 R/W Asserts interrupt from software
VICxSoftIntClear 0x1c W Clears interrupt from software
VICxProtection 0x20 R/W Bit 0 enables protection from user mode access
VICxVectAddr 0x30 R/W Enables priority hardware

See documentation.

Vectored Operation

Procedure

Initialization

  1. Write kernel entry point into VICxDefVectAddr
  2. If desired write special entry point into VICxVectAddry
  3. When ready to accept interrupts write source and enable into VICxVectCntly

When an interrupt occurs

  1. Read VICxVectAddr to find address
  2. Move result to PC
  3. When service is complete write VICxVectAddr to start priority hardware

Look carefully at what's in 0x18

Register Name Offset R/W Description
VICxVectAddr 0x030 R/W Read: address of vector for highest priority interrupt

Write: service complete, enable priority hardware

VICxDefVectAddr 0x034 R/W Default vector address
VICxVectAddry 0x100+4y R/W Vector address for interrupt y
VICxVectCntly 0x200+4y R/W Control register for interrupt y

Bit[0-4]: interrupt source for interrupt y

Bit[5]: enable vectored interrupt y


Clock Server, Task Structure

How is AwaitEvent Used?

  1. There should (almost) always be a task blocked on AwaitEvent for every interrupt type. Why?
  2. A server cannot call AwaitEvent. Why?
  3. We call the task that calls AwaitEvent a Notifier. Why?
  4. Code for a typical Notifier
    main( ) {
        Tid server;
        int evtType, data;
        Receive( &server, &evtType, ... );
        // Other initialization
        Reply( server, ... );
        FOREVER {
            data = AwaitEvent( evtType );
            Send( server, &data, ... );
        }
    }
  5. Code for a typical server
    main( ) {
        notifier = Create( HIGHEST, ... );
        // other initialization
        Send( notifier, &evtType, ... );
        FOREVER {
            Receive( &requester, &request, ... );
            switch ( request.type ) {
            case NOTIFIER:
                data = request.data;
                Reply( notifier );
                break;
            case CLIENT:
                ...
            }
        }
    }

More About AwaitEvent

Argument

  1. Somewhere there is a list of event types
  2. This is not very portable

Return value

Related to three free choices discussed in last lecture.

Strategies

Strategy 1: Kernel does it all

Strategy 2: Notifier does most of it


Clock Server

Primitives

int Time( )
int Delay( int ticks )
int DelayUntil( int ticks )

Implementation

main( ) {
    notifier = Create( HIGHEST, ... );
    time = 0
    Send( notifier, &evtType, ... );
    FOREVER {
        Receive( &requester, &request, ... );
        switch ( request.type ) {
        case NOTIFIER:
            Reply( notifier, ... )
            time++;
            Check suspended tasks and reply
            break;
        case TIME_REQUEST:
            Reply( requester, time,... )
            break;
        case DELAY_REQUEST: 
            Add requester to list of suspended tasks
            Check suspended tasks and reply
            break;
        }
    }
}

Comments:

  1. You need a common request type, or possibly a union.

Return to: