You are on page 1of 128

OSE Epsilon

ARM Kernel

ARM Kernel

Users Guide

Enea Embedded Technology

Copyright
Copyright 2005 by Enea Embedded Technology. All rights reserved. No part of this publication may be reproduced, transmitted, stored in a retrieval system, or translated into any language or computer language, in any form or by any means, electronic, mechanical, optical, chemical or otherwise, without the prior written permission of Enea Embedded Technology. If, however, your only means of access is electronic, permission to print one paper hardcopy is hereby granted. The software described in this document is furnished under a licence agreement or a non-disclosure agreement. The software may be used or copied only in accordance with terms of agreement.

Disclaimer
Enea Embedded Technology makes no representations or warranties with respect to the contents hereof and specifically disclaims any implied warranties of merchantability or fitness for any particular purpose. Further, Enea Embedded Technology reserves the right to revise this publication and to make changes from time to time in the contents hereof without obligation to Enea Embedded Technology to notify any person of such revision or changes.

ARM Kernel

Trademarks
OSE is a registered trademark of Enea Embedded Technology

Last modified: 20 December 2005

EArmKrnUG4.6
OSE Epsilon/ ARM Kernel

Contents
1 Introduction 2 Introduction to OSE
2.1 Definition of an RTOS 10 2.2 Purpose of an RTOS 10 2.3 Real-Time Operating System Tasks 10 2.3.1 Resource Management 11 2.3.2 Time Management 11 2.3.3 Interprocess Communication 11 2.3.4 Speed Considerations 12 2.4 OSE Design Benefits 12 2.5 Concurrent Processes 12 2.5.1 Process States 13 2.5.2 Priority Based Process Scheduling 14 2.5.3 Round-Robin Process Scheduling 14 2.6 Process Categories in OSE 16 2.7 Process Types in OSE 16 2.7.1 Prioritized Processes 17 2.7.2 Background Processes 17 2.7.3 Interrupt Processes 17 2.7.4 Interrupt Performance 18 2.7.5 Timer Interrupt Processes 19 2.8 OSE Operating System Tools 19 2.8.1 Messages 20 2.8.1.1 Message Passing Through Mailboxes 20 2.8.1.2 Direct Message Passing in OSE 21 2.8.2 Fast Semaphores 22 2.8.3 Semaphores 23

7 9

ARM Kernel

3 Getting Started
3.1 Example System Description 26 3.2 Step by Step Tutorial 28 3.2.1 Equipment 29 3.2.2 Preparation 30 3.2.3 OSE Configuration 30 3.2.4 Getting the System Files 33 3.2.5 Getting Specific Drivers 33 3.2.6 Getting the Example Source Files 34 3.2.7 Building the System with ARM ADS 35 3.2.8 Building the System with IAR EWB 36 3.2.9 Building the System with GNU GCC 37 3.2.10 Running the System without OSE Illuminator 40 3.2.11 Running the System with OSE Illuminator 40 3.2.12 Debugging 42 3.2.12.1 Epsilon Debug Server 42 3.2.12.2 Debugging with OSE Illuminator 42

25

Users Guide / 4.6

Contents 3

4 Configuring OSE Epsilon for ARM


4.1 C Compiler 45 4.2 Target Name 46 4.3 CPU Type 47 4.4 Memory Model 48 4.5 Debug Option 49 4.6 Buffer Check Option 50 4.7 Stack Check Option 51 4.8 Option Debugger 52 4.9 Option Conditional Halt 53 4.10 Option Dispatcher in RAM 54 4.11 Pool Size 55 4.12 Buffer Sizes 56 4.13 Interrupt Stack 57 4.14 Temporary Stack 58 4.15 Error Handler 59 4.16 Start Handlers 60 4.17 Swap Handler 61 4.18 Send Handler 62 4.19 Receive Handler 63 4.20 Power On Handler 64 4.21 Power Off Handler 65 4.22 Idle Handler 68 4.23 Fast interrupts as IRQ:s 69 4.24 Interrupt Processes 70 4.25 Timer Interrupt Processes 71 4.26 Prioritized Processes 72 4.27 Link Handler Processes 73 4.28 Background Processes 74 4.29 Enable Wake Up 75

43

ARM Kernel

5 Building a System
5.1 5.2 5.3 5.4 5.5 System Files 79 Configuration 79 Configuration Utility 79 Illuminator System Level Debugger 79 Assembly-Time Errors 80

77

6 System Design
6.1 System Creation Cycle 83 6.2 Processes 84 6.2.1 Prioritized Processes 85 6.2.2 Background Processes 86 6.2.3 Interrupt Processes 87 6.2.4 Timer Interrupt Processes 88 6.2.5 Selecting Process Type 89 6.2.6 Process Include Files 90 6.2.7 Process Declarations in C 91 6.2.7.1 Prioritized and Background Processes 91 6.2.7.2 Interrupt and Timer-Interrupt Processes 91 6.2.8 Process Declarations in Assembler 92 4 Contents

81

Users Guide / 4.6

ARM Kernel

6.2.8.1 Prioritized and Background Processes 92 6.2.8.2 Interrupt and Timer-Interrupt Processes 92 6.2.9 Process Design Rules 93 6.3 Starting and Stopping Processes 93 6.4 Signals 94 6.4.1 Using Signals In Processes 95 6.4.2 Buffer Transfer 96 6.5 Fast Semaphores 97 6.6 Semaphores 97 6.7 Memory Utilisation 98 6.7.1 Global Variables 98 6.7.2 Memory Requirements 99 6.7.2.1 Memory Used By the Buffer Pool 99 6.7.2.2 Memory Required By Stacks 99 6.7.2.3 Memory requirements 100 6.8 Speed Considerations 102 6.8.1 Task Switch Performance 102 6.8.2 Timer-Interrupt Process Frequency 102 6.8.3 Signal Transmission Performance 103 6.8.4 Interrupt Handling Performance 103 6.8.5 Time Consumption of Other Functions 103 6.9 System Start 104 6.10 Writing the Interrupt Handler 104 6.10.1 Sample Interrupt Handler 104 6.10.2 Nested OSE Interrupts 104 6.10.3 Interrupt Enable/Disable Functions 105 6.11 Writing a Link Handler 106 6.11.1 Multiple Physical Links 107 6.11.2 Buffer Structure 107 6.11.3 Reformatting Buffers 107 6.12 Writing an Error Handler 108 6.12.1 Error Information 108 6.12.2 Continuing After an Error 110

7 Illuminator Debugger
7.1 Serial Line Connection 112 7.1.1 System Configuration 113 7.1.2 Testing the Target Debug Connection 114 7.1.3 Epsilon Debug Server 115 7.2 Symbolic Signal Information 116

111

8 Timeout Server
8.1 Request Timeout 118 8.2 Cancel Timeout 119 8.3 Retrigger Timeout 119

117

9 Glossary

121

Users Guide / 4.6

Contents 5

ARM Kernel
6 Contents

Users Guide / 4.6

1 Introduction
OSE for ARM is a fast, compact, real-time operating system for the ARM (Thumb) line of microprocessors from ARM Ltd. The purpose of this manual is to give the reader a good understanding of real-time system design in general, and the different mechanisms in OSE in particular. This manual is intended for users not familiar with real-time programming as well as experienced users and is intended for application developers. This manual describes how to use the ARM Kernel in the following sections:

Introduction to OSE on page 9 gives an introduction into OSE and describes its main features. Getting Started on page 25 is a step by step tutorial on how to generate a system. Configuring OSE Epsilon for ARM on page 43 describes how to configure a system. Building a System on page 77 explains how to build and to generate OSE for ARM system. System Design on page 81 explains how to design an OSE for ARM system. Illuminator Debugger on page 111 gives an introduction in the OSE Illuminator system level debugger. Timeout Server on page 117 contains information about the OSE for ARM Time Out Server. Glossary on page 121 defines common terminology used with OSE

ARM Kernel

Users Guide / 4.6

Introduction 7

ARM Kernel
8 Introduction

Users Guide / 4.6

2 Introduction to OSE
OSE is a fast, compact, real-time operating system (RTOS) for microprocessors and microcontrollers for embedded systems. A system under OSE consists of a number of independent subprograms called processes. A process may be written to some extent as if it had the entire CPU for its own exclusive use. By assigning a priority to each process, OSE ensures that the right process is always executing. An event which requires another process with a higher priority to execute, forces an immediate switch of process. This scheme ensures fast response to important events. Processes co-operate by exchanging signals. A process may send a signal to the mailbox of another process to inform the receiver of an event or to respond to an event. Signal transmissions often cause execution to switch to another process (a task switch). A signal is a dynamically allocated message buffer containing a signal number and an optional data structure.

ARM Kernel

Signal numbers are used to select which signals to receive, while leaving others in the mailbox of the receiving process. It is possible to ignore events which are unimportant at the moment simply by selecting which signals to receive. Other processes use the CPU while a process is waiting for a signal to arrive. Unused message buffers are stored in the central buffer pool until allocated by a process. Only one process at a time may access a signal (or message buffer), thereby eliminating conflicts. If a process needs to suspend execution for a specific interval of time, it calls OSE which monitors time and activates other processes during the wait. For more information on the OSE real-time operating system, see:

Definition of an RTOS on page 10 Purpose of an RTOS on page 10 Real-Time Operating System Tasks on page 10 OSE Design Benefits on page 12 Concurrent Processes on page 12 Process Categories in OSE on page 16 Process Types in OSE on page 16 OSE Operating System Tools on page 19 Fast Semaphores on page 22 Semaphores on page 23

Users Guide / 4.6

Introduction to OSE 9

2.1 Definition of an RTOS


Anyone is free to define the term real-time operating system and many have indeed done so. The following definition is often used: "A real-time operating system is a program that must respond to external events within a limited time." When a PC user is waiting for the result of a compilation, no disaster will occur if he must wait a few seconds more or less. On the other hand, 10 extra seconds in an aircraft control system may literally be the difference between life and death. A real-time operating system would certainly be useful in a personal computer, but it is a necessity in many embedded systems.

2.2 Purpose of an RTOS


It is important to note that a real-time operating system is designed to do the work that is done in almost every real-time system. It is intended to replace the control loops, jumps, calls and global variables that would otherwise control program execution.

ARM Kernel

One major advantage of using a real-time operating system is that the manpower required to write a program system is substantially reduced. There are several reasons for this. One is that a large and potentially difficult part of the program has already been written and debugged before a project is even started. Another reason is that many small independent programs are considerably easier to write, debug and modify than one large complex program. Once a program system is written, it can be easier to debug when a real-time operating system is used if the debugging tools are designed to detect real-time problems in the interaction between many programs. The control structure of program systems without OS tends to vary considerably depending on both the application and the particular designer. Using an OS, the tools and techniques are the same in every project, making it much easier for programmers to be efficient in various projects.

2.3 Real-Time Operating System Tasks


A real-time operating system can do many things, some closer to the operating system core, some closer to the application. The following sections describe the basic tasks that comprise the core in most designs:

Resource Management on page 11 Time Management on page 11 Interprocess Communication on page 11 Speed Considerations on page 12

10 Definition of an RTOS

Users Guide / 4.6

2.3.1 Resource Management


There are many resources in a real-time system, mainly the CPU, memory and various hardware such as ports, displays, communication links, etc. The user of a real-time OS must partition his program system into a number of program parts which may operate independently of each other. Such parts are called processes. Only one process can use the CPU at a time. It is an important task of the operating system to control activation of the various processes. Under the control of the operating system, many processes can share the same memory. The operating system also decides which process is to be granted use of the various other resources of the real-time system.

2.3.2 Time Management


There are often many timing requirements in a real-time system. Perhaps the operator has to be notified after a certain time, or a valve is to be open for a number of milliseconds. Most real-time operating systems have a notion of time and can schedule activities after a specified period or at a specified time.

ARM Kernel

2.3.3 Interprocess Communication


When partitioning a real-time system into processes, the designer tries to keep them as isolated as possible. Ideally, there should be no ties between processes. Interprocess ties can appear in many forms: Global variables, subroutine calls, timing relationships, priority relationships, interrupt disables, semaphores, messages, etc. In this manual, any interaction between processes will be referred to as "interprocess communication", regardless of the actual form used. Unfortunately, it is often necessary to have communication between processes. Imagine, for example, the keyboard process and the screen process in a terminal. It is obvious they cannot be completely isolated from each other. One mark of a good system design, however, is that processes have few ties to each other. An important task of real-time operating systems is to handle communication between processes. Interprocess communication is channelled through the operating system for the following reasons:

To keep inter process connections as few as possible. To make inter process connections clearly visible. To use standardized inter process connections. To allow debugging to focus on the interaction between processes. To improve process response time.

Users Guide / 4.6

Resource Management 11

2.3.4 Speed Considerations


Generally, if a system is not fast enough with a real-time operating system, it will certainly not be fast enough without one. There are two reasons for this: 1. Systems running under a real-time operating system are always executing at the code section that is most important at any particular moment. 2. The task of directing the work must be done, either by the operating system or by the user code. Intense competition between operating system manufacturers has produced some designs with very high performance. For those who plan to make their own kernel, it is possible, but not easy, to do better in a reasonably short time.

2.4 OSE Design Benefits


One major advantage of using OSE is that the manpower required to write a program system is substantially reduced. There are several reasons for this. One is that a large and potentially difficult part of the program is already written and debugged even before a project is started. Another reason is that many small independent programs are considerably easier to write, debug and modify than is one large and complex program. Once a program system is written, it is simpler to debug when OSE is used, since the debugging tools are specifically designed to detect real-time problems in the interaction between many programs. You need not be an operating systems expert to write programs under OSE. The system calls are few and easy to understand and use. Extensive error-checking will reveal and pinpoint most mistakes, both when generating a system and when running it. Since every programmer uses the same limited set of tools, it is easier to understand, correct or modify programs written by others. Programs are rendered considerably more portable because the interface between modules is completely defined by the system calls. Most real-time high level description and specification languages tie in directly with OSE. OSE can be tailored to a specific application when configuring the operating system. If, in another project, you decide on another configuration, all modules written for the old configuration are completely compatible in the new system. OSE Systems also markets operating systems for other processors. The internals of each operating system is optimized for its particular processor. The user interfaces of all operating systems contain identical basic elements

ARM Kernel

2.5 Concurrent Processes


A process is an independent program running under OSE. At every instant of time, the most important process ready to run is running. As soon as a more important process is ready to run, the current process is removed from the CPU and the new process is entered and allowed to run. This is called a process switch. The part of the operating system that performs process switches is often referred to as the dispatcher.

12 Speed Considerations

Users Guide / 4.6

If you are running a system without a real-time operating system, the processor will often find itself unable to respond quickly to an event if the wrong part of the program is running and continues to do so for some time. Herein lies an important distinction between an OSE real-time operating systems and other operating systems. The OSE real-time operating system has what is referred to as a "pre-emptive" dispatcher. This means that the dispatcher has the power to stop the current process after the next assembler instruction and immediately move execution to a completely different part of the program system. All OSE operating systems have pre-emptive dispatchers and can be pre-empted even inside system calls.

2.5.1 Process States


In OSE, processes can have one of the following states:

RUNNING The process is the one currently in control of the CPU. In a single processor system, only one process can be in this state at a time.

ARM Kernel

READY The process needs the CPU and will be running as soon as it is permitted to do so. However, another process of higher or equal priority is RUNNING and the READY process must wait until all READY processes of higher priority are WAITING.

WAITING The process is waiting for something, for example a message, and has no need of the CPU.

Figure 2.1 Process states in OSE

Users Guide / 4.6

Process States 13

2.5.2 Priority Based Process Scheduling


Some operating system designs permit many processes to have the same priority. Different system designs have different methods for selecting which process to run when more than one process is READY on the same priority level. Some systems always select the oldest (created first) process first, whereas others select processes in some random fashion to give truly equal priority to the processes on the same priority level. The difference between processes on the same priority level and on different priority levels is that there is no process switch if a process on the same priority level becomes READY. If, on the other hand, a process on a higher priority level becomes ready, it will immediately become RUNNING and the previously running process becomes READY. This process scheduling principle will be referred to as priority based in this manual. Processes scheduled with this principle are called prioritized processes in an OSE system.

2.5.3 Round-Robin Process Scheduling

ARM Kernel

In priority based scheduling, processes are switched whenever a process on a higher priority level becomes READY. On the other hand, a process could run indefinitely if no process of higher priority became ready. That means that a process running indefinitely would lock out other processes. Another scheduling scheme is the round-robin principle. In this case, processes on the same priority level share CPU time, and they share it equally in the simplest case. When a process has used up its time-slice, it is interrupted by the operating system, even if the process is still RUNNING and may be put last in the queue. The size of time-slices need not be equal. The round-robin scheduling principle is used in many larger systems such as the UNIX operating systems. In such systems, the size of the time-slice is often changed at run-time according to various principles. Since round-robin is the only scheduling principle in many larger systems, response times are slow, for no process change occurs until the current time-slice is used up. Many unimportant processes may also be allocated CPU time before an important process. Many real-time operating systems allow the user to select either a priority based or a round-robin scheduling scheme. Some of them allow both principles to be used at the same time in one system. A system using both principles simultaneously might be utilized in the following way: 1. Time critical processes are scheduled on a priority basis and thus allowed to finish their job without interruption. 2. Operators are round-robin scheduled on one priority level. Operators have time- slices of equal length, except the superuser who has a longer time-slice. Operators thus share

