Hello, dear friend, you can consult us at any time if you have any questions, add WeChat: daixieit

EEE8087 4W Rev. 1.3

Real Time Embedded Systems

Worksheet 4. The Time-Slicing Structure

This week we start work on the central components of an elementary real-time operating system - we will call it a 'runtime system' - that divides the processor's time between separate user tasks.    These tasks will need to communicate with the system, and will request its services by means of a 'software interrupt'.

Implementation of Software Interrupts

A software interrupt is known as a 'trap'. It causes the processor to respond in a very similar way as it does to a hardware interrupt, and so allows system calls from the user program and interrupts      from hardware devices to enter the operating system in a consistent way.

There are 16 trap instructions available, numbered 0 to 15, and written

trap

#0

...

trap

#15

Each of the 16 trap instructions may have its own interrupt service routine (ISR). After pushing the   PC and SR, the processor then accesses a table in low memory, at address 80H. As for the hardware interrupts, the table contains a 4-byte value corresponding to the address of the ISR for each software interrupt. Vectors for the two types of interrupt will normally be combined into a single block of code.

;interrupt vectors

org

hvec1  dc.l

hvec2  dc.l

org

svec0  dc.l

svec1  dc.l

$64

hisr1

hisr2

$80

sisr0

sisr1

;origin 64H

;address of hardware ISR 1

; ... etc

;origin 80H

;address of software ISR 0

; ... etc

Controlling Interrupts

There is, however, an important difference between hardware and software interrupts. Hardware interrupts are in order of priority, with 7 being the highest priority and 1 the lowest. If two hardware  interrupts occur at the same time, then the one at the higher priority will be accepted and the other  one will be kept waiting until the first ISR has completed. If a hardware interrupt occurs shortly after another one, but while the ISR for the first interrupt is still in execution, then the processor will again compare the priorities of the two interrupts. If the new interrupt is of a higher priority, then it will interrupt the lower priority ISR. If the new interrupt is at a lower priority than the currently executing ISR, it will be kept waiting until that ISR completes.

Software interrupts do not behave in an analogous way. Since the processor can only execute one instruction at a time, it would be impossible for two software interrupts to occur at the same time,     and unless a programmer includes a trap instruction within an ISR, there will also be no occasions  on which a trap takes place during the processing of another trap. There is therefore no point in prioritising the software interrupts, and all 16 are at the same priority. There is, however, the question of the relative priority of the hardware and software interrupts. What if a hardware interrupt is raised at the same time as the processor is executing a software interrupt instruction? This is handled by assigning all the software interrupts to priority level 0. Processing of a software interrupt is therefore interruptible by a hardware interrupt at any of the priority levels 1 to 7.

Within your system, however, regardless of the type of interrupt being processed, you will want to  prevent the acceptance of any other interrupt. Your system will therefore be completely uninterruptible. Once entered, it will always run to completion and then return to the user task that  was running when the interrupt was raised. You will therefore need to disable interrupt acceptance, the procedure for which is explained now.

Using the simulator, examine the 16-bit status register. Bits 8, 9 and 10 (labelled 'INT') hold a 3-bit   value that represents the interrupt priority mask. When an interrupt is accepted, the mask is set to   the priority level of that interrupt. A hardware interrupt will only be accepted if its priority is greater    than the current setting in the mask. Normally, the mask is set to 000 (decimal 0) thereby allowing   the acceptance of any hardware interrupt. However, it will remain at zero during its response to a     software interrupt, since that is the priority of these interrupts, and will thereby allow the hardware to interrupt the software ISR. If you wish to prevent this, then the following instruction, placed at the     very start of a software ISR, sets the mask to binary 111 (decimal 7). Any hardware interrupts will    now be disabled, and held pending until the mask is returned to zero.

or      #$0700,sr          ;disable hardware interrupts

The status register will have been automatically saved on the stack at the start of the interrupt      servicing. On execution of the 'return from exception' instruction (RTE), it will be restored, and the mask reset to the zero value that it held previously, thereby allowing the acceptance of any          hardware interrupt that might have been raised in the meantime and is currently pending.

If you want to enable hardware interrupts at any other time, the following instruction will set the mask to zero.

and   #$f8ff,sr             ;enable hardware interrupts*

Practical Work

Assessment question

Work in pairs on this question, and keep a copy of your answer. You will need to submit your software, including the test programmes that you use to demonstrate it, and your documentation. These items should be placed into a single zipped file, and uploaded to a Canvas submission point to be advised. The submission deadline is 2pm on Friday 20th January, 2023.

The work consists of writing a basic time-slicing system, along the lines of the one discussed in the  lecture. It should allow the execution of several concurrent user tasks, with support for task scheduling and inter-task communication. Test your system, and using short test programmes of the type used in the lectures, show clearly that each function is working. Demonstrate the operation of   mutual exclusion and task synchronisation. Write a short document describing how to use the system, stating the maximum number of instructions executed by each of the functions.

The system runs in the foreground, and is entered following either a timer interrupt or a software interrupt from one of the tasks requesting service. Another hardware interrupt will be added later.

The following system calls should be supported by means of software interrupts. They can either each be allocated to a separate trap number, or (as in the demonstration system) they can all be called on the same trap, with one of the registers used to hold a value identifying the requested  function. Some of the calls also require additional parameters in other registers.

1. Create task

Function:     Parameters:

2. Delete task

Function:     Parameters:

3. Wait mutex

Function:

Parameters:

4. Signal mutex

Function:

Parameters:

5. Initialise mutex

Function:     Parameters:

A currently  unused TCB is marked as in use and set up for a new task .     It is placed on the ready list. The requesting task remains on the ready list.

The start address of the new task,

The address of its top-of-stack .

The requesting task is terminated, its TCB is removed from the list and marked as unused.

None.

If the mutex variable is one, it is set to zero and the requesting task is placed back onto the ready list. If the mutex is zero, the task is placed onto the wait list, and subsequently transferred back to the ready list when another task    executes a signal mutex.

None.

If the mutex variable is zero, and a task is waiting on the mutex, then that task            is transferred to the ready list and the mutex remains at zero. If the mutex is zero and no task is waiting, the mutex is set to one. In either case, the requesting task remains on the ready list.

None.

The mutex is set to the value 0 or 1, as specified in the parameter.

0 or 1.

When this is working, extend the system with the following functions. Function 6 will require the use of an additional interrupt at level 2, and you will need to consider the implications of this for the

correct working of the system.

6. Wait I/O:

Function:

Parameters:

7. Wait time

Function:

Parameters:

The requesting task is placed onto the wait list, until an interrupt signifies completion of an I/O operation, when the task is transferred back to the ready list.

None.

The requesting task is placed onto the wait list until the passage of the number of timer interrupts specified in the parameter, when it is transferred back to the ready list.

Number of timer intervals to wait.

An additional function is executed automatically at start-up, or if the user presses the reset button.

System reset

Function:

The system is initialised: all internal variables are reset, and each TCB is marked as unused.  A TCB for task T0 is then created, and T0 becomes the running task .


The system assumes that a default user task, T0, is present. The system runs this task immediately after a reset. It will need to be located at a predetermined address, which will be coded into the       reset function.

Your system should be robust, and deal with errors in an intelligent way. For example, what if the user tries to create more tasks than there are available TCBs?

The Demonstration System


A system was demonstrated during the lecture. Excerpts of code from it are reproduced below. These can be used in your own systems; unchanged, modified, or rewritten as you wish.

The system recognises a hardware interrupt at level 1 from the timer. It also allows system calls by means of software interrupts, all of which have been allocated to trap 0. These system calls are     programmed by placing a value that identifies the requested function into data register 0, and any  other parameters as required by each of the individual functions in registers D1 onwards. For         example, system call 1 is used to create a new task. Suppose that this new task is called T1, and  that its top-of-stack is to be located at address 6000H. It would be programmed as follows.

move.l     #1,d0      ;set id in d0

move.l     #t1,d1     ;set address of new task in d1

move.l     #$6000,d2  ;set stack address in d2

trap       #0         ;call system

The main data structure used in this system is a list of task control blocks (TCBs). Each TCB        represents the state of one of the tasks. It contains a copy of all that task's registers, together with some items of control information including a flag that indicates whether the TCB is in use.

At any time, each of the tasks will be in one of three states: it will be the currently running task, it will be ready to run when its turn comes up, or it will be unable to run because it is waiting for the           occurrence of some event, which could be a signal operation on a mutex, the expiry of a time           interval, or an I/O interrupt.

At initialisation, all the TCBs in the list are marked as unused. As each new task is started, one of    the unused TCBs is allocated for it and marked as used. These TCBs are organised into two linked  lists, in which each element contains a pointer to the next element. These lists are called 'ready' and 'waiting'. Two more data items consist of pointers to the first element in each list. The pointer            rdytcb holds the address of the first element in the list of ready TCBs. The first element in this list  is the task that actually is running. The linkage in this list is circular, that is, the last entry points back to the first, so making it easy to access each TCB in rotation. The pointer wttcb holds the address  of the first element in the list of TCBs that are waiting. There is no need to access elements of this   list in rotation, so the last element in this list has its pointer set to zero.


0                  1                  2                  3                  4                  5                  6                  7


N                  N                                      N                  N                                      N                  0

rdytcb


wttcb

The example above shows a list of 8 elements, each of which has a pointer, labelled N, to the next element. Elements 4, 6, 0 and 1 are on the ready list, with element 4 being the TCB for the running task. Elements 3 and 7 are on the waiting list, and elements 2 and 5 are unused.

The system is organised into the following sections.

Data definitions and equates

org  0

Interrupt vectors

Executable code

System reset

First-level interrupt handler

Service routines

Scheduler

Dispatcher

Data storage

Default user task T0

Data definitions

Each TCB represents the state of one of the current tasks, and is defined as follows.

tcb

org

0

;tcb record

tcbd0

ds.l

1

; D register save

tcbd1

ds.l

1

tcbd2

ds.l

1

tcbd3

ds.l

1

tcbd4

ds.l

1

tcbd5

ds.l

1

tcbd6

ds.l

1

tcbd7

ds.l

1

tcba0

ds.l

1

; A register save

tcba1

ds.l

1

tcba2

ds.l

1

tcba3

ds.l

1

tcba4

ds.l

1

tcba5

ds.l

1

tcba6

ds.l

1

tcba7

ds.l

1

tcbsr

ds.l

1

; SR (status reg) save

tcbpc

ds.l

1

; PC save

tcbnext

ds.l

1

; link to next record

tcbused

ds.l

ds.l

ds.l

1

1

1

; record in use flag ; other fields as required ;

tcblen

equ

*

; length of tcb record in bytes

Data storage

Storage for a list of TCBs is defined as in the first line below. The constant ntcb represents the number of TCBs in the list, and should be set up as an equate. Other variables are described   throughout these notes.

tcblst

ds.b

tcblen*ntcb

;tcb list (length x no of tcbs)

rdytcb

ds.l

1

;^