14 Priority Based Process Scheduling

Users Guide / 4.6

the available CPU time equally. The superuser is allowed a larger share of CPU resources. None of the operators can lock the others out from the system. 3. Tests and other housekeeping processes share time on a lower priority level. They are allowed CPU time only when nothing time critical is under way and no operator has work to do. Processes intended for a priority based scheduling scheme must be written in a different way than those intended for round-robin scheduling. There must be no infinite loops in the internal control structure in a process written for priority based scheduling. If there is an infinite loop in one process, processes on lower priorities will never be allowed to use the CPU. If the loop contains a call to the operating system that causes the process to become WAITING, lower priority processes can come in, and there is no problem. Processes written for round-robin scheduling can contain whatever loops the programmer desires; in this respect they are always handled safely by the operating system. In an OSE system, processes scheduled according to the round-robin principle are called background processes.

ARM Kernel

Background processes with equal priority Running process

CPU

Waiting background processes which become ready

Figure 2.2 Round-robin process scheduling For each priority equal or below the background priority level, a process (FIFO) queue is maintained. Processes enter the READY list at the end of the queue and processes are selected for execution from the head of the queue. OSE gives each process a user selected time-slice for running before pre-empting it to allow the next process in the READY queue to run.

Users Guide / 4.6

Round-Robin Process Scheduling 15

2.6 Process Categories in OSE


Processes can be divided into two types depending on whether they always exist or are created and killed as they are needed. Static processes always exist, whereas dynamic processes may be created and killed at run-time. In the most commonly used design with static processes, one process starts executing after system start, normally the highest prioritized, and all static processes have already been created and are READY. It is an error for a static process to kill itself, and it is an error for a process to try to kill a static process. This ensures that a static process always exists, and it is thus always possible to communicate with a static process. The real-time operating system can declare the names of all static processes' public. Any process may then declare the name of a static process external and can obtain its process ID and communicate with it.

2.7 Process Types in OSE


Process types in OSE are described in:

Prioritized Processes on page 17 Background Processes on page 17 Interrupt Processes on page 17 Interrupt Performance on page 18 Timer Interrupt Processes on page 19

ARM Kernel

16 Process Categories in OSE

Users Guide / 4.6

2.7.1 Prioritized Processes


Prioritized processes are the most common processes in a typical OSE system. Prioritized processes have a strict order of priority. The highest priority process will always run before every other process. The lowest priority process will be allowed to run only when no other prioritized process is ready. If two processes are assigned the same priority, the choice of precedence between the two processes is made by OSE. When a process has no further work to do for the moment, it becomes not ready. A process is not ready when it is waiting for a message or when it is waiting for a delay to end or when it is waiting at a semaphore. A process is swapped out from the CPU when it becomes not ready or when a process of higher priority becomes ready. Note that a process may be interrupted between almost any two assembler instructions and in the middle of any C instruction. A process is swapped in if all processes of higher priority are not ready and the process itself is or becomes ready.

2.7.2 Background Processes

ARM Kernel

These are identical to prioritized processes except that they do not have priority. A background process will only be allowed to run when no prioritized process is ready. The time left over when no prioritized process is running is divided between ready background processes. Running background process is switched by the operating system at user defined intervals. A background process is allowed to execute until it becomes not ready or a prioritized process becomes ready or until the background process has executed for the duration of the user defined interval. Background processes may be written either in assembly or C.

2.7.3 Interrupt Processes


An interrupt is a hardware generated event that will cause the CPU to suspend the currently running process and turn control over to the interrupt routine dedicated to that particular interrupt. Interrupts are used in systems with and without real-time operating system. The programs handling interrupts are called processes in some operating systems, service routines in others and device drivers or part of device drivers in still other systems. In OSE they are called interrupt processes. Some real-time operating systems canalize all interrupts through the operating system that then calls the appropriate interrupt process. Others let the user write the calling code and then provide entry and exit calls for the process. In some cases the entry call can be avoided. The latter principle offers faster interrupt handling but less convenience. An important performance advantage of the latter method is that interrupts which do not need use of the operating system can avoid both the entry and the exit routine. An interrupt process is called whenever its interrupt occurs, provided that no other interrupt of higher or equal hardware priority is running. Should such be the case, this interrupt must wait its turn.

Users Guide / 4.6

Prioritized Processes 17

Processes have priorities assigned by the operating system. Interrupt processes have the priority assigned to its interrupt by hardware. In some CPUs they may, however, change priority by writing to some status register.
External Interrupt Hardware
Hardware Delay Encoding Incoming Interrupt Stacking of CPUs state data Finish current Instruction

Software
Interrupt process including system calls

ARM Kernel

Operating system or user code finishes execution of longest critical section

Operating system finishes interrupt servicing Operating system context switch

USER PROCESS

OSE

Figure 2.3 Interrupt processes There can exist only one interrupt process for each of the available hardware interrupt vectors. An interrupt process is called as a subroutine whenever its interrupt occurs, provided that no other interrupt is running.

2.7.4 Interrupt Performance


Interrupt response time is the time elapsed between the occurrence of an interrupt and the execution of the first instruction of the interrupt process. Most operating systems and many user programs disable interrupts from time to time. The longest time in which interrupts are disabled is called interrupt latency. Interrupt latency of a real-time operating system is one of the most important performance factors. It is often difficult to design a system when interrupt latency is not known. Real-time operating systems vary considerably with regard to the calls they allow to be made from an interrupt process. Some permit all calls (with the exception of those which cause the caller to sleep). Others, however, permit only a single call from interrupt

18 Interrupt Performance

Users Guide / 4.6

processes. This design is used by operating systems that do not disable interrupts. Another way to effectively achieve zero interrupt latency is to disable interrupts for a shorter time than the longest CPU instruction. This method has the advantage of permitting most system calls to be used by an interrupt process. Many real-time operating systems allow the user to set aside some hardware interrupt priority levels and request that these levels should not be disabled by a real-time operating system. Interrupt handlers working on such levels may never call any real-time operating system function. If they do so nonetheless, the system will crash sooner or later. Since such interrupts cannot use system calls, they are, among other things, unable to activate a process that runs under non-interrupt. If other processes are to act on data from such an interrupt, they must poll some suitable variables.

2.7.5 Timer Interrupt Processes


Timer interrupt processes work like interrupt processes except for the manner in which they are called. For each timer interrupt process the user selects a number of system ticks to elapse between each call to the process.

ARM Kernel

2.8 OSE Operating System Tools


There are hundreds of slightly different operating system tools available. As it is outside the scope of this short introduction to describe them all, only one type of tool will be described in detail; messages as used under OSE. A few more of the most common tools will be described in terms of their differences. The user partitions his system into processes that are then activated as appropriate by the real-time operating system. When these processes need to communicate with each other or otherwise affect one another, services are requested from the operating system through the use of system calls. A system call is not different from any procedure call except for one thing: a process making a system call can be put to sleep by the operating system. This is the one thing that makes system calls similar. They may either implicitly request that the caller becomes WAITING, or they may make a higher priority process READY. In the latter case the effect is similar; the caller becomes READY while the other process becomes RUNNING, effectively putting the caller to sleep. In some situations, control is returned to the caller, which may then continue execution. The above implies that any of these tools can be used to emulate any of the others. Why are there so many tools? One reason is that once the basic "go-to-sleep"- mechanism is built, it is relatively simple to add many tools. Apart from this, when a tool is accurately and wisely used in the situation for which it has been designed, additional convenience or sometimes higher performance can be obtained. See also:

Messages on page 20 Fast Semaphores on page 22 Semaphores on page 23


Timer Interrupt Processes 19

Users Guide / 4.6

2.8.1 Messages
When a process wants to receive a message it calls the operating system, requesting a message. If none is available, the operating system puts the process to sleep until one arrives. When a process wants to send a message, it calls the operating system, submitting the message. If the receiving process is of higher priority, or if a higher priority process is sleeping at the mailbox in question, the calling process is put to sleep, and the higher priority process is allowed to use the CPU. Mailboxes are described further in this chapter. A message is often actually a buffer, an area of memory, where processes may read and write data. A buffer may be used by many different processes, but only one process at a time may access a buffer. If processes should access buffers without control, the resulting errors would be difficult to find. Messages not only carry data; they may also initiate actions by the various processes.
2.8.1.1 Message Passing Through Mailboxes

ARM Kernel

OSE is not using message passing trough mailboxes. Under some other operating systems, messages are sent to mailboxes to which any process can send and from which any process can receive. In this case there must be some set of rules determining which processes are to send to a certain mailbox and which processes are to receive from the mailbox. Processes must send their messages to the mailbox where the addressee is waiting when it requires these messages. Which mailbox to send to is determined by set of rules that evolves as the system is designed and tested. If some messages are unwanted at certain times, more mailboxes can be created and processes can wait at these. If it is not desirable to create more mailboxes, the user may design his process as a state machine and receive all messages at one mailbox. When a new message is added to the work of the process, the number of states can double. Most of the state machine is often affected when new functions are added to it. Processes must be carefully designed, since a process that needs prompt response from another must know at which mailbox the target process is waiting or else it must send messages to all possible mailboxes. In the latter case, the unused messages must be removed once the process has received one copy of the message. Mailboxes are not used in the OSE operating system.

20 Messages

Users Guide / 4.6

The figure below shows mailbox message passing in one direction only. In reality, the situation becomes more complex when messages are passed in both directions.

Sending Processes

Receiving Processes

ARM Kernel

Figure 2.4 Mailbox message passing

2.8.1.2 Direct Message Passing in OSE

OSE operating systems send messages directly to processes. In OSE the name signal is also often used. Messages and Signals are exactly the same in an OSE system. In this scheme it is not necessary to know which mailboxes to create, kill and send to and receive from. With this design it is not possible to avoid unwanted messages by creating more mailboxes. Possibly, more processes could be introduced to solve the problem.

Users Guide / 4.6

Messages 21

Another solution is to let a process select the messages it is interested in receiving at any particular moment. If this tool is available, the "prompt response" problem of the previous paragraph is also solved, for a process is always waiting at the same mailbox.
Sending Processes Receiving Processes

ARM Kernel

Figure 2.5 Direct message passing In OSE signals (or messages) are sent between processes. Each message is a buffer, an area of memory, where processes may read and write data. A buffer may be used by many different processes, but only one process at a time may access a buffer. Signals not only carry data, they also initiate actions by the various processes. All processes can exchange signals, even those residing in other computers. (Through the use of a link handler.) When a process gains access to a signal buffer by allocating it or receiving it, the process becomes the owner of the buffer. Only the owner may perform operations on the buffer. Once a signal has been sent to another process it can no longer be accessed by the sending process. A process may select the signals it is interested in receiving at any particular moment. The process will then wait for signals to arrive. Meanwhile, other processes are allowed to execute.

2.8.2 Fast Semaphores


Fast semaphores is a specific OSE feature and are intended for those rare cases where user programs cannot use message passing due to timing problems. For example, a fast semaphore may be used to count characters in a user implemented buffer between an interrupt process receiving characters and a prioritized process consuming characters.

22 Fast Semaphores

Users Guide / 4.6

Fast semaphores work like this: A fast semaphore is a signed integer owned by a process. It is operated by system calls WAIT (WAIT_FSEM) and SIGNAL (SIGNAL_FSEM). Only the owner may wait at a fast semaphore. Other processes may signal it.

2.8.3 Semaphores
Semaphores are somewhat similar to fast semaphores, but they differ in one very important aspect: A semaphore is not related to any specific process. Any background or prioritized process may wait at a semaphore, not just the owner. Any type of process may signal a semaphore. The main purpose of semaphores is to protect critical code sections from concurrent execution (so called mutual exclusion) without disabling interrupts. This is often done to protect global shared resources. If the compiler supports static initialisation of C structures this can be used to declare a semaphore at compile time. OSE is a message-passing real-time operating system. It is therefore strongly recommended to not use global variables and semaphores in an OSE system. Only message passing design ensures a clear and secure system and makes it possible to use some powerful features in the OSE Illuminator system level debugger.

ARM Kernel

Semaphores are mainly used to ensure that only one process at a time is using a global shared resource. As soon as the process currently occupying the resource releases it, it will automatically be given to the next in its waiting queue. Use the wait_sem system call to get in line to use the resource as soon as possible and the signal_sem system call to releases it as soon as the resource is no longer needed. A semaphore is a counter to which 1 can be added and from which 1 can be subtracted. Adding 1 is called "signalling the semaphore" and subtracting 1 is called "waiting for the semaphore". If the counter is 0 and a process tries to subtract 1, the subtracting (waiting) process is put to sleep. If a process is asleep at the semaphore and another process signals the semaphore, the sleeping process becomes READY and will be allowed to run if it is of higher priority than the signalling process. The counter of a semaphore may be a single bit, in which case the semaphore is referred to as a binary semaphore. The other type is often called a counting semaphore.

Users Guide / 4.6

Semaphores 23

Semaphore example: Assume a system with two printers. When the system is started, the semaphore is initialised to 2. Each process needing a printer first waits at the semaphore. When the process has finished with the printer, it signals the semaphore. When the first two processes wait for the semaphore, the counter is simply decreased. When the third process waits for the semaphore, it is put to sleep because the semaphore is 0. When one of the first two processes is finished, the semaphore is signalled and the third process is awakened. In this way, the semaphore sees to it that only one process at a time uses each printer. One way to solve the same problem with messages: A process owns the printer (the printer process for example). Processes that need a printer send a message to the printer process, and when the process receives a reply message, the printer is available. As long as there is no reply message, the requesting process is sleeping.

ARM Kernel
24 Semaphores

Users Guide / 4.6

3 Getting Started
This is a step-by-step tutorial that shows how to generate a simple application with the OSE for ARM real-time operating system, see Example System Description on page 26. You will be guided through the configuration and the generation of an example system in Step by Step Tutorial on page 28.

ARM Kernel
Users Guide / 4.6

Getting Started 25

3.1 Example System Description


In this example we have designed a small motor controller system which is working completely inside the processor without using any peripheral functions. You can find the source files in the example-directory of the OSE delivery. The following figure shows the example system:

runner

TEST_VAL KEY_HIT keyhand

test KEY CURRENT KEY_R control

ARM Kernel

CHARACTER MOTOR_ON OVERCURR motor bg1 bg2 display

Figure 3.1 Example system There is a keyboard where commands can be typed, a test process which reads some current sensor, a display process where messages can be displayed, a motor process controlling the rather big motor and a control process controlling the system. There is also a runner process, which gives simulated input to the keyboard and the test process.

26 Example System Description

Users Guide / 4.6

There are eight signals used:


KEY_HIT KEY KEY_R MOTORON CURRENT OVERCURR CHARACTER TEST_VAL

The system consists of seven source files:


runner.c

This process gives test stimuli (signals KEY_HIT and TEST_VAL) to the keyhand and test processes. This process calls also the function feedback() at a regular rate. Feedback is included in the module led.c and controls the LEDs on the evaluation board (if there are LEDs available on the board).

ARM Kernel

keyhand.c

In reality an interrupt process managing the keyboard. In this simulated system this process receives the signal KEY_HIT from runner. The characters are just echoed to control, and keyhand then waits for a receipt (signal KEY_R).
test.c

In reality a timer-interrupt process, measuring the current from a sensor and sending the value to control. In this simulated system test receives TEST_VAL signals from runner, and transfers the content inside the signal CURRENT to control.
motor.c

This process receives the MOTORON signal and starts and stops the motor accordingly.
display.c

If a character is displayable, control will forward it to display.


control.c

This is the spider in the net, controlling the system. Receives KEY_HIT and CURRENT signals, sends MOTORON to motor, CHARACTER and OVERCURR to display, and KEY_R to keyhand.
bg.c

Two background processes, which do not have a specific functionality. It is just to show how to setup a background process.
led.c

Includes the function feedback() which controls a row of leds on the evaluation board.

Users Guide / 4.6

Example System Description 27

3.2 Step by Step Tutorial


This tutorial shows you how to generate the example system in the following sections:

Equipment on page 29 Preparation on page 30 OSE Configuration on page 30 Getting the System Files on page 33 Getting Specific Drivers on page 33 Getting the Example Source Files on page 34 Building the System with ARM ADS on page 35 Building the System with IAR EWB on page 36 Building the System with GNU GCC on page 37 Running the System without OSE Illuminator on page 40 Running the System with OSE Illuminator on page 40 Debugging on page 42

ARM Kernel

28 Step by Step Tutorial

Users Guide / 4.6

3.2.1 Equipment
To run this Getting Started System, you need the following equipment:

PC running Windows 98, 2000 or NT. A target evaluation board preferably one where an OSE for ARM board support package is delivered. This tutorial is designed for the ARM Evaluator-7T evaluation board. You could use any board with a processor where the OSE for ARM kernel runs but you might have to modify the system startup files and some drivers. Your preferred debugger connected to your selected ARM evaluation board. One of the following development environments:
ARM Developer Suite IAR Embedded Workbench GNU GCC

OSE Epsilon for ARM RTOS. If you would like to run also the OSE Illuminator system level debugger, you will need the additional equipment:
A serial line connected of one of your PCs COM ports to the serial port of

ARM Kernel

your target board which is supported by the serial device driver.


OSE Illuminator which is delivered on a separate CD. Please consult the

OSE Illuminator Users Guide for information about installation and usage.

Users Guide / 4.6

Equipment 29

3.2.2 Preparation
This Getting Started example is not a ready to run plug-and-play project where you push a button and your system is generated and after down loading you see something running in the target. This is maybe quite nice for a demonstration but not very useful to learn how to configure and generate an OSE for ARM system. In this Tutorial we will guide you through the whole configuration and generation process. You will learn what files you need and which configuration entries you have to define. First, you will need to create a work directory in a suitable place.

3.2.3 OSE Configuration


The OSE operating system can be configured to have completely different characteristics depending on the trade-off you want to make between speed, memory consumption and code size. The configuration is accomplished by entering the desired values into the osarm.con configuration file. 1. Copy the osarm.con configuration file into your working directory. You will find this file at: <installdir>\arm\krnxxx\<yourCompiler>\conf\ Be sure to copy osarm.com from the directory corresponding to your used compiler. 2. Start your preferred editor and load osarm.con into the editor. 3. Check the compiler configuration line. It should fit your used compiler environment (ARM for ARM ADS, IAR for IAR Systems and GNU for GNU GCC. The option SINGLECHIP is not used in this example. 4. Define a target name such as:
TARGET_NAME motcon

ARM Kernel

5. For the ARM Evaluator-7T evaluation board define the following CPU:
CPU ARM7T DMI

6. Define the memory endianess model such as:


MEMORY_MODEL LITTLE

7.We will enable some kernel internal debug functions:


DEBUG BUFFER_CHECK STACK_CHECK YES YES YES

30 Preparation

Users Guide / 4.6

8.If you will not use the OSE Illuminator system level debugger enter the following debugger options:
OPTION DEBUGGER,NO

If you are using the OSE Illuminator system level debugger over a serial line enter the following debugger option definitions:
OPTION DEBUGGER,ONCHIP,1024,20

This will generate the OSE for ARM debug kernel. Please consult Option Debugger on page 52 for more information concerning the debugger options. It is simpler to first generate a system without OSE Illuminator support. 9. You do not need to modify the memory allocation default settings for this simple getting started example:
POOL BUFFERSIZES 1024 4,8,16,32,64,128,256,512

This will define a message pool of a size of 1024 bytes and individual message sizes of 4, 8, 16, 32, 64, 128, 256 and 512 bytes.

ARM Kernel

10.We will use the default interrupt and temporary stack sizes:
ISTACK_SIZE TEMP_STACK_SIZE 256,512 256

11.We define one start handler. This handler is included in the file timer_setup.* of the board support package delivery.
START_HANDLER TimerSetup

12.Now we are defining the prioritized processes:


PRI_PROC PRI_PROC PRI_PROC PRI_PROC PRI_PROC PRI_PROC motor,256,14 control,256,17 test,256,17 display,256,17 keyhand,256,17 runner,256,18

For all process we declare a stack of 256 bytes. All processes have the same priority of 17 except process runner which has a priority of 18 and motor with 14. 13.To show how OSE background processes are defined, we have included the background processes bg1 and bg2:
BG_PROC BG_PROC bg1,256,10 bg2,256,10

The two background processes have a stack of 256 bytes and a times slice of 10 ticks.

Users Guide / 4.6

OSE Configuration 31

14.The file osarm.con is now complete and should look more or less like this (without comments):
COMPILER ARM TARGET_NAME motcon CPU ARM7T DMI MEMORY_MODEL LITTLE DEBUG YES BUFFER_CHECK YES STACK_CHECK YES OPTION DEBUGGER,ONCHIP,1024,20 POOL 1024 BUFFERSIZES 4,8,16,32,64,128,256,512 ISTACK_SIZE 256,512 TEMP_STACK_SIZE 256 START_HANDLER TimerSetup PRI_PROC motor,256,14 PRI_PROC control,256,17 PRI_PROC test,256,17 PRI_PROC display,256,17 PRI_PROC keyhand,256,17 PRI_PROC runner,256,18 BG_PROC bg1,256,10 BG_PROC bg2,256,10 END

ARM Kernel

The file can vary depending on used compiler, evaluation board and debug option. 15.Open a shell window and change the directory to your example working directory. Run the configuration utility confarm.exe by declaring osarm.con as input file:
<install_dir>\arm\krnxxx\bin\confarmosarm.con

For every change in the osarm.con configuration file the confarm.exe utility must be executed again. If your IDE allows to define external utilities or you are using a makefile you could add this step in the IDE or in the makefile. 16.The kernel will be generated in your working directory. The file name of the kernel is osarm.*. The extension differs from compiler to compiler (ARM: osarm.s, GNU: osarm.S, IAR: osarm.s79).

32 OSE Configuration

Users Guide / 4.6

3.2.4 Getting the System Files


1. We will copy and assemble the OSE for ARM system files which are needed to setup and start the system. 2. To setup the C system you will need the C startup file. Copy the file crt0.* into your working directory. You will find this file in the OSE for ARM board support package of your selected board (ARM Evaluator-7T board in this example): <installdir>\arm\bspxxx\Evaluator7T\<yourCompiler>\src\ The file extension differs from compiler to compiler (ARM: crt0.s, GNU: crt0.S, IAR: crt0.s79). 3. OSE for ARM needs an interrupt handler to manage all interrupts. Copy the file inthdlr.* into your working directory. You will find this file in the OSE for ARM board support package of your selected board (ARM Evaluator-7T board in this example): <installdir>\arm\bspxxx\Evaluator7T\<yourCompiler>\src\ The file extension differs from compiler to compiler (ARM: inthdlr.s, GNU: inthdlr.S, IAR: inthdlr.s79). 4. The OSE-Tick-Timer needs to be initialized before OSE is started. Copy the file timer_setup.* into your working directory. You will find this file in the OSE for ARM board support package of your selected board (ARM Evaluator-7T board in this example): <installdir>\arm\bspxxx\Evaluator7T\<yourCompiler>\src\ The file extension differs from compiler to compiler (ARM: timer_setup.s, GNU: timer_setup.S, IAR: timer_setup.s79).

ARM Kernel

3.2.5 Getting Specific Drivers


1. If you want to use the OSE Illuminator system level debugger and have therefore set OPTION DEBUGGER,ONCHIP,1024,20, you also need a serial driver to connect Illuminator to your target board. If you are using the ARM environment and the ARM Evaluator-7T board copy the file eldm_uart.* into your working directory. You will find this file in the OSE for ARM board support package of your selected board (ARM Evaluator-7T board in this example): <installdir>\arm\bspxxx\<yourBoard><yourCompiler>\src\ The file extension differs from compiler to compiler (ARM: eldm_uart.s, GNU: eldm_uart.S, IAR: eldm_uart.s79).

Users Guide / 4.6

Getting the System Files 33

3.2.6 Getting the Example Source Files


1. Every process of the example system resides in one C file. Copy all example *.c files into your working directory. You will find these files in the example directory of the kernel delivery: <installdir>\arm\krnxxx\<yourCompiler>\exp\motcon\ The following files will be copied: motor.c, control.c, test.c, display.c, keyhand.c, runner.c, and bg.c. 2. Every signal (or message) of the example system resides in one signal file. These signals will be included by the processes. Copy all example *.sig files into your working directory. You will find these files in the example directory of the kernel delivery: <installdir>\arm\krnxxx\<yourCompiler>\exp\motcon\ The following files will be copied:

characte.sig current.sig key.sig key_hit.sig key_r.sig motoron.sig overcurr.sig test_val.sig

ARM Kernel

3. There is a system header file delivered for the example. This file will be included by some processes. Copy the file system2.h into your working directory. You will find this file in the example directory of the kernel delivery: <installdir>\arm\krnxxx\<yourCompiler>\exp\motcon\ 4. If there are LEDs on your board available there is a function called feedback() to manage these LEDs. This function is defined in the file led.c and led.h. Copy led.c and led.h to your working directory. You will find these files in the board support package directory for your selected board, e.g.: <installdir>\arm\bspxxx\<yourBoard>\src\ <installdir>\arm\bspxxx\<yourBoard>\include\

34 Getting the Example Source Files

Users Guide / 4.6

3.2.7 Building the System with ARM ADS


1.We will build the system with the ARM ADS development environment. If you are using the IAR environment, skip this chapter and go to Building the System with IAR EWB on page 36. If you are using the GNU environment, skip this chapter and go to Building the System with GNU GCC on page 37 . 2.Start the ARM ADS development environment. 3.Menu File -> New -> Thumb Executable Image Select Project Name (e.g. motcon) and choose a Location. 4.Change the project settings: Menu Edit -> DebugRel settings... Select pane Access Path -> System Paths Add the following paths: <installdir>\arm\krnxxx\ads\include <installdir>\arm\bspxxx\include <installdir>\arm\bspxxx\<yourBoard>\include <installdir>\arm\bspxxx\<yourBoard>\ads\include

ARM Kernel

Select pane Build extras and uncheck Use modification date caching. Select pane ARM Assembler -> ATPCS. Check ARM/Thumb interworking. Select pane ARM Linker. Choose Linktype: Scattered and enter a Scatterdefinition File. Now click save. 5. Adding files to the project: Menu Project -> Add Files => File selector dialogue. a) Select all .c files b) Select all .s files 6. Building the project Menu Project -> Make 7.Go to Running the System without OSE Illuminator on page 40 or Running the System with OSE Illuminator on page 40.

Users Guide / 4.6

Building the System with ARM ADS 35

3.2.8 Building the System with IAR EWB


1.We will build the system with the IAR Embedded Workbench development environment. If you are using the ARM ADS development environment, skip this chapter and go to Building the System with ARM ADS on page 35. If you are using the GNU environment, skip this chapter and go to Building the System with GNU GCC on page 37. 2. Create a new project: Menu: File -> New -> Project Go to your working directory, enter a project name and press Create. 3. Add files to the project: Menu: Project -> Files a) Select C files: motor.c, control c, test.c, display.c, keyhand.c, runner.c, bg.c, led.c b) Select assembler files: crt0.s79, inthdler.s79, timer_setup.s79 osarm.s79 (If you do not have this file, make sure to run confarm.exe in your working directory and that the compiler switch in osarm.con is set to IAR). eldm_uart.s79 (only if you plan to use illuminator). 4. Project settings Select Debug in the project window and to the Menu Project -> Options Select pane ICCARM -> Preprocessor. Add the following paths (each in a separate line): <installdir>\ARM\krnxxx\IAR\include <installdir>\ARM\bspxxx\include <installdir>\ARM\bspxxx\<your Board>include <installdir>\ARM\bspxxx\<your Board>IAR\include Select pane AARM -> Include and add the above paths here as well. Select pane XLINK -> Include Set Override Default and enter the path to an XCL file for your board. Select pane XLINK -> Diagnostics Set No global type checking to prevent warnings about union SIGNAL having more then one definition. 5. Building the project Menu Project - > Make 6. Go to Running the System without OSE Illuminator on page 40 or Running the System with OSE Illuminator on page 40.

ARM Kernel

36 Building the System with IAR EWB

Users Guide / 4.6

3.2.9 Building the System with GNU GCC


1.We will use the GNU make utility to build the system with the GNU GCC compiler. If you are using the ARM ADS development environment, skip this chapter and go to Building the System with ARM ADS on page 35. If you are using the IAR Embedded Workbench environment, skip this chapter and go to Building the System with IAR EWB on page 36. 2. Start your preferred editor and create a Makefile. The next steps will explain the makefile entries for the example project. 3. First we will define the compiler and assembler macros and a remove macro for the host operating system:
CC=arm-thumb-elf-gcc AS=arm-thumb-elf-as LD=arm-thumb-elf-ld CPP=$(CC) -E -xc RM=rm -f

ARM Kernel

4. Define the compiler assembler and linker flags:


ASFLAGS CFLAGS CFLAGS+ LDFLAGS = = = = -mthumb-interwork -EL -Wall -O2 -fomit-frame-pointer -mthumb -mthumb-interwork -mlittle-endian -s -marmelf -e OSE_RESET -T gnu.lnk

5. Define the OSE include path:


INC = -I<install_dir>/arm/krnxxx/gnu/include

6. Add the GNU include path:


INC += -I<gnu_install_dir>/arm-thumb-elf/include

7. Define the GNU library for the linking:


LIBS = -lc

8. Set the executable and build name:


all: motcon.elf

Users Guide / 4.6

Building the System with GNU GCC 37

9. Define all C-files and the related object macro:


C_SRC C_SRC C_SRC C_SRC C_SRC C_SRC C_SRC C_SRC = += += += += += += += bg.c control.c display.c keyhand.c motor.c runner.c test.c timer.c

C_OBJ = $(C_SRC:.c=.o)

10.Define all Assembler files and the related object macro:


AS_SRC = osarm.S AS_SRC += crt0.S AS_SRC += inthdlr.S AS_SRC += timer_setup.S AS_OBJ = $(AS_SRC:.s=.o)

ARM Kernel

11.Set the makefile meta rules for assembling and linking:


OBJ= $(C_OBJ) $(AS_OBJ) .SUFFIXES: .c .o.S .S.o: $(CC) $(INC) $(CFLAGS) -c -o $@ $< .c.o: $(CC) $(CFLAGS) $(INC) -c $< -o $@

12.Instead of running the OSE for ARM configuration utility confarm.exe manually (see OSE Configuration on page 30), you could include this step in the makefile:
osarm.S : osarm.con confarm osarm.con

13.Define the linking process:


motcon.elf: $(OBJ) osarm.o gnu.lnk $(LD) $(LDFLAGS) -Map motcon.map $(OBJ) $(LIBS) \ osarm.o -o motcon.elf

14.You can also set a cleaning action:


clean: $(RM) osarm.S $(RM) *.o $(RM) *.elf $(RM) *.*~

38 Building the System with GNU GCC

Users Guide / 4.6

15.The file Makefile is now complete and should look more or less like this:
CC=arm-thumb-elf-gcc AS=arm-thumb-elf-as LD=arm-thumb-elf-ld CPP=$(CC) -E -xc # OS stuff RM=rm -f ASFLAGS = -mthumb-interwork -EL CFLAGS = -Wall -O2 -fomit-frame-pointer CFLAGS = -mthumb -mthumb -interwork -mlittle-endian LDFLAGS = -s -marmelf -e OSE_RESET -T gnu.lnk INC = -I/OSE/epsilon/ARM/krn361/GNU/include INC += -I/usr/arm-thumb-elf/include LIBS = -lc

all: motcon.elf C_SRC C_SRC C_SRC C_SRC C_SRC C_SRC C_SRC C_SRC = += += += += += += += bg.c control.c display.c keyhand.c motor.c runner.c test.c timer.c

ARM Kernel

C_OBJ = $(C_SRC:.c=.o) AS_SRC = osarm.S AS_SRC += crt0.S AS_SRC += inthdlr.S AS_SRC += timer_setup.S AS_OBJ = $(AS_SRC:.S=.o) OBJ= $(C_OBJ) $(AS_OBJ) .SUFFIXES: .c .o .S .S.o: $(CC) $(CFLAGS) $(INC) -c $< -o $@ .c.o: $(CC) $(CFLAGS) $(INC) -c $< -o $@ osarm.S : osarm.con confarm osarm.con motcon.elf: $(OBJ) osarm.o gnu.lnk $(LD) $(LDFLAGS) -Map motcon.map $(OBJ) $(LIBS) osarm.o -o motcon.elf clean: $(RM) osarm.S $(RM) *.o $(RM) *.elf $(RM) *.*~

The file can vary depending on used compiler, evaluation board and debug option. 16.Run the make utility to generate the executable. 17.Go to Running the System without OSE Illuminator on page 40 or Running the System with OSE Illuminator on page 40.

Users Guide / 4.6

Building the System with GNU GCC 39

3.2.10 Running the System without OSE Illuminator


If you are running the system without our OSE Illuminator system level debugger, you just need to download the generated executable and test it. Connect your preferred source level debugger to the target system and start it. Setup the board to enable the memory system and download the generated executable. Set some breakpoints at different location inside the example system and check the function of the whole system.

3.2.11 Running the System with OSE Illuminator


Illuminator is a system level debugger for OSE real-time operating systems. In a typical real-time system, the crucial parts are the interfaces between the different system components and the real-time behaviour and status of system functions and resources. In an OSE system, the components are processes and the interface is always made up of OSE signals. With a traditional source code debugger it would be a tough job to supervise or debug these interfaces because a source level debugger concentrates on code lines. The OSE Illuminator system level debugger is designed to make it easy to work with the signal interfaces.

ARM Kernel

The main system level debugger functionality resides in the target system for the serial line version. On the host, you have the graphical user interface (written in Java) and a communication module called Epsilon Debug Server (edbgserver). For the serial line Illuminator, you need a free serial interface in your target system and on your host. It is an easy to use and simple configurable architecture which is very well suited for single chip systems. If you have selected the debug option (OPTION DEBUGGER) in the ARM kernel configuration file, the Debug Kernel will be generated. The Debug Kernel includes beside the standard OSE for ARM kernel also debug code and memory to use with the OSE Illuminator system level debugger. To connect the Debug Kernel to the host system, you need a serial driver eldm_uart.s), the serial interfaces and the serial cable.

40 Running the System without OSE Illuminator

Users Guide / 4.6

Host Illuminator
TCP/IP

Target OSE for ARM Debug Kernel

edbgserver

serial.* Serial Line comx uart

Figure 3.2 Serial line Illuminator system

ARM Kernel

18.Connect your Source Level Debugger to the JTAG debug port of your evaluation board. Switch-on the debugger. 19.Connect the serial cable from a free serial port on your host PC to the serial interface connector of the target board. 20.Switch-on the target board. 21.Start the debugger and download the generated file motcon.* into your target system. 22.Run the target system from your source level debugger.

Users Guide / 4.6

Running the System with OSE Illuminator 41

3.2.12 Debugging
We are supposing that you have generated the system for Serial Line Illuminator, downloaded the executable into your target system and started the target program.
3.2.12.1Epsilon Debug Server

You have to start the communication program on the host system called edbgserver manually.
If you have installed OSE for ARM at the default location on your PC, you can find the edbgserver.exe file at the location: c:\ose\epsilon\arm\krnxxx\bin Open a MS-DOS shell window and change the working directory of this window to the directory where edbgserver.exe is located. Run edbgserver.exe. You will now see the following window:

ARM Kernel

3.2.12.2Debugging with OSE Illuminator

Please consult the Illuminator Users Guide for a detailed description of OSE Illuminator.

42 Debugging

Users Guide / 4.6

4 Configuring OSE Epsilon for ARM


The configuration file osarm.con must be customized to your particular configuration. Edit this file until it meets system requirements. Always keep a copy of the original configuration file. Most declarations in the configuration file must be present at system generation. The order in which declarations appear is also fixed. If you encounter problems with due to the order declarations and you are unable to locate the reason, make a new copy and re-enter your definitions. Each configuration has a syntax description where names within angles < > are user selected labels and all other words shown are reserved. Also provided are examples of configurations. Numbers used are expected to be in decimal notation, unless you specify otherwise. Hexadecimal numbers are entered by preceding the hexadecimal number with a "0x". For details on notational conventions, refer to the appropriate assembly language manual. The configuration file osarm.con is the input file for the confarm configuration program. After running confarm, the OSE Epsilon for ARM kernel (osarm.*) will be generated. For more information about system generation, see Building a System on page 77.

ARM Kernel
Users Guide / 4.6

Configuring OSE Epsilon for ARM 43

Configuration is described in:


C Compiler on page 45 Target Name on page 46 CPU Type on page 47 Memory Model on page 48 Debug Option on page 49 Buffer Check Option on page 50 Stack Check Option on page 51 Option Debugger on page 52 Option Conditional Halt on page 53 Option Dispatcher in RAM on page 54 Pool Size on page 55 Buffer Sizes on page 56 Interrupt Stack on page 57 Temporary Stack on page 58 Error Handler on page 59 Start Handlers on page 60 Swap Handler on page 61 Send Handler on page 62 Receive Handler on page 63 Power On Handler on page 64 Power Off Handler on page 65 Idle Handler on page 68 Fast interrupts as IRQ:s on page 69 Interrupt Processes on page 70 Timer Interrupt Processes on page 71 Prioritized Processes on page 72 Link Handler Processes on page 73 Background Processes on page 74 Enable Wake Up on page 75
Users Guide / 4.6

ARM Kernel

44 Configuring OSE Epsilon for ARM

4.1

C Compiler
Defines the used C compiler product. Supported compilers are: ARM (ARM Ltd.) ADS/RVCT, IAR (IAR Systems AB) and GNU GCC. The option SINGLECHIP enables the generation of a Single-Chip version. This is very useful for projects which need limited memory consumption. There is only one restriction for the Single-Chip version: All OSE data segments must reside in the first 64 Kbyte memory range. This declaration must be the first entry in osarm.con. This declaration must always be present.

Description:

Syntax: Parameter:

COMPILER<type>[,SINGLECHIP]

type

ARM Kernel

ARM IAR GNU

SINGLECHIPEnables the generation of a system with limited memory consumption. Example


COMPILER COMPILER ARM IAR,SINGLECHIP

Users Guide / 4.6

C Compiler 45

4.2

Target Name
This entry allows you the give your target a specific name. The target name will be displayed in the OSE Illuminator system level debugger and can be used in OSE Linkhandlers to access targets in a distributed environment.

Description:

Syntax:

TARGET_NAME

<name>

Parameter: Example

name

User defined character string

TARGET_NAME

motcon

ARM Kernel
46 Target Name

Users Guide / 4.6

4.3

CPU Type
The possible CPU types are ARM7TDMI (includes all ARMv4T derivatives), ARMv5T (includes also ARMv5TE) and XSCALE. This declaration must always be present.
CPU <type>

Description:

Syntax:

Parameter:

type

ARM7TDMI ARMV5T XSCALE


ARM7TDMI

Example
CPU

ARM Kernel
Users Guide / 4.6

CPU Type 47

4.4

Memory Model
Defines the endian type. Select LITTLE for little endian and BIG for big endian. This declaration must always be present. This item must correspond with compile and debug options.

Description:

Syntax:

MEMORY_MODEL

<model_type>

Parameter: Example

model_type

LITTLE BIG

MEMORY_MODEL

LITTLE

ARM Kernel
48 Memory Model

Users Guide / 4.6

4.5

Debug Option
The debug option enables some of the error checks and also makes it possible to use the Illuminator debugger. If debug is not enabled, there is a substantial reduction of the code size of the operating system. There is also an increase in execution speed. This declaration must always be present.
DEBUG <state>

Description:

Syntax:

Parameter: Example

state

YES NO

DEBUG

YES

ARM Kernel
Users Guide / 4.6

Debug Option 49

4.6

Buffer Check Option


If a user process obtains a buffer from ALLOC, it must not write beyond the end of that buffer. Should the process do so, this will probably cause erratic system crashes. Such errors are difficult to detect. If you select the buffer check option, OSE Epsilon for ARM will detect buffer overwrite errors and also suggest the process responsible. Without the buffer check option only scanned information will be available after a buffer handling error. If buffer check is selected, each buffer will require another four bytes. There is also a substantial performance penalty for the SEND, RECEIVE, RECEIVE_W_TMO, RECEIVE_ALL_BUT and ALLOC, FREE system calls. The buffer check option requires the debug option (see Debug Option on
page 49). This declaration must always be present.

Description:

ARM Kernel

Syntax:

BUFFER_CHECK

<state>

Parameter: Example

state

YES NO

BUFFER_CHECK

YES

50 Buffer Check Option

Users Guide / 4.6

4.7

Stack Check Option


It is a fatal error to run out of stack for a process. The system will crash and it may prove very difficult to locate errors of this kind. If stack check is selected the operating system will check for failed stacks and the erroneous process may be revealed. It will check the interrupt stacks, the temp stack an the current process stack. The stack check will be executed at every system tick. This declaration must always be present.

Description:

Syntax:

STACK_CHECK <state>

Parameter: Example

state

YES NO

STACK_CHECK

YES

ARM Kernel
Users Guide / 4.6

Stack Check Option 51

4.8

Option Debugger
This option is used to enable the possibility to connect the OSE Illuminator System Level Debugger.
OPTION DEBUGGER,<type>

Description:
Syntax:

Parameter

type

NO No system level debugger will be used. ONCHIP, <max. trace>,<max. evact> This option is used to enable the possibility to connect the OSE Illuminator System Level Debugger over a serial line interface to the target system. Please consult the OSE Illuminator manual for more information. <max. trace> Maximum number of entries in the trace ring buffer of the target OSE debugger. <max. evact> Maximum number of entries in the evact table of the target OSE debugger.

ARM Kernel

Example
OPTION DEBUGGER,NO

52 Option Debugger

Users Guide / 4.6

4.9

Option Conditional Halt


If this option is selected, timer interrupt processes are taken into account when calculating the time possible to halt the system at conditional halt (system call cond_halt). This declaration is optional. If this entry is omitted, the default setting is: NO.

Description:

Syntax:

OPTION COND_HALT_W_TIMINT,<switch>

Parameter: Example

switch

YES NO

OPTION COND_HALT_W_TIMINT,YES

ARM Kernel
Users Guide / 4.6

Option Conditional Halt 53

4.10 Option Dispatcher in RAM


Description: If this option is selected, the OSE dispatcher will be placed in a separate section which can be placed in RAM. The section name is OSEDSP (ADS 1.1, GNU) or FARFUNC_A_I (IAR). This can improve the performance of the system. The size of the dispatcher is 128 bytes. This declaration is optional. If this entry is omitted, the default setting is: NO.
Syntax: OPTION DISPATCHER_IN_RAM,<switch>

Parameter: Example

switch

YES NO

OPTION DISPATCHER_IN_RAM,YES

ARM Kernel
54 Option Dispatcher in RAM

Users Guide / 4.6

4.11 Pool Size


Description: Defines the size of the buffer pool in bytes. The pool must be able to contain all buffers used at any one time. This declaration must always be present. The Pool will be placed in section OSEPOOL.
Syntax: POOL <size>

Parameter:

size

The buffer pool size in bytes. 48..4294967292 The limits are determined by system design. (Refer to Memory Requirements in Building a System.)

Example
POOL 2000

ARM Kernel
Users Guide / 4.6

Pool Size 55

4.12 Buffer Sizes


Description: There are eight buffer sizes available. Each of these can be selected in the range 4..4294967292. When a process allocates a buffer, one of the eight buffer sizes will be chosen. The buffer size chosen will be large enough to contain the requested number of bytes. If the size is larger than required, a number of bytes will be unused. In order to waste as little memory as possible, you should select buffer sizes to match those of the buffers your system will actually use. NOTE that the sizes must be declared in ascending order and must be a multiple of 4 (integer aligned). This declaration must always be present.
Syntax: BUFFERSIZES <size1>,<size2>,<size3>, <size4>,<size5>,<size6>, <size7>,<size8>

ARM Kernel

Parameter:

size1 size2 size3 size4 size5 size6 size7 size8

Buffer size 1. Buffer size 2. Buffer size 3. Buffer size 4. Buffer size 5. Buffer size 6. Buffer size 7. Buffer size 8. NOTE that sizes must be stated in order of increasing size.

Range: Example

4..4294967292. Size 0 is not permitted.

BUFFERSIZES 32,64,128,256,1024,2048,4096,8192

56 Buffer Sizes

Users Guide / 4.6

4.13 Interrupt Stack


Description: This declaration reserves space for the interrupt stack. The stack is placed in section OSESTACK.
Syntax: ISTACK_SIZE <stacksize>,[<second>]

Parameter:

stacksize second

The extra stack space in bytes. The limits are determined by system design. The second stack is used by nested interrupts only. With nested interrupts, the first stack is used to save the registers, and the second is used for local variables of the interrupt functions. Size estimation: (max nesting level - 1) * 60 for the first stack (max nesting level ) * (max stack usage) for the second stack.

ARM Kernel

Example
ISTACK_SIZE 2048

Users Guide / 4.6

Interrupt Stack 57

4.14 Temporary Stack


Description: This section reserves space for the temporary stack. The stack is placed in section OSESTACK.
Syntax: TEMP_STACK_SIZE <stacksize>

Parameter: Example

stacksize

The extra stack space in bytes.

TEMP_STACK_SIZE

160

ARM Kernel
58 Temporary Stack

Users Guide / 4.6

4.15 Error Handler


Description: This declaration is used to inform the operating system which procedure to call on an error. This declaration is optional and need be present only if an error handler is used.
Syntax: ERROR_HANDLER <name>

Parameters: Example

name

The name of your error handler procedure.

ERROR_HANDLER

ERROR_DISPLAY

ARM Kernel
Users Guide / 4.6

Error Handler 59

4.16 Start Handlers


Description: A start handler is called before OSE Epsilon for ARM is initialised. Initialisation that must take place with interrupts disabled or before any process is started should also be put in a start handler. A start handler written in C may be declared as:
void my_init_of_global_data(void) { . . . };

This declaration is optional and need be present only if test handlers are needed.
Syntax: START_HANDLER <name>

ARM Kernel

Parameters: Example

name S

The name of your test handler procedure.

START_HANDLER START_HANDLER

RAM_TEST my_init_of_global_data

60 Start Handlers

Users Guide / 4.6

4.17 Swap Handler


Description: The swap handler is called by OSE Epsilon for ARM each time a new process is about to be swapped in and also when entering IDLE mode. A swap handler is mostly used by debuggers to collect statistics on process performance. Interrupts are disabled while calling the swap handler. Interrupts must not be re-enabled by the handler and no system calls may be used by the handler. A swap handler written in assembly receives the ID of the next process to run in R0. The swap handler uses the temporary stack. The process ID for the 'idle process' is 0xFF. A swap handler written in C may be declared as:

ARM Kernel

void swap_log(PROCESS prev_id, PROCESS next_id) { . . . };

This declaration is optional and need be present only if a swap handler is needed.
Syntax: SWAP_HANDLER <name>

Parameters: Example

name

The name of your swap handler procedure.

SWAP_HANDLER swaplog

Users Guide / 4.6

Swap Handler 61

4.18 Send Handler


Description: The send handler is called by OSE Epsilon for ARM each time a signal is sent to any process. A send handler is mostly used by debuggers to collect signal trace lists. Interrupts are disabled while calling the send handler. Interrupts must not be re-enabled by the handler and no system calls except SENDER and SIGSIZE may be used by the handler. A send handler written in C may be declared as:
void send_log(PROCESS mysender, PROCESS myaddressee, union SIGNAL *sig) { . . . };

ARM Kernel

This declaration is optional and need be present only if a send handler is needed.
Syntax: SEND_HANDLER <name>

Parameters: Example

name

The name of your send handler procedure.

SEND_HANDLER siglog

62 Send Handler

Users Guide / 4.6

4.19 Receive Handler


Description: The receive handler is called by OSE Epsilon for ARM each time a signal is received by a process. A receive handler is mostly used by debuggers to collect signal trace lists. Interrupts are disabled while calling the receive handler. Interrupts must not be re-enabled by the handler and no system calls except SENDER and SIGSIZE may be used by the handler. A receive handler written in C may be declared as:
void receive_log(PROCESS mysender, union SIGNAL *sig) { . . . };

ARM Kernel

This declaration is optional and need be present only if a receive handler is needed.
Syntax: RECEIVE_HANDLER <name>

Parameters: Example

name

The name of your receive handler procedure.

RECEIVE_HANDLER siglog

Users Guide / 4.6

Receive Handler 63

4.20 Power On Handler


Description: A power on handler must be present if the system shall be able to warm start after it has been powered down by the power off handler. This can happen as a result of using either of the system calls POWER_FAIL or COND_HALT. This procedure checks if a warm or a cold start should be performed. It returns a value other than zero if a warm start is required. A warm start may be used only when the entire memory remains valid since the last time the system was running, and if the system was shut down by the power off handler. If a warm start is required, all I/O ports must be initialized by the power on handler to the values that were current at the time of the POWER_FAIL call. If a cold start is required, I/O ports may instead be initialised by the processes using the I/O. The power on handler can use the system call ADD_TICKS to let the
OSE Epsilon for ARM time system compensate for the time that the system

ARM Kernel

has been powered down. This is particularly useful if the system was powered down as a consequence of the COND_HALT system call. See power off handler for information about how to use ADD_TICKS safely. A power on handler should be written in assemlber because the C system is not yet setup. A power on handler written in assembler should return a int value in R0. This declaration is optional and need be present only if the POWER_FAIL system call is utilised.
Syntax: POWER_ON_HANDLER <name>

Parameters: Example

name

The name of your power on handler procedure.

POWER_ON_HANDLER

my_power_on

64 Power On Handler

Users Guide / 4.6

4.21 Power Off Handler


Description: A power off handler is needed if either of the system calls POWER_FAIL or COND_HALT are to be used. The power off handler acts as a server to both these system calls. In the case of POWER_FAIL the power off handler should prepare the system for a warm start by performing an orderly shut down. The other option is to handle COND_HALT. This mechanism is intended to put the system in a 'light sleep' that enables the system to conserve power while still maintaining operation of time-outs, delay and timer if CONDHALT_W_TIMER is set, and possible some other external hardware. In this case the timer hardware should be setup to wake up the system after a time that is determined by the idle_ticks parameter. The handler should then proceed by either halting the processor or performing an orderly shut down. The choice depends on the available hardware capabilities of the system. Perhaps the system shall be halted for short sleep time and powered down for long sleep times.

ARM Kernel

The power off handler is called with interrupts disabled. The parameter is idle_ticks: zero => power fail not equal zero => cond_halt ticks

A power off handler written in C may be declared as: (This example deals with COND_HALT by halting the processor)
void my_power_off(OSTICK idle_ticks) { If (idle_ticks != 0) { <Prepare timer to wake up after idle_ticks> <Halt processor> <Re-initialies timer and call ADD_TICKS> } else { <Save current state of all I/O ports.> <Set warm start flag.> <Create ram checksum and save it.> <Turn off power and enforce hardware reset.> } }

Users Guide / 4.6

Power Off Handler 65

The above pseudo code contains a few tricky parts that need further explanation. They concern handling of the timer and the halt mechanism: It is assumed that the halt mechanism wakes up by an interrupt. It should never fall asleep if an interrupt is pending when the halt operation is performed. It is also assumed that the processor continues executing on the instruction after halt when the interrupt arrives. The interrupt should be serviced as soon as a interrupts are enabled (when the handler is exited). It is imperative that the halt mechanism does not lack any of these properties. Otherwise the algorithm described here will be prone to dead-locks. One tricky aspect o handling timer chips is that they may wrap around and cause an interrupt during the execution of the handling code. The software must deal with this in some way. The idle_ticks parameter defines how many ticks may be skipped without disturbing the OSE Epsilon for ARM time-out, delay and timer system. The timer hardware should be adjusted to generate an interrupt that many system ticks later than planed. E.g. if idle_ticks is 3 and the timer hardware has 27% of a tick time remaining until the next interrupt, it should be reinitialized to generate an interrupt after 3,27 tick times. It is also possible that the timer issues an interrupt during the execution of this code, e.g. resulting in a pending interrupt and 99% of a tick time until the next tick. This must be detected and countered. In this case by initialising the timer to 2.99 tick time and clearing the pending interrupt. The processor can wake up from halt by any interrupt. I.e. it could be woken up either by a timer interrupt or another interrupt, whichever occurs first. The software should be able to handle both cases, perhaps by checking if a timer interrupt is pending. (Remember that interrupts are disabled during the execution of the handler.) The timer should be re-synchronised to generate interrupts at tick intervals. This should be done without disturbing any pending interrupts. The system call add_ticks should be called with the number of ticks that have been skipped during the halt time. This value should never be more than the idel_ticks parameter. Note that the time will usually be one more than the idle_ticks parameter if the time expired. In this case the last tick should be handled by a call to OSE_TIMER_ENTRY, for more information see appendix. This will happen naturally when the system handles the pending interrupt, provided that the interrupt is not cleared by the reinitialisation of the timer.

ARM Kernel
66 Power Off Handler

Users Guide / 4.6

If the system sleeps by powering down instead of by using a halt mechanism, the code for reinitializing the timer and updating the system timer must reside in the power on andler. This declaration is optional and need be present only if either the POWER_FAIL or the COND_HALT system call is utilised.
Syntax: POWER_OFF_HANDLER <name>

Parameters: Example

name

The name of your power off handler procedure.

POWER_OFF_HANDLER

my_power_off

ARM Kernel
Users Guide / 4.6

Power Off Handler 67

4.22 Idle Handler


Description: The Idle Handler is called whenever no processes are in the ready state (i.e. no processes want the CPU to execute). The Idle Handler uses the temporary stack. Consult also Temporary
Stack on page 58.

Note that the Idle Handler must never end. It is an error for an Idle Handler to execute a return statement. This declaration is optional and need be present only if an idle handler is needed.
Syntax: IDLE_HANDLER <name>

Parameters: Example

name

The name of your idle handler procedure.

IDLE_HANDLER

my_idle

ARM Kernel
68 Idle Handler

Users Guide / 4.6

4.23 Fast interrupts as IRQ:s


Description: If you plan to use fast interrupts (FIQ:s) as normal interrupts set this option to YES. FIQ:s will then be disabled and enabled at the same time as IRQ:s. If this option is NO FIQ:s are not touched by the OSE Epsilon for ARM kernel
FIQ_AS_IRQ <switch>

Syntax:

Parameters: Example

switch

YES NO

FIQ_AS_IRQ YES

ARM Kernel
Users Guide / 4.6

Fast interrupts as IRQ:s 69

4.24 Interrupt Processes


Description: Enter the names of the interrupt processes in your system. Note that several steps are needed before an interrupt process is completely installed:
The interrupt process must be declared. The interrupt handler must be modified to recognise the interrupt source,

and call the interrupt process entry code.


The interrupt process entry code is created by OSE Epsilon for ARM. When

calling the entry code from your interrupt handler, add OSE_ to the named declared below. The interrupt process should not be called directly from the interrupt handler.
The interrupt process is called from ARM-mode. Therefore interworking

should be enabled for thumb-mode routines.


The interrupt generating hardware must be initialised.

ARM Kernel

These declarations are optional and need be present only if interrupt processes are needed.
Syntax: INT_PROC <process_name>

Parameter: Example S

process_name The name of a process.

INT_PROC INT_PROC INT_PROC

bandersnatch LINK_TRANCEIVER SERIAL_0

70 Interrupt Processes

Users Guide / 4.6

4.25 Timer Interrupt Processes


Description: Enter the names of the timer-interrupt processes in your system. Timer-interrupt processes are called with configurable period. The period between calls is expressed in system ticks. The period is 1..4294967295. These declarations are optional and need be present only if timer-interrupt processes are needed.
Syntax: TI_PROC <process_name>,<call_interval>,[,init]

Parameters:

process_name The name of a process. call_interval The interval between calls to the process.Range: 1..4294967295. init Initial delay. This an optional parameter. A timer interrupt process starts normally at time 0 at system start. You can give an initial delay before the interrupt will be started. Range: 1..4294967295.

ARM Kernel

Example
TI_PROC TI_PROC tnuctipun,155 poll,100,10

Users Guide / 4.6

Timer Interrupt Processes 71

4.26 Prioritized Processes


Description: Enter the names of the prioritized processes in your system. A priority is specified for each process A process of higher priority runs before every process of lower priority. If several processes have the same priority they are chosen from in a first ready, first served fashion. At startup the prioritized processes are made ready in the order they appear in the osarm.con file. These declarations are optional and need be present only if prioritized processes are needed.
Syntax: PRI_PROC <process_name>,<stacksize>, <priority>[,mode]

Parameters:

process_name The name of a process. stack_size The requested size in bytes for the stack of the process. Range: 160..4294967295. priority The requested priority for the process. 0 = highest priority, 31 = lowest priority. Optional CPU mode SYS (default) USR

ARM Kernel

mode

Example
PRI_PROC PRI_PROC PRI_PROC my_process,128,1 outsider,128,19 SLAVER,128,15

72 Prioritized Processes

Users Guide / 4.6

4.27 Link Handler Processes


Description: A Link Handler is an ordinary prioritized process. Link handlers are needed to build distributed OSE systems with message based transparent communication. The Link Handler will receive all signals which are sent to processes with a pid of higher than 255. This entry will assign a name and define some parameters for the link handler. There is only one link handler allowed in an OSE Epsilon for ARM system.
Syntax: LINKHANDLER <process_name>,<stacksize>, <priority>[,mode]

Parameters:

process_name The name of the link handler process. stack_size The requested size in bytes for the stack of the process. Range: 160..4294967295. priority The requested priority for the process. 0 = highest priority, 31 = lowest priority. Optional CPU mode SYS (default) USR

ARM Kernel

mode

Example
LINKHANDLER my_link,128,10

Users Guide / 4.6

Link Handler Processes 73

4.28 Background Processes


Description: Enter the names of the background processes in your system. All background processes are of equal priority and the order in which they are declared is of no importance. These declarations are optional and need be present only if background processes are needed.
Syntax: BG_PROC <process_name>,<stacksize>, <timeslice>[,mode]

Parameters:

process_name The name of a process. stack_size The requested size in bytes for the stack of the process. Range: 160..4294967295. timeslice The number of system ticks the process will be allowed to run before being swapped out. Range: 160..4294967295. mode Optional CPU mode SYS (default) USR

ARM Kernel

Example

S
BG_PROC BG_PROC background_tests,128,12 THRINT,1024,1

74 Background Processes

Users Guide / 4.6

4.29 Enable Wake Up


Description: This option enables the operating system to activate the interrupt process or timer interrupt process, if a signal is received from a prioritized or background process. System call wake_up() must be used to determine whether it was activated by hardware or by the operating system.

Syntax:ENABLE_WAKE_UP <state>

Parameter: Example

state

YES NO

2
YES

ENABLE_WAKE_UP

ARM Kernel
Users Guide / 4.6

Enable Wake Up 75

ARM Kernel
76 Enable Wake Up

Users Guide / 4.6

5 Building a System
To build a system, do the following: 1. Determine the specifications of the system, such as functions, speed requirements, environment etc. 2. Design the system, i.e. determine hardware configuration, memory usage, interrupt structure, processes and process interface. 3. Select the files you need from the OSE Epsilon for ARM installation and copy them to your working directory. 4. Modify the system files for the used board. This should include at least the system initialization functions, the interrupt handler and a tick timer setup file. You can find examples of such files in the Board Support Package delivery. 5. Configure the system, that is, enter configuration data into the configuration file osarm.con.

ARM Kernel

Run confarm.exe to create the assembler file osarm.*. Ensure you have the correct version of osarm.con. File extensions differ from compiler to compiler (e.g. ARM: *.s, GNU *.S, IAR: *.s79). 6. Generate the ARM kernel by assembling the file osarm.*. 7. Write your signal specifications. A reasonable approach is to have a small set of related signals in each include file. If you are using the OSE Soft Kernel, you should keep your signal specifications consistent with Softkernel demands. 8. Write your processes and compile/assemble them. 9. If you have selected the debug option (OPTION DEBUGGER) in the osarm.con configuration file the Debug Kernel will be generated and you also need a communication module to connect the Debug Kernel to the host. For an asynchronous serial line connection, you can find a driver in the OSE Epsilon for ARM Board Support Package. 10.We recommend that you also write an error handler if you have a display device in your target system. An error handler may display errors quickly and conveniently during debugging 11.Link the generated kernel, the bsp system files, your processes, your handlers and the compiler library together to form the target binary file.

Users Guide / 4.6

Building a System 77

The following diagram shows the process for building a system:

Configuration osarm.con

osarm.mac (osarm_sc.mac) Include Assembler System Files

confarm

osarm.anc osarmi.anc Include

ose.h ose_i.h ose_usr.h Include Processes and user files written in C

osarm.s (ARM) osarm.s79 (IAR) osarm.S (GNU)

Processes and user files written in assembler

ARM Kernel

Assemble

Compile

clib

Link

See also:

System Files on page 79 Configuration on page 79 Configuration Utility on page 79 Illuminator System Level Debugger on page 79 Assembly-Time Errors on page 80

78 Building a System

Users Guide / 4.6

5.1 System Files


To setup an OSE Epsilon for ARM system, you will need a few system files. These are:

crt0.* inthdir.* timer_setup.* File extensions will differ from compiler to compiler (e.g. ARM: *.s, GNU *.S, IAR: *.s79).

Examples of these system files can be found in the OSE Epsilon for ARM board support package delivery. If your board is not supported, you can use these system files as templates.

5.2 Configuration
The OSE operating system can be configured to have completely different characteristics depending on the trade-offs you want to make between speed, memory consumption and code size. The configuration is accomplished by entering the desired values into the osarm.con configuration file. As shipped, osarm.con contains a configuration suitable for a typical system. Browse through it and change the settings as required for your application. If you are unsure about a setting use the current setting. However, you must always define the names of the processes in your particular system.

ARM Kernel

5.3 Configuration Utility


When the configuration is satisfactory, you must run the confarm.exe configuration utility. This will create the kernel file osarm.*. The confarm command syntax is:
confarm input_file [output_file]

For every change in the osarm.con configuration file, the confarm.exe utility must be executed again.

5.4 Illuminator System Level Debugger


If you have selected the debug option (OPTION DEBUGGER) in the osarm.con configuration file the Debug Kernel will be generated. You also need a communication module to connect the debug module of the kernel to the host. For an asynchronous serial line connection a serial driver is included in the board support package delivery.

Users Guide / 4.6

System Files 79

5.5 Assembly-Time Errors


Many configuration errors are detected by OSE when you run the configuration utility and assemble the operating system. OSE does not attempt to detect errors which the assembler will find. Assembler error messages should enable you to correct most of these errors. Never attempt to correct assembly time errors until all OSE Epsilon for ARM configuration errors have been corrected. This is because OSE Epsilon for ARM configuration errors also generate assembler errors.

ARM Kernel
80 Assembly-Time Errors

Users Guide / 4.6

6 System Design
OSE Epsilon for ARM is a fast, compact, real-time operating system for the ARM line of microprocessors from ARM Ltd. OSE Epsilon for ARM is designed exclusively to fit the peculiarities of the ARM processor family. Every conceivable effort has been made making OSE Epsilon for ARM as fast as possible. The entire system is written in heavily optimized assembler. The data structures are designed to fit the processor memory structure and the specific system calls. Tasks which traditionally have been left to the user to accomplish as best he can has been taken over by the operating system. Most of the design effort has been spent in selecting and tuning a set of system calls which provides maximum system performance. Speed is not always paramount. At times it is necessary to preserve code memory. This can be done in two ways when using OSE Epsilon for ARM. In a small system the size of the operating system itself may be a problem. Should such be the case you may use OSE in a minimum code configuration. If the system is large, the size of the operating system will be a minor problem since it is inherently small.

ARM Kernel

A system under OSE Epsilon for ARM consists of a number of independent subprograms called processes. A process may be written to some extent as if it had the entire CPU for its own exclusive use. By assigning a priority to each process, OSE Epsilon for ARM ensures that the right process is always executing. An event which requires another process with a higher priority to execute, forces an immediate switch of process. This scheme ensures fast response to important events. Processes co-operate by exchanging signals. A process may send a signal to the mailbox of another process to inform the receiver of an event or to respond to an event. Signal transmissions often cause execution to switch to another process (a task switch). A signal is a dynamically allocated message buffer containing a signal number and an optional data structure. Signal numbers are used to select which signals to receive, while leaving others in the mailbox of the receiving process. It is possible to ignore events which are unimportant at the moment simply by selecting which signals to receive. Other processes use the CPU while a process is waiting for a signal to arrive. Unused message buffers are stored in the central buffer pool until allocated by a process. Only one process at a time may access a signal (or message buffer), thereby eliminating conflicts. If a process needs to suspend execution for a specific interval of time, it calls OSE which monitors time and activates other processes during the wait.

Users Guide / 4.6

System Design 81

For more information on system design, see:


System Creation Cycle on page 83 Processes on page 84 Starting and Stopping Processes on page 93 Signals on page 94 Fast Semaphores on page 97 Semaphores on page 97 Memory Utilisation on page 98 Speed Considerations on page 102 System Start on page 104 Writing the Interrupt Handler on page 104 Writing a Link Handler on page 106 Writing an Error Handler on page 108

ARM Kernel

82 System Design

Users Guide / 4.6

6.1 System Creation Cycle


This chapter contains information on how to create a system using OSE Epsilon for ARM. It discusses major design parameters such as memory usage, speed factors and interrupts. It also takes you through the various phases of programming, from writing the first line of the first process until catching the last bug. Specification techniques are outside the scope of the manual, however. The first step in the design process is to divide the system into a number of processes. Concurrent events should be handled by separate processes. That is, if two things may occur at the same time, they should be handled by different processes. For example, in a terminal, the operator may be typing at the keyboard while the computer sends characters to the terminal. In the division of work between processes, one important consideration is to minimize the interface between processes. That is, they should have as little as possible to do with each other. Another design consideration is to avoid very small and very large processes. It is also desirable not to have processes share hardware. Once the system is divided into processes, the interface between them is described by defining the signals to be exchanged. The processes, the sequence of events and timing are probably described using some specification and description language. When the system has been designed, the processes are written, either in C or assembly. We suggest that you use the process templates provided in the appendixes. Each process is put in a separate file and these are compiled/assembled. When this is done, the operating system must be assembled. Then the system is linked. The system is now ready to run. It is possible that errors have been made in the system design, in the writing of the processes, in the configuration of the operating system or in the linking command. Should such be the case, the error(s) must be detected and located during the process of debugging. The OSE Illuminator debugger is a useful tool when trying to find errors.

ARM Kernel
Users Guide / 4.6

System Creation Cycle 83

6.2 Processes
A process is an independent program running under OSE. In every instant of time, the most important process ready to run is running. As soon as a more important process wants to run the current process is removed from the CPU and the new process is entered and allowed to run. This is called a task switch. If you are running a system without OSE, the processor will often find itself unable to respond quickly to an event since the wrong part of the program is running and continues to do so for some time. There are several types of processes to allow you to run each part of your program at the right moment. The process types differ mainly in the way in which they are activated and in the way they use memory. The total number of processes of all types may not exceed 254. Each process is associated with a unique process identity, which is used in system calls to select the process. This identity is allocated by the operating system during system start, and it is placed in a global variable where it can be accessed by other processes. This variable is named as the process with an appended underscore character. E.g. a process named "keyboard" has an id which is placed in a variable named "keyboard_".

ARM Kernel

In the ..\example directory of the OSE Epsilon for ARM Installation you will find process example files. Processes are further described in:

Prioritized Processes on page 85 Background Processes on page 86 Interrupt Processes on page 87 Timer Interrupt Processes on page 88 Selecting Process Type on page 89 Process Include Files on page 90 Process Declarations in C on page 91 Process Declarations in Assembler on page 92 Process Design Rules on page 93

84 Processes

Users Guide / 4.6

6.2.1 Prioritized Processes


Prioritized processes are the most common processes in a typical system. Prioritized processes have a strict order of priority. The highest priority process will always run before every other process. The lowest priority process will be allowed to run only when no other prioritized process is ready. If two processes are assigned the same priority, the choice of precedence between the two processes is made by OSE Epsilon for ARM. When a process has no further work to do for the moment, it becomes not ready. A process is not ready when it is waiting for a message or when it is waiting for a delay to end or when it is waiting at a semaphore. A process is swapped out from the CPU when it becomes not ready or when a process of higher priority becomes ready. Note that a process may be interrupted between almost any two assembler instructions and in the middle of any C instruction. A process is swapped in if all processes of higher priority are not ready and the process itself is or becomes ready. A prioritized process may use all system calls. When a prioritized process returns from a call to RECEIVE it may be certain that a signal is available.

ARM Kernel

Note that a prioritized process must never end. When its task is done it should loop back to the beginning and wait for another request for its services. If it is certain that it will not again be needed, it may call STOP to stop itself. It is an error for a process to execute a return statement. Prioritized processes may be written either in assembly or C.

Users Guide / 4.6

Prioritized Processes 85

6.2.2 Background Processes


These are identical to prioritized processes except that they do not have priority. A background process will only be allowed to run when no prioritized process is ready. The time left over when no prioritized process is running is divided between ready background processes. Running background process is switched by the operating system at user defined intervals. A background process is allowed to execute until it becomes not ready or a prioritized process becomes ready or until the background process has executed for the duration of the user defined interval. Background processes may be written either in assembly or C.

ARM Kernel
86 Background Processes

Users Guide / 4.6

6.2.3 Interrupt Processes


An interrupt is a hardware generated event which will cause the system to suspend the currently running background or prioritized process and turn control over to the interrupt process dedicated to that particular interrupt. There can exist only one interrupt process for each of the available hardware interrupt vectors. An interrupt process is called as a subroutine whenever its interrupt occurs, provided that no other interrupt is running. As long as an interrupt process is running, other interrupts are not permitted by the CPU. This means that interrupt processes prevent other interrupts, with the same or lower priority, while they execute. Interrupt latency for a certain interrupt process is therefore roughly determined by OSE Epsilon for ARM internal interrupt latency (see section on speed considerations) added to the execution time of the sum of all interrupt processes of the same or higher hardware priority. If this is not acceptable, interrupts can run outside the OSE Epsilon for ARM. In that case, no system call may be executed. An interrupt process will never become not ready, but is running from beginning to end each time it is activated. It is thus impossible for an interrupt process to wait for a signal or make a delay. Should it be allowed to do so it would stop almost all other activity in the system. If receive is called it will immediately return, even if there was no signal in the queue. No interrupt processes exist for the fast interrupt and illegal instruction trap. These events are served by optional handlers (NMI-handler, trap-handler etc.), which are not processes and may not execute any OSE system calls. OSE Epsilon for ARM does not interfere with these handlers except that the trap vectors are defined by the start-up code (init.s). Interrupt processes may be written in C or assembly. All interrupt processes share a common stack, which size is determined by the largest interrupt stack defined in the configuration. All interrupt processes will be enabled before the first prioritized processes called. Code which must be executed before interrupts are enabled, must reside in OSE_INIT_INTERRUPT which is located in the file INTHDLR.S. This code may also be included in the POWERON_HANDLER or in the START_HANDLER, both of which may be declared in the configuration file osarm.con. Note that several steps are needed before an interrupt process is completely installed:

ARM Kernel

The interrupt process must be declared. The interrupt handler must be modified to recognise the interrupt source, and call the interrupt process entry code. The interrupt process entry code is created by OSE Epsilon for ARM. When calling the entry code from your interrupt handler, add OSE to the name declared in the osarm.con. The interrupt process should not be called directly from the interrupt handler. The interrupt process is called from ARM-mode. Therefore interworking should be enabled for thumb-mode routines. The interrupt generating hardware must be initialised.
Interrupt Processes 87

Users Guide / 4.6

6.2.4 Timer Interrupt Processes


Timer interrupt processes work like interrupt processes except for the manner in which they are called. For each timer interrupt process the user selects a number of system ticks to elapse between each call to the process. Timer interrupt processes should be short because they must be fast enough to permit all of them to execute during one system tick. If this is not possible, the process has been incorrectly designed, and parts of the task should be performed in a prioritized process. Timer interrupts have the same priority as the interrupt source, which generated the system tick. Other interrupts with higher priority then the timer interrupt may run as normal. Timer-interrupt processes are called with configurable period. The period between calls is expressed in system ticks. The period is 1..4294967295. Timer-interrupt processes will start at the first timer-interrupt. Many timer-interrupt processes have variables which must be initialised in a START_HANDLER or as initialised static variables if the process is written in C. Timer interrupt processes may be written either in assembly or C.

ARM Kernel
88 Timer Interrupt Processes

Users Guide / 4.6

6.2.5 Selecting Process Type


Interrupt processes respond to events faster than any other process type. On the other hand, they must perform their task in a very short time. Imagine, for instance, an interrupt process whose task is to receive characters from the serial link. When a character has arrived, the process must quickly store it in a buffer. If this takes too long, the next character will be lost. When all the characters of a message have been received, some program must analyse and work with the message. This often takes much longer than the time between characters sent on the serial link. The interrupt process therefore sends the message to a prioritized process. The prioritized process will respond much slower than the interrupt, but, on the other hand, it can spend a long time working with the message. When the message is taken care of, the process waits for the next message, thus freeing the CPU for other processes. Prioritized processes also have different priorities thus enabling a more important process to interrupt a less important one. Suppose that a system has a routine which performs tests such as memory checks. These should be run as often as possible, but they should never subtract from system performance by using up time for more important work. Here, a background process is ideal, since it executes only when no interrupt or prioritized process is running. Timer-interrupt processes may be used for polling purposes. This type of task, for instance checking the status of a bit or a byte, can be done either by a background process or a timer-interrupt process. The difference is that a timer-interrupt process will check at well defined moments in time whereas background processes will check only when the system idles. If a measurement, for example a voltage, is to be sampled at regular intervals you might do this in a background process. It might sample the voltage, then make a delay, sample the voltage etc. If, however, other processes of higher priority should run, samples will be lost. To avoid this, a timer-interrupt process can be used since it would ensure that no samples are lost.

ARM Kernel
Users Guide / 4.6

Selecting Process Type 89

6.2.6 Process Include Files


The user interface to OSE Epsilon for ARM is defined in a number of C header and assembler include files, which should be included in an OSE Epsilon for ARM application.
Prioritized and Background Processes written in C must include the file ose.h.

Prioritized and Background Processes written in C and running in USR mode must include ose_usr.h

Interrupt and Timer Interrupt Processes written in C must include the file ose_i.h Prioritized and Background Processes written in Assembler must include the file

osarm.anc.

OSE Interrupt and Timer Interrupt Processes written in Assembler must include the file osarmi.anc.

ARM Kernel
90 Process Include Files

Users Guide / 4.6

6.2.7 Process Declarations in C


6.2.7.1 Prioritized and Background Processes

Prioritized and Background Processes written in C must contain the declaration:


OS_PROCESS (my_process) {}.

C Syntax:
OS_PROCESS (<process_name>) { /* Code for process <process_name> */ }

where the parameter process_name is the name of the process

6.2.7.2 Interrupt and Timer-Interrupt Processes

Interrupt and Timer-Interrupt Processes written in C must contain the declaration:


OS_INT_PROCESS (my_process,int_src) {}.

ARM Kernel

You have to declare a second parameter for Interrupt and Timer-Interrupt Processes which holds the information from what source the interrupt occurred. The source can be: 1. The real hardware interrupt. 2. A signal sent to the process. 3. The fast semaphore was signalled. C Syntax:
OS_INT_PROCESS (<process_name>,<int_src>) { . . . }

Parameters: process_nameThe name of the process

int_src

Source of interrupt (variable, type int): 0 Invoked by hardware interrupt 1 Invoked by signal sent to this process 2 Invoked by a SIGNAL_FSEM to this process. This irrespective of the actual FSEM value. GET_FSEM gives no real value.

Users Guide / 4.6

Process Declarations in C 91

6.2.8 Process Declarations in Assembler


6.2.8.1 Prioritized and Background Processes

Prioritized and Background Processes written in assembler must contain the declaration:
PROCESSMY_PROCESS.

Assembler Syntax:
PROCESS <process_name> ; ; Process entrypoint. This is ; ; where the process is called ; ; from the operating system. . . .

Parameter:process_nameThe name of the process

6.2.8.2 Interrupt and Timer-Interrupt Processes

ARM Kernel

Interrupt or Timer-Interrupt Processes written in assembler must contain the declaration:


OS_INT_PROCESS <my_process>

For Interrupt and Timer-Interrupt Processes the register R0 holds the information from what source the interrupt occurred. The source can be: 1. The real hardware interrupt. 2. A signal sent to the process. 3. The fast semaphore was signalled.
Assembler syntax: OS_INT_PROCESS <process_name> ; ; Process entrypoint. This is where the process ; ; is called from the operating system. ; ; ; ; Test register R0 for source ; ; of interrupt. . . END

Parameter:process_nameThe name of the process R0 Source of interrupt (register R0): 0 1 2 Invoked by hardware interrupt Invoked by signal sent to this process Invoked by a SIGNAL_FSEM to this process.

92 Process Declarations in Assembler

Users Guide / 4.6

6.2.9 Process Design Rules


There are some mistakes in writing processes which can not be detected by OSE. They may cause a lot of trouble for, once made, they can be difficult to find. To avoid them, follow these few design rules carefully:

Avoid doing several things at a time in a process. Concurrent work should be in different processes. Do not send lots of signals from a process without waiting for a reply once in a while. Remember that the receiving process may not run at all until the sender becomes not ready. Avoid taking advantage of knowledge on process priorities when designing a system. Priorities should be used only to promote fast response to the environment. A well designed system uses only a few priority levels. If a procedure is called from more than one process, the procedure must be re- entrant or interrupts must be disabled while the procedure is executing. Do not use global variables. If you must, then disable interrupts while accessing them. Do not share ports between processes. Shared ports must be treated as global variables. Never modify buffers after they have been sent to other processes. Avoid using large auto arrays in C processes. If these are instead declared static, stack requirements are much easier to determine. Make sure the correct version of osarm(i).anc is included in an assembler process.

ARM Kernel

When testing your system, always have a breakpoint set on the label Q_ERR in osarm.s. If this breakpoint is reached, an error has occurred. (For details on errors, refer to RunTime Error Messages.) If you forget this breakpoint, the system will be unable to inform you of errors.

6.3 Starting and Stopping Processes


A system where processes are stopped and started needs careful design, since it may easily hang. The start/stop feature is intended mainly for debugging. If start/stop is to be used, it is safer only to allow a process to stop itself. If processes are allowed to stop each other, a process may be stopped while communicating with a third process. That process may then hang and thus fail to respond to the first, stopping, process which in its turn may then hang. The result is that the stopped process may never be started again. There are several other ways to create unstable systems using start and stop, so do not use these calls unless you have to.

Users Guide / 4.6

Process Design Rules 93

6.4 Signals
Signals are messages sent between processes. Each message is a buffer, an area of memory, where processes may read and write data. A buffer may be used by many different processes, but only one process at a time may access a buffer. Signals not only carry data, they also initiate actions by the various processes. All processes can exchange signals, even those residing in other computers. (Through the use of a link handler.) Before a signal can be sent a buffer must be allocated and the data, if any, must be entered into the buffer. The signal number, which must always be present, is entered by the operating system when the buffer is allocated, but may be altered by the user if convenient. The signal number is always the first word of a buffer. When a process gains access to a signal buffer by allocating it or receiving it, the process becomes the owner of the buffer. Only the owner may perform operations on the buffer. Once a signal has been sent to another process it can no longer be accessed by the sending process. A process may select the signals it is interested in receiving at any particular moment. The process will then wait for signals to arrive. Meanwhile, other processes are allowed to execute.

ARM Kernel
94 Signals

Users Guide / 4.6

6.4.1 Using Signals In Processes


It is a fatal error to write beyond the end of an allocated buffer. Such errors may be detected if you select the BUFFER CHECK option when configuring the system. If you do not, the system will simply crash and you will find it exceedingly difficult to find out why. When writing in C, the method for accessing and allocating buffers described below minimizes the risk for buffer overwrite errors. It also provides code which is easy to read. To achieve maximum speed you should manipulate the pointers yourself, preferably in assembly. Declare each signal as shown in the signal template. Each part of the signal buffer is endowed with a name in the structure declaration of the signal. Use the structure to decide the size of the buffer to allocate. (For a more detailed example, refer to Sample Signal.)
Syntax: #define<SIG_NAME>(<value_1>) struct <sig_name> { SIGSELECT sig_no; <member_type> <member>; . . }; union SIGNAL { SIGSELECT sig_no; struct <sig_name> <sig_name>; }; union SIGNAL *<buf_ptr>; <buf_ptr>=alloc(sizeof(<struct sig_name>),<SIG_NAME>); To access the signal buffer: <buf_ptr>-><sig_name>.<struct_member> = <value_1>;

ARM Kernel

Parameters: sig_nameThe name of the signal struct_memberSome data of the signal SIG_NAMEA number 0..32767 which identifies the signal. value_1A variable name or number.

Users Guide / 4.6

Using Signals In Processes 95

Example
#define MY_SIGNAL (17) struct my_signal { SIGSELECT sig_no; char character; }; union SIGNAL { SIGSELECT sig_no; struct my_signal my_signal; }; union SIGNAL *sig_ptr; sig_ptr = alloc( sizeof(struct my_signal), MY_SIGNAL ); To access the signal buffer:

ARM Kernel

sig_ptr->my_signal.character = 0xd;

6.4.2 Buffer Transfer


At times, buffers are used for other purposes than signal transmissions. Sometimes a buffer may be turned over to another process via a global variable instead of using SEND. If a buffer is transferred from one process to another and the other process tries to send or free that buffer, the result will be an error condition. The operating system will detect that someone is trying to free or send a buffer which he does not own. To avoid this, the process who wants to free/send the buffer must call RESTORE. RESTORE will then note that the calling process is the new owner of the buffer.

96 Buffer Transfer

Users Guide / 4.6

6.5 Fast Semaphores


There is no need to read this chapter unless you have serious response problems in your system. Fast semaphores are intended for those rare cases where user programs cannot use signals due to timing problems. For example, a fast semaphore may be used to count characters in a user implemented buffer between an interrupt process receiving characters and a prioritized process consuming characters. Fast semaphores work like this: A fast semaphore is a signed integer owned by a process. It is operated by system calls WAIT (WAIT_FSEM) and SIGNAL (SIGNAL_FSEM). Only the owner may wait at a fast semaphore. Other processes may signal it. The WAIT operation decrements the value of the semaphore and blocks the calling process (owner) if the result becomes negative. The caller is again allowed to run only if some other process makes the value of the semaphore non negative by issuing a SIGNAL operation. The SIGNAL operation increments the value of the semaphore. If there is a process waiting at the semaphore, it is released if the result becomes non negative.

ARM Kernel

There is one fast semaphore associated with each prioritized or background process. This semaphore must be explicitly initialised by the process before it is referenced the first time by any process (using the system call SET_FSEM). The current value of a fast semaphore may be examined (GET_FSEM) so that semaphore overrun can be avoided.

6.6 Semaphores
Semaphores are somewhat similar to fast semaphores, but they differ in one very important aspect: A semaphore is not related to any specific process. Any background or prioritized process may wait at a semaphore, not just the owner. Any type of process may signal a semaphore. The main purpose of semaphores is to protect critical code sections from concurrent execution (so called mutual exclusion) without disabling interrupts. This is often done to protect global shared resources. If the compiler supports static initialisation of C structures this can be used to declare a semaphore at compile time. Semaphores are mainly used to ensure that only one process at a time is using a global shared resource. As soon as the process currently occupying the resource releases it, it will automatically be given to the next in its waiting queue. Use the wait_sem system call to get in line to use the resource as soon as possible and the signal_sem system call to releases it as soon as the resource is no longer needed. OSE also implements a simpler form of semaphores for exclusive use by the OSE kernel and associated products. For example, the FLUSH system call uses an internal semaphore to protect internal data structures.

Users Guide / 4.6

Fast Semaphores 97

6.7 Memory Utilisation


6.7.1 Global Variables
It is not recommended to use global variables, that is variables used by more than one process. If processes use global variables/buffers there will be access problems. One process may access the first byte of such a variable, then a change of process occurs before the next byte is accessed. While the process is swapped out, some other processes may change the variable/buffer. Thus, the results of accesses to global variables are unpredictable. Global variables will make it impossible to use some of the most powerful debugging tools available when using OSE. The use of signals is recommended instead of global variables. Processes written using signals only, will also be easy to use in other processors, and in other projects. When designing using signals, simply let every piece of hardware be owned by a process. Other processes send signals to the owner when they need to access that particular hardware. All access problems are then avoided.

ARM Kernel

One way of avoiding global variables is to design the hardware such that processes need not to share it. This is possible if the ports are organized in such a way that the bits needed by one process reside in one port. If global variables are used, interrupts must be disabled/enabled at each access, with the concomitant response time increases.

98 Memory Utilisation

Users Guide / 4.6

6.7.2 Memory Requirements


The amount of code memory and data memory needed in your system is determined by system configuration and design. This section is intended to serve as a guideline when designing your hardware.
6.7.2.1 Memory Used By the Buffer Pool

The buffer pool is a major user of data memory. There are eight fixed, user selected, sizes of signal buffers. Estimate maximum number of buffers of each size used by your system. Each buffer also uses a 12 byte administration block (8 bytes in single-chip version). If the debug option is used, each buffer needs an additional eight bytes. Use the following formula to calculate buffer pool size
POOL = no_of_buffers_size1*size1+no_of_buffers_size2*size2 +no_of_buffers_size3*size3+no_of_buffers_size4*size4 +no_of_buffers_size5*size5+no_of_buffers_size6*size6 +no_of_buffers_size7*size7+no_of_buffers_size8*size8

No_of_buffers is the maximum number of buffers in use at any one time.

ARM Kernel

In a normal system with only a few permanently allocated buffers, something like 2 kilobytes is a reasonable pool size. In a large system, 4-6 kilobytes may be more appropriate.
6.7.2.2 Memory Required By Stacks

Each prioritized and background process must have its own stack. The stack will contain return addresses, local variables and any data that the process may push. The stack must be large enough to contain all data needed at any one time. When an interrupt occurs the interrupt process must have a stack to use during the interrupt. OSE Epsilon for ARM maintains one stack shared by timer-interrupt and interrupt processes. Stack requirements of these processes do not affect the size of the stacks reserved for prioritized and background processes. A process written in C typically requires 160-256 bytes of stack. However, this depends largely on the application. A few C library functions need a lot of stack, maybe 1-2 kilobyte. If a process requires large dynamic arrays or strings it may also need more stack. A reasonable approach is to start with 256 bytes and adjust stacksizes after a while when actual demands can be seen.

Users Guide / 4.6

Memory Requirements 99

6.7.2.3 Memory requirements

Memory requirements are listed in the following tables:

Table 1: RAM requirement for OSE Epsilon for ARM mode: kernel per process, PCB per process, minimum stack Signal header 160 12 160 8 376 68 normal 220 52 single chip

Add stacks, pool size and the amount of memory used by the operating system to find out total data memory needs.

ARM Kernel

Note: There is a 72 byte register save area as well (80 byte for XSCALE).

100 Memory Requirements

Users Guide / 4.6

Table 2: ROM requirements for OSE Epsilon for ARM RTOS Kernel (minimum, no debug) Kernel (full, no debug) Kernel (minimum, debug) Kernel (full, debug) Kernel (minimum, debug + eldm) Kernel (full, debug + eldm) 2.0 kbytes 4.0 kbytes 2.5 kbytes 4.5 kbytes 7.5 kbytes 9.0 kbytes memory required

The amount of code memory required is mainly determined by the size of the application programs. Only if the system is very small the size of the operating system is important

ARM Kernel

In the minimum configuration, only the system calls alloc, send, receive, free_buf and delay are used. eldm is the debug monitor which is needed if the OSE Illuminator system level debugger will be used.

Users Guide / 4.6

Memory Requirements 101

6.8 Speed Considerations


When designing a system, it is often necessary to decide if it meets certain speed requirements. This section is intended to provide some help when calculating speed. All execution times are approximate, remember that times extend due to interrupts etc. The conditions for execution times are the same as in section 7. Generally, if a system is not fast enough with OSE, it will certainly not be fast enough without. There are two reasons for this: 1. Systems running under OSE are always executing at the code section which is most important at any particular moment. 2. The task of directing the work must be done, either by the operating system or by user code. Since the executive is written in assembly and much work has been spent optimizing it, it is mostly faster than user code. The execution times stated in this paragraph assume a ARM7TDMI processor running with a clock frequency of 64 MHz (OSE Epsilon for ARM in RAM, one wait state), and that the system has been configured for fast execution with no debug options selected.

ARM Kernel

6.8.1 Task Switch Performance


The time required for a task switch is determined by system configuration. In an OSE Epsilon for ARM system, the task switching time is 2 microseconds.

6.8.2 Timer-Interrupt Process Frequency


The maximum frequency which might be used for timer-interrupt processes is determined by the system tick. The tasks to be performed at each system tick must be finished before the next tick. 2 us are always required for a tick. If at least two background processes are used, add another 1 us. For each delay or timeout which expires during a tick, add another 3 us. For each declared timer-interrupt process, add 2 us of operating system overhead. Each timer-interrupt process activated requires another 4 us in addition to the time used by the process itself. Add the times for a worst case situation in your system and you will see the maximum timer-interrupt frequency. Keep in mind that if timer-interrupts use up all time between ticks, other parts of the system will be unable to execute. It is not reasonable to expect to activate a timer-interrupt process more often than every 500 us, even if the system has been designed with this purpose in mind.

102 Speed Considerations

Users Guide / 4.6

6.8.3 Signal Transmission Performance


A complete signal transmission sequence would be: 1. allocate a buffer, 2. send the signal, 3. change to the receiving process, 4. receive the signal, 5. free the buffer. This whole sequence would at least use up approximately 13 us. If a shorter time is required, use the same buffer back and forth between the processes. This would reduce the time consumption to 8 us. The time between an interrupt process is activated and in its turn has activated a prioritized process would be 13 us.

6.8.4 Interrupt Handling Performance

ARM Kernel

Interrupts are usually used to provide fast response. The time from hardware signals an interrupt until execution of the first line of code dealing with the interrupt is often referred to as interrupt latency. Two components determine interrupt latency: 1. The time required to initialize the interrupt. The state before the interrupt must be saved and execution must be transferred to the interrupt handling routine. 2. Interrupts are disabled from time to time. This is done by the CPU itself, by OSE and by user programs. OSE disables interrupts for a maximum duration of us. The time under (1) above must be added to the time interrupts may be disabled.

6.8.5 Time Consumption of Other Functions


Functions other than interrupts, task switches, ALLOC, FREE_BUF, SEND and RECEIVE have not been considered as time critical. The execution times for DELAY and RECEIVE_W_TMO vary widely, depending on number of pending delays and timeouts in use, interrupts disturbing etc. The system start always consumes time to initialize all tables and variables. If no users start handler is present a medium sized system configured no debug requires approximately 700 us to start.

Users Guide / 4.6

Signal Transmission Performance 103

6.9 System Start


When the system is started, it starts execution at the symbol START_OSE in osarm.*. Interrupts are disabled. The system then initialises a small temporary stack and calls the power on handler if present. If a warm start is required, control is immediately passed to the process which was running when POWER_FAIL last occurred. If no warm start is required, the users start handlers, if any, are called one at a time. Start handlers get a slightly larger stack. When start handlers are called, no memory has yet been initialised. The current stack is located in memory between the symbols ZZ_TEMP_STACK_E (low limit) and ZZ_TEMP_STACK (high limit). When the start test is done, OSE Epsilon for ARM initialises its internal data structures. The prioritized process with the highest priority is swapped in and allowed to start executing from the first instruction. Other processes are activated as required by priorities and events. Background processes start executing when no prioritized process is ready.

6.10 Writing the Interrupt Handler

ARM Kernel

In OSE Epsilon for ARM, you have to supply a user-written Interrupt Handler to be able to use OSE Interrupt Processes.

6.10.1 Sample Interrupt Handler


The OSE Epsilon for ARM delivery (Board Support Packages, bsp) contains templates which describe how to write your own interrupt handler (i.e. c:\ose\epsilon\arm\krn\<compiler>\bsp\<board_type>\inthdlr.s). When interrupt, the user has to decide which interrupt occurred and call proper interrupt process. One interrupt source must call the OSE_TIMER_ENTRY to manage system tick.

6.10.2 Nested OSE Interrupts


If nested interrupts are required, macros INIT_INT_NESTED and QUIT_INT NESTED must be used. When the first interrupt occurs all registers are saved in the data area of running process. When a nested interrupt occurs, registers must be saved on the interrupt stack. INIT_INT_NESTED does all this and switches the CPU mode to SYSTEM mode. Before re-enabling interrupt, user may set a new interrupt mask in order to mask out interrupts with the same or lower priority. When leaving a nested interrupt, register values are restored from the interrupt stack. When leaving, lowest level of interrupt registers are restored from the data area of the running process. The dispatch request flag (DP_REQ) is also checked, to determine if a dispatch is required. QUIT_INT_NESTED does this.

104 System Start

Users Guide / 4.6

6.10.3 Interrupt Enable/Disable Functions


Since OSE Epsilon for ARM runs most of the time in Thumb- and System-Mode, there is no normal way to disable interrupts. Therefore the user must provide three functions which can be found in the file inthdlr.s in the delivery bsp directory (c:\ose\epsilon\arm\krnxxx\<compiler>\bsp\<board>\src\inthdlr.s): 1. arm_lock. This function should lock interrupts in the interrupt-controller and save the current status on the stack. This function is called from Thumb-mode. 2. arm_unlock. This function should restore the interrupt controller status with a value read from the stack. This function is called from Thumb-mode. 3. zz_interrupt_enable_a. This function should enable all interrupts in the interrupt controller from a value stored in a shadow register. It is called from ARM-mode. It is called only once at system startup right before the first process is swapped in.

ARM Kernel
Users Guide / 4.6

Interrupt Enable/Disable Functions 105

6.11 Writing a Link Handler


This section is not intended to be a complete instruction on how to write a link handler. You will probably need extensive knowledge on communications software before writing a good link handler. The following text will merely try to explain matters particular to OSE. Processes in every CPU running OSE are numbered from 1 up to the number of processes. These numbers are also the addresses of the processes. When a signal is sent to an external CPU the addressee will be stated as a number, higher than process number 255 in the sending CPU. When SEND finds an addressee higher than 255 in the CPU, that signal will be forwarded to the link handler of the CPU. The link handler must have a table with information which enables it to translate addresses used in its CPU to addresses valid in the receiving CPU. Apart from the address translation task, a link handler must contain communication software for the type of link used. How to write that software is outside the scope of this manual. A link handler is an ordinary prioritized process with the process name LINKHANDLER (must be in capitals). No other name may be used. Other processes may send signals to the link handler in the same way all signals are sent. In addition to that, all signals sent to processes unknown to SEND will generate an OSE system error. Ordinary signal buffers contain no information about the addressee, since the process which received the signal is the addressee. Signals sent to processes outside the CPU have a different format containing the address of the process to which the signal is to be sent. The link handler should use the ADDRESSEE system call to look at the address of the buffer and decide if that address is valid. If the address is not recognized, the link handler should call ERROR. Signals, coming from processes in other CPUs, can be received by the link handler or some other process. A process receiving signals from a physical link allocates a signal buffer using ALLOC, places the received signal in the buffer and sends it to the addressee inside this CPU. The SEND_W_S system call is used for this purpose since it enters a specified process as sender of the signal. This allows the link handler to emulate the global sender of the signal.

ARM Kernel

106 Writing a Link Handler

Users Guide / 4.6

6.11.1 Multiple Physical Links


If there are many physical links in the system, you are likely to need one link handler for every physical link. Only one link handler may be named LINKHANDLER and receive signals from SEND however.That link handler will have to forward signals to other link handlers using the SEND_W_S call as necessary. Those signals should not be restored and freed until they have reached the leaf link handler.

6.11.2 Buffer Structure


Buffers sent by SEND to the link handler have the following structure: Buffer size in bytes is counted from signal number to the last byte. I.e. a buffer containing only the signal number will have buffer size set to 2. The system calls ADDRESSEE, SIGSIZE and SENDER may be used to extract information from the buffer structure in a portable way.

6.11.3 Reformatting Buffers

ARM Kernel

The buffers received from RECEIVE directed to an external process have a different format than ordinary buffers. The format of ordinary buffers is described in the section on the system call ALLOC, the special format was detailed in the section above. NOTE that the special format is applicable only to signals directed to external processes. Signals sent from a process directly to the link handler are of standard format. Special format buffers must be reformatted before they can be returned to the system. This is done by the system call RESTORE. (For details, see System Calls.)

Users Guide / 4.6

Multiple Physical Links 107

6.12 Writing an Error Handler


When an error has been detected, it is often desirable to log the error and additional data on some logging device or a display. Since the operating system can not know which devices are available in a particular system the operating system remains in an infinite loop after an error. If other actions are to be taken, the user must write an error handler to do this work. Interrupts are disabled while the error handler is executing. You are not allowed to use system calls in the error handler except: ADDRESSEE, CURRENT_PROCESS, GET_FSEM, GET_PRI, GET_TICKS, SENDER, SIGSIZE, WAKE_UP NOTE that the name of the error handler must be declared in the configuration file osarm.con. Error handlers may be written in C or assembly.

6.12.1 Error Information


When the users error handler is called, information on the error is available in the global ERR_MSG array and in the CPU-registers. In order to obtain the information the ERR_MSG array must be declared as an external variable:
Syntax: extern unsigned int ERR_MSG[5];

ARM Kernel

EXAMPLE
extern unsigned int ERR_MSG[5]; display( ERR_MSG[1] ; /* /* /* /* Display running process, assuming you have written a procedure display to show the digits. */ */ */ */

The following five integers of information are provided:


ERR_MSG[0] Error number. (For details, see Run-Time Error Messages.) ERR_MSG[1] The process which was running when the error occurred. Processes are numbered from 1 which is assigned to the first process declared in osarm.con and increased by one for each subsequent process. ERR_MSG[2] The address of the process control block (PCB) of the running process. ERR_MSG[3] Current stackpointer. ERR_MSG[4] Zero when called from user.

108 Writing an Error Handler

Users Guide / 4.6

If the operating system itself detected the error, ERR_MSG[2] will be non zero. If this occurs ERR_MSG[0] - ERR_MSG[4] have the following functions:

ERR_MSG[0] Error number. (For details, see Run-Time Error Messages.) ERR_MSG[1] The process which was running when the error occurred. Processes are numbered from 1 which is assigned to the first process declared in osarm.con and increased by one for each subsequent process. ERR_MSG[2] The address of the process control block (PCB) of the running process. ERR_MSG[3] Current stackpointer. ERR_MSG[4] Non zero when called from user.

ARM Kernel
Users Guide / 4.6

Error Information 109

6.12.2 Continuing After an Error


It is not possible to continue when the operating system has detected an error. If a user process has detected an error, the error handler may decide to continue execution, perhaps after the error handler has restored the situation. If the user-written error handler decides to continue, it may return to ERROR where execution will continue after the statement where ERROR was called. If the user-written error handler decides not to continue, it must remain in an infinite loop. If the user-written error handler decides to restart the system, it must enforce a reset of the CPU.

ARM Kernel
110 Continuing After an Error

Users Guide / 4.6

7 Illuminator Debugger
Illuminator is a System Level Debugger for the OSE Real-Time Operating System from Enea Embedded Technology. Illuminator can be used for OSE (aka OSE Delta), OSEck (aka OSE for DSP) and OSE Epsilon systems. OSE Illuminator is delivered on a separate OSE Delta CD (labelled OSE X.X, where X.X represents the version). In a typical real-time system, the crucial parts are the interfaces between the different system components and the real-time behaviour and status of system functions and resources. In an OSE system, the components are processes and the interface is always made up of OSE signals. With a traditional source code debugger, it would be a tough job to supervise or debug these interfaces because a source level debugger concentrates on code lines. Our OSE Illuminator system level debugger is designed to make it easy to work with the signal interfaces. Illuminator is a standalone debugger which will be used together with a serial line or other interfaces for target connection. It can therefore be used together with any other debugging tool such as Emulators and ROM-Monitor-HLL-Debuggers from any supplier. The OSE Illuminator System Level Debugger can be connected in different ways to an OSE Epsilon target system. Illuminator consists of a user interface and a communication module called Epsilon Debug Server (edbgserver.exe) on the host, and the ARM Debug Kernel on the target. Please consult the Illuminator Users Guide for a detailed description of OSE Illuminator. You can find this manual in the OSE Delta delivery.

ARM Kernel
Users Guide / 4.6

Illuminator Debugger 111

7.1 Serial Line Connection

Host Illuminator
TCP/IP

Target ARM Debug Kernel

edbgserver

serial Serial Line comx uart

ARM Kernel

Figure 7.1 Serial line connection between host and ARM target Illuminator is connected to the Epsilon Debug Server (edbgserver) over a host TCP/IP connection. The debug server translates the Illuminator signals into a special debug protocol which is send over the serial line to the target system. The ARM Debug Kernel contains the target system level debug functions. It is connected over a serial driver (serial.c) to the serial line connection to the host system. By means of different hooks into the OSE kernel the debug module gets all necessary system information from the kernel. As all debug functions are located in the target the Debug Kernel functions need some target resources. The hooks into the kernel results in some timing overhead when debug is enabled. The debug functions also uses code and data memory from the target system. All event trace is performed in the target. The ARM Debug Kernel will automatically be generated if the debug option (DEBUG YES) is selected in the OSE Epsilon for ARM configuration file osarm.con. You also need a communication module to connect the ARM Debug Kernel to the host. For an asynchronous serial line connection the driver serial is included.

112 Serial Line Connection

Users Guide / 4.6

7.1.1 System Configuration


As you are already familiar with the OSE Epsilon for ARM real-time operating system, you know that you are configuring the system with the configuration file osarm.con. There are three entries in this file for debugging:
; ; ; ; ; ; 2.1 Debug options (must not be left empty) DEBUG (YES | NO) BUFFER_CHECK (YES | NO) STACK_CHECK(YES | NO) OPTION DEBUGGER,(NO | ONCHIP,<trace>, <evact> DEBUG YES BUFFER_CHECK YES STACK_CHECK YES OPTION DEBUGGER,ONCHIP, 1024, 16

ARM Kernel

The entries for DEBUG, BUFFER_CHECK and STACK_CHECK must not be left empty and you can switch on these run-time functions also without using OSE Epsilon Illuminator. A Buffercheck or Stackcheck error will then jump into an errorhandler if you have defined one. The OPTION DEBUGGER must not be left empty. The OPTION DEBUGGER, ONCHIP will enable some hooks in the OSE Epsilon for ARM kernel and generate the OSE Epsilon for ARM Debug Kernel. After the system configuration file osarm.con is satisfactory run the configurations utility confarm.exe. Confarm.exe reads the configuration file osarm.con and produces the configured kernel. Assemble this file and link it together with your system. You will find the confarm.exe in the ..\conf\ directory of your OSE Epsilon for ARM installation.

Users Guide / 4.6

System Configuration 113

7.1.2 Testing the Target Debug Connection


After you have downloaded the generated application into the target system and started the target you can check the host-target communication by a simple test. 1. Download the application including the ARM Debug Kernel and serial driver into the target. 2. Start the target system from your system level debugger. 3. Connect the serial line cable for the Illuminator debugger. 4. Open a suitable terminal program on the host PC. 5. Be sure that you have selected the right communication port and the right baud rate (same as in serial of the target) on your host PC. 6. Enter the command VE in the terminal. 7. The target system should now respond with: >OSE Epsilon for ARM ver. X.Y.Z >ELDM for ARM ver. X.Y.Z

ARM Kernel

If the target system is not responding you need to debug the target modules and to check the communication settings.

114 Testing the Target Debug Connection

Users Guide / 4.6

7.1.3 Epsilon Debug Server


If the targets system is running, you have to start a small communication program on the host system called edbgserver manually. If you have installed OSE Epsilon for ARM at the default location on your PC, you can find the edbgserver.exe file in the directory: c:\ose\epsilon\arm\krnxxx\bin Illuminator communicates with the Epsilon Debug Server (edbgserver.exe) which controls the Serial Interface of the PC. Please note that the Illuminator uses TCP/IP, so make sure that networking is enabled on your machine (you can verify this by using the ping command, e.g. ping myhost where myhost is the host name of your PC). Open a MS-DOS shell window and change the working director of this windows to the directory where edbgserver.exe is located. Run edbgserver.exe. You will see now the following window:

ARM Kernel

edbgserver communicates by default over COM1 with a baudrate of 115200 baud. If you need another baudrate or another serial interface, type edbgserver in the command window with the following parameters:
edbgserver <com=x> <bd=y> <silent> <debug>

where:

<com=x> is the comport x = 1, 2, 3 or 4. Default value is 1. <bd=y> is the baudrate yy = 9600, 19200, 38400, 57600 or 115200. Default value is 115200. <silent> The silent option will remove the system alive prompt (swimming fish) from the edbgserver window. This allows user debug messages from the target to be displayed in the edbgserver window.

Users Guide / 4.6

Epsilon Debug Server 115

<debug> If the debug option is selected, you can see the eldm low level debug commands. All eldm debug messages from the target are displayed, e.g.:
edbgserver edbgserver com=2 bd=38400 com=2 silent debug

7.2 Symbolic Signal Information


Due to some limitations, Illuminator cannot load symbolic signal information generated by the ARM, GNU and IAR tool chain. Therefore, Symbolic Signal Information for OSE Epsilon for ARM target systems is not available in this version.

ARM Kernel
116 Symbolic Signal Information

Users Guide / 4.6

8 Timeout Server
The Time-Out Server allows processes to handle time intervals either to schedule events or to detect time-out conditions. Include the following entry in osarm.con:
TI_PROC tosv,<timeslice>

The time resolution is <timeslice> * system clock ticks. The Time-Out Server is delivered in source code. The file name is tosv.c and can be found in SRC directory of the OSE installation. The functions are described in:

Request Timeout on page 118 Cancel Timeout on page 119 Retrigger Timeout on page 119

ARM Kernel
Users Guide / 4.6

Timeout Server 117

8.1 Request Timeout


timeoutID cancel = request_tmo(S32 time, SIGSELECT signal_id); request_tmo let user processes request time out signal after a specific time interval with a resolution down to clock ticks. The signal ID of the received signal after a time-out is the signal ID specified in the request_tmo system call. The request_tmo returns cancel information which can be used if user process wants to cancel the time out. If time is positive, it is taken relative to the current system time. If it is negative it is the absolute represented system tick at which a timeout should occur. Returns an ID which can be used to remove the timeout with cancel_tmo. Example:
request_tmo(-10000,0x1234); get Signal 0x1234 at tick 10000

request_tmo( 10000,0x1234);

ARM Kernel

get Signal 0x1234 at tick + 10000

118 Request Timeout

Users Guide / 4.6

8.2 Cancel Timeout


void cancel_tmo (timeoutID cancel_info); Removes a timeout-request. The given ID is checked and if valid, the timeoutrequest is removed from the list. Example:
timeoutID cancel_info; cancel_info = request_tmo(100L,3); /* A signal with identity 3 is returned after */ /* 100 systemticks cancel_info holds information */ /* if the time-out must be cancelled */ void cancel_tmo(timeoutID cancel_info)

User process can cancel their own previously given time-out request by calling cancel_tmo. Do not use the same signal ID at the same time when using cancel_tmo.

ARM Kernel

8.3 Retrigger Timeout


void retrigger_tmo (S32 new_time, timeoutID id); Set a timeout value to a new time. If the timeout had occurred before retrigger_tmo is called, an error will be generated. Example:
retrigger_tmo (-10000,last_tmo);

Users Guide / 4.6

Cancel Timeout 119

ARM Kernel
120 Retrigger Timeout

Users Guide / 4.6

9 Glossary
Many of the terms used in this manual are specific to operating systems and real-time systems. These can have a different meaning in different contexts. Below, you will find definitions of terms as they are used in this manual.

as shipped buffer buffer pool

The OSE-files as they were delivered to your company. A section of memory. It is reserved using the ALLOC system call. It is often used to store signals. The section of memory containing all reserved buffers. At times there is memory left in the pool where more buffers may be reserved. The instructions which make up a program. The memory where code constants are stored. It is often ROM or PROM but can also be RAM in an emulator or target system. System call designed specifically for communications software. In OSE, FLUSH, RESTORE, ADDRESSEE and SEND_W_S are communication functions. Events which occur at the same time. For example, in a terminal, the operator may type at the keyboard and the host computer may send characters concurrently. The operating system may contain different parts of code and behave differently depending on the configuration. The configuration is determined by data entered by the designer into the ostri.con configuration file. Locating end removing errors from a system. The tools used to develop a system. For example: editors to write source code, assemblers/compilers to generate machine readable instructions, emulators to find errors. To decide which process is to run at a particular moment. The ready process which has the highest priority is always selected. See also: swap, task switch.

code

ARM Kernel

code memory communication function concurrent

configuration

debugging development tools dispatch

dispatcher

The program which performs a dispatch.

Users Guide / 4.6

Glossary 121

emulator

A tool to locate errors. With an emulator you may look inside the CPU to see where in the code it is executing, the value of variables etc. An emulator can also stop execution at interesting points in the program. An emulator is necessary to be able to use the full power of the OSE system level debugger. Something happens in the system. For example, the operator may have pressed a button. Events are often connected to interrupts or polled. To issue instructions to the CPU. The instructions are then carried out by the CPU. The program system has experienced a deadlock. It will cease to function and the system will appear to be dead to an observer. The boundary between processes. Together, all contacts between two processes is their interface. In OSE, the process interface consists of the signals exchanged between the processes. An event which, through hardware, causes the CPU to transfer control from the currently running program to another program called interrupt process. For example, as soon as a bit changes the CPU starts executing a subroutine which handles that event. No time is spent checking whether the bit has changed or not. See also: poll.

event

execute hang interface

ARM Kernel

interrupt

interrupt latency interrupt source memory pool message not ready

The time from the occurrence of an event until the first instruction of the corresponding interrupt process is executed. The hardware which causes an interrupt. For example, a timer or a pin on the CPU. See buffer pool. See signal. When a process has no further work to do it becomes not ready. It will then be swapped out by the operating system. See also: ready (p. 123).

operating system

The part of a program system which decides which processes to run, and when. It also distributes the resources of a system, such as memory and time. OSE is an operating system. A process is a program which runs independently of other programs. In principle, a process may act as if it was alone in the CPU.

process

122 Glossary

Users Guide / 4.6

pointer

A word (2 bytes) of memory containing an address to another part of memory. A pointer may, for example, point to a buffer, i. e. contain the address to a buffer. To check for an event at regular or irregular intervals. For example checking the value of a bit every millisecond. If the bit has changed, a subroutine is executed to handle that event. After the bit has changed, there may be some time before it is checked and the subroutine is started. The CPU always spends a fraction of its time checking the bit, and perhaps other bits. See also: interrupt (p. 122).

poll

pool ready

See buffer pool (p. 121). As soon as a process has something to do it becomes ready. If it has higher priority than the process currently running the currently running process is swapped out. A process may be ready for a long time without being permitted to execute. See also: not ready (p. 122).

ARM Kernel

real-time

An administrative program, for example a word processor, may keep its user waiting for long intervals of time. It will still not be considered useless. A program controlling the brakes of a car will not be very useful if it needs a minute to calculate what to do when the brake pedal is pressed. Programs which have to react to external events within a limited time are called real-time programs. An operating system designed to handle such programs is a real-time operating system. Code is re-entrant if more than one process at a time may execute it. This requires that the code does not use fixed variable locations i. e. it must use registers or the stack. The OSE system calls are reentrant. Code which is not re-entrant can not be called from more than one process unless interrupts are disabled. For example, consider the following C-procedure:
my_proc() { extern int my_variable; my_variable += 1;

re-entrant

This code is not re-entrant.

Users Guide / 4.6

Glossary 123

Assume that my_variable has the value 17. If process A calls my_proc, the procedure reads my_variable and finds 17. Then process A is swapped out for some reason and process B is swapped in. After a while process B calls my_proc and my_proc increments my_variable which then becomes 18. A moment later process B is swapped out and process A is swapped in again. It has already read my_variable which was then 17 and now increments it to be 18. Result: my_variable is still 18 although it has been incremented twice since it was 17! run signal swap See execute (p. 122). A buffer which is sent from one process to another. To save the environment of one process and then restore the environment of another process. Together, all hardware and software of your product form the system which you design. The processes may call the operating system when they want to use its services, for example sending or receiving a signal. Such calls are referred to as system calls. System calls are the only way for processes to obtain service from the operating system. The program system executes out of control. The behaviour of the system can not be predicted in case of a system crash. A system crash is the result of errors in user processes or it may result from electrical upsets. Almost every system crash is detected by the error locating devices of the operating system. Is the act of entering configuration data into the configuration file and assembling the operating system. At regular intervals, the operating system checks to see if delays or timeouts have run out or if a timer-interrupt process should be activated. These intervals are called system ticks. The hardware where your programs will ultimately run. Work to be performed by some part of some program. To swap out a process, perform a dispatch and swap in a new process. See also: dispatch (p. 121), swap (p. 124).
124 Glossary Users Guide / 4.6

ARM Kernel

system system call

system crash

system generation system tick

target system task task switch

user user interface

Someone using the operating system. The system calls programmers use when they communicate with the operating system.

ARM Kernel
Users Guide / 4.6

Glossary 125

ARM Kernel
126 Glossary

Users Guide / 4.6

Index
A
ARM Assembly-Time Errors 45 80 74, 86 115 50 56 107 96 113 77

Configuration file Configuring Continuing After an Error CPU CPU Type

43 43 110 11 47

D
DEBUG 113 Debug Kernel 40, 77, 79, 111, 113 49 Debug Option 121 Definition of Terms Dispatcher 12 54 DISPATCHER_IN_RAM

B
Background Process baudrate Buffer Check Option Buffer Sizes Buffer Structure Buffer Transfer BUFFER_CHECK Building a System

E
edbgserver Enable Wake Up Epsilon Debug Server ERR_MSG Error Handler Error Information Execution time 40, 42, 112, 115 75 40, 42, 111, 112, 115 108 59 108 102

C
C Compiler Cancel Timeout comport COND_HALT_W_TIMINT Configuration configuration background processes buffer buffer sizes C compiler check conditional halt CPU types debug option enable wake_up error handler Idle Handler interrupt processes interrupt stack Link Handler processes option debugger OSE dispatcher power off handler power on handler prioritized processes receive handler send handler start handler swap handler target name temporary stack 45 119 115 53 79 74 50 56 45 51 53 47 49 75 59 68 70 57 73 52 54 65 64 72 63 62 60 61 46 58

ARM Kernel

F
Fast Semaphore FLUSH 22, 97 97

G
GET_FSEM Getting Started GHS Global Variables 97 25 45 98

H
Hardware 11

I
IAR 45 40, 42, 79, 111 Illuminator Interprocess Communication 11 103 Interrupt Handling Performance 103 Interrupt latency Interrupt Performance 18 17, 70, 87 Interrupt Process 18 Interrupt response time Interrupt Stack 57

L
led.c led.h LEDs Link Handler Processes 34 34 34 73 20

M
Mailbox

Users Guide / 4.6

Index 127

max. evact 52 52 max. trace Memory Model 48 100 Memory Required By OSE for ARM 99 Memory Required By Stacks Memory Requirements 99 Memory Used By the Buffer Pool 99 98 Memory Utilisation Message 20, 22, 94 107 Multiple Physical Links

N
Nested interrupts 57

O
ONCHIP Option Conditional Halt OPTION DEBUGGER Option Debugger Option Dispatcher in RAM osarm.con osarm.s OSE 4.2 52, 113 53 113 52 54 30, 43, 79 77 111

ARM Kernel

P
Pool Size 55 64 Power On Handler Pre-emptive 13 17, 72 Prioritized Process 14 Priority Based Process Scheduling Process 9, 11, 81, 83 13 Process States

Serial Line Connection serial line Illuminator system SET_FSEM Signal Signal transmission sequence SIGNAL_FSEM SINGLECHIP Speed Speed Considerations Stack Check Option STACK_CHECK Start Handler Starting and Stopping Processes Static Process Swap Handler Symbolic Signal Information System Configuration System Creation Cycle System Design System Initialization System Start system2.h

112 41 97 9, 81, 94 103 23, 97 45 12, 81 102 51 113 60 93 16 61 116 113 83 81 79 104 34 46 58 114 114 11 117 19, 71 14 95 23, 97 13 106 108 104

T
Target Name Temporary Stack Terminal Testing the Target Debug Connection Time Management Timeout Server Timer Interrupt Process

R
RAM requirement READY Receive Handler Reformatting Buffers Request Timeout Resource Resource Management RESTORE Retrigger Timeout ROM requirements Round-Robin Process Scheduling RUNNING 100 13 63 107 118 11 11 96 119 101 14 13 23 97 62 112

U
UNIX Using Signals In Processes

W
WAIT_FSEM WAITING Writing a Link Handler Writing an Error Handler Writing the Interrupt Handler

S
Semaphore Semaphores Send Handler serial

Users Guide / 4.6

Index 128

You might also like