• 沒有找到結果。

Seed: 一個適合網路設備之嵌入式即時作業系統核心

N/A
N/A
Protected

Academic year: 2021

Share "Seed: 一個適合網路設備之嵌入式即時作業系統核心"

Copied!
62
0
0

加載中.... (立即查看全文)

全文

(1)

資訊科學系

S e e d : 一 個 適 合 網 路 設 備 之

嵌 入 式 即 時 作 業 系 統 核 心

Seed: an Embedded Real-time Operating System Kernel for

Network Appliances

研 究 生:王俊喬

指導教授:張瑞川 教授

(2)

Seed: 一個適合網路設備之嵌入式即時

作業系統核心

研究生:王俊喬

指導教授:張瑞川教授

國立交通大學資訊科學所

嵌入式系統在現代日常生活中到處可見,並且扮演了一個相當重要的角色。 嵌入式系統的特點在於它是一個應用程式特定的系統,而且通常硬體資源較為不 足。除此之外,有愈來愈多的嵌入式應用程式要求能夠即時地完成自己的工作, 並且希望能有與其他系統利用網際網路溝通的能力。 為了能夠滿足以上的系統需求,我們發展了一個支援網際網路的即時嵌入式 作業系統,名叫 Seed。Seed 是一個小尺寸、富有彈性、高效能、具可攜性的嵌 入式作業系統核心。此外,Seed 核心為了支援即時系統,所提供的服務都是可 預測或者固定時間的行為模式。最後,為了能讓系統更進一步能夠有網際網路溝 通的能力,我們也移植了一個名叫 lwIP 的小型 TCP/IP 網路溝通協定模組在 Seed 作業系統上。 Seed 作業系統核心目前支援先佔式多工、執行緒彼此間溝通和同步的機制、 以及記憶體、定時器、中斷的管理。核心影像檔若包含 lwIP 大小為 75 Kbytes, 若是不包含 lwIP 大小是 21 Kbytes。核心的尺寸相當地小因而適合嵌入式系統。 然後我們把 Seed 的效能測量出來,結果顯示出我們的系統相當適合小型的即時 嵌入式網路設備。

(3)

Seed: an Embedded Real-Time Operating System

Kernel for Network Appliances

Student:Chun-Chiao

Wang

Advisor:Prof. Ruei-Chuan Chang

Institute of Computer and Information Science

National Chiao-Tung University

Abstract

Embedded systems are ubiquitous and play a significant role in modern daily life.

The characteristics of embedded systems are application-specific and scarce hardware

resources. Besides, more and more applications in embedded system care not only

real-time to complete their works, but also want to own Internet-access capability

which allows the devices to communicate with other systems.

To achieve these requirements, we developed an Internet-supported embedded

real-time operating system called Seed. The Seed kernel is small, flexible, high

performance, and portable for embedded system. Besides Seed have deterministic or

constant timing behavior to support real-time system. Finally, to enable the

Internet-access capability, we ported a small TCP/IP stack, lwIP, to Seed.

Seed kernel currently provides preemptive multitasking, task synchronization /

communication, and management of memory, timers and interrupts. The size of the

kernel image is about 75Kbytes with lwIP, or 21Kbytes without lwIP. It is quite small

and suitable to embedded system. The performance results show that Seed is quite

(4)

Acknowledgements

For accomplishing this thesis, I would like to thank my respected advisor Prof.

Ruei-Chuan Chang for instructing me in research. Additionally, I deeply appreciated

David Chang’s assistance for giving me much advice and opinion on writing this

thesis. Thanks to each member of the computer system laboratory for their

encouragement and kindly help

Besides, I would like to thank my parent and my girlfriend, too, for their

encouragement and unlimited love. Finally, I want to thank all my friends for all the

joyous things that inspire my life.

Chun-Chiao Wang

Institute of Computer and Information Science

National Chiao-Tung University

(5)

Table of Contents

論 文 摘 要 ...i Abstract ...ii Acknowledgements... iii Chapter 1 Introduction ...1 1.1 Motivation...1 1.2 Thesis organization ...2

Chapter 2 Related Works ...3

2.1 Linux & RTLinux ...3

2.2 eCos...3

2.3 μC/OS-II...4

2.4 Commercial RTOSes ...4

Chapter 3 Design and Implementation ...5

3.1 Kernel Overview...5 3.1 Task Management ...9 3.1.1 Design ...9 3.1.2 Implementation ... 11 3.1.3 Interface ...16 3.3 Interrupt Management...19 3.3.1 Design ...19 3.3.2 Implementation ...20 3.3.3 Interface ...21 3.4 Timer Management ...23 3.4.1 Design ...23 3.4.2 Implementation ...23 3.4.3 Interface ...25 3.5 Memory Management...27 3.5.1 Design ...27 .3.5.2 Implementation ...28 3.5.3 Interface ...30 3.6 Message Queue ...32 3.6.1 Design ...32 3.6.2 Implementation ...33 3.6.3 Interface ...34 3.7 Semaphore...36 3.7.1 Design ...36 3.7.2 Implementation ...37

(6)

3.7.3 Interface ...37

3.8 Hardware Abstract Layer (HAL) ...39

3.8.1 Boot...39 3.8.2 Interrupt...40 3.8.3 CPU Context ...41 3.8.4 Devices...41 3.9 Implementation Status ...43 3.9.1 Platform...43

3.9.2 Implemented Kernel Components ...43

3.9.3 Implemented Drivers ...44

3.9.4 LWIP Integration...44

Chapter 4 Experimental Results...47

4.1 Basic Measurement...47

4.1.1 Code Size ...47

4.1.2 Primitive Performance Measurement ...48

4.2 Performance Measurement of the Network System ...49

Chapter 5 Conclusion and Future Work...51

5.1 Conclusion ...51

5.2 Future work...51

(7)

List of Figures

Figure 3.1 Seed Kernel Architecture ………8

Figure 3.2 Task States ………..11

Figure 3.3 Data Structures for Task Scheduling ………..13

Figure 3.4 Mapping Table for Finding the Highest Priority Task ………..14

Figure 3.5 Pseudo Code for Finding the Highest Priority Task ………..14

Figure 3.6 Task Priority Ready Queues with Priorities ………..16

Figure 3.7 DISR Data Structures ………..21

Figure 3.8 Active Timer List ………..24

Figure 3.9 Memory Partition Data Structure ………..29

Figure 3.10 Message Queue Data Structure ………..33

Figure 3.11 Seed Boot Flow ………..40

(8)

List of Tables

Table 3.1 Function Mapping between lwIP OS Emulation Layer and Seed

kernel ………..45

Table 4.1 Code Size of Seed Kernel ………..47

Table 4.2 Performance of Seed Kernel Functions ………..48

Table 4.3 Latency of Seed Interrupt Handling ………..49

Table 4.4 Throughput of LWIP Running on Seed ………..50

(9)

Chapter 1

Introduction

1.1 Motivation

Embedded systems are ubiquitous and play a significant role in modern daily life.

They can be found everywhere, such as watches, VCD/DVD players, digital cameras,

mobile phones, PDAs, missile systems, flight control systems and etc. Traditional

embedded operating system usually addresses two issues: limited hardware resources

and real-time support. Therefore, an embedded operating system must be able to run

on top of limited resources as well as provide real-time support to its applications.

With the popularity of Internet and rapid development of network technologies,

Internet-access capability is becoming a necessarily for many embedded systems.

Such network appliances can not only communicate with each other, but also enable

many creative applications on them such as remote control functionality. For example,

an user can control an in-home VCD/DVD recorder to record his favorite TV

programs when he is working at office.

Therefore, modern embedded operating systems should satisfy the requirements

of running on the top of limited hardware resources, supporting real-time applications,

and providing Internet-access capability. Many commercial real-time operating

systems do satisfy the above requirements. However, they are usually expensive and

not open source. On the other hand, non-commercial kernels often have limitations for

fulfilling the requirements. This motivates us to design and implement a real-time

embedded operating system, named Seed, for network appliances. Seed contains an

OS kernel designed for time-critical embedded applications. Besides the basic kernel

services, we also ported a small TCP/IP protocol stack called lwIP [7] to Seed. This

(10)

The kernel has the following four design goals. First, it is designed to be flexible

for supporting various applications in embedded systems. Second, Seed supports

real-time applications. For example, it provides preemptive multitasking and

deterministic (or constant) timing services. Third, Seed is designed for high

performance and small kernel size. And fourth, Seed is an extremely portable kernel.

It is easy to port Seed to other hardware platforms by replacing the hardware

abstraction layer.

Seed is currently implemented on Samsung SNDS100 evaluation board. The

kernel supports preemptive multitasking, task synchronization/communication, and

management of memory, timers and interrupts. As we mentioned above, the TCP/IP

stack is also ported. The size of the kernel image is about 75Kbytes with lwIP, or

21Kbytes without lwIP, which is small enough for resource-limited systems.

1.2 Thesis organization

The rest of the thesis is organized as follows. The following chapter describes

previous research related to real-time embedded kernels. Chapter 3 presents the

design and implementation details of Seed kernel. Besides, we introduce lwIP and the

porting status in this chapter. The experiment results are shown in Chapter 4. Finally,

(11)

Chapter 2

Related Works

In this chapter, we describe some of the related real-time embedded kernels.

2.1 Linux & RTLinux

Linux is a famous open source operating system. Many vendors such as

MontaVista [15] and Metrowerks [12] have put efforts on making Linux an

Embedded RTOS. The techniques include shrinking the kernel and the libraries,

reducing the timer interrupt intervals, inserting preemption points in the kernel, and

etc. However, Linux kernel is inherently designed for general-purpose and

non-real-time systems [3]. The techniques can not transform Linux to a true real-time

kernel.

Therefore, a Real-Time Linux (RTLinux) [8][17] was developed for real-time

applications. In RTLinux, a real-time extension co-exists along with the original

Linux kernel. And, each application is divided into the real-time part and the

non-real-time part. The former runs directly on the real-time extension, while the

latter runs on the original Linux kernel. However, the cooperation between the RT and

non-RT parts not only consumes extra computing and memory resources but also

make the application development complicated.

Seed is a pure real-time embedded kernel. Developing real-time applications on

Seed is easy and instinctive without extra overheads.

2.2 eCos

The eCos kernel [18] is a flexible, configurable, and real-time embedded kernel.

(12)

divides the interrupt handing into two parts: Interrupt Service Routine (ISR) and

Deferred Service Routine (DSR). However, the DSR of eCos has no priority levels.

By contrast, Seed has eight priority levels and supports constant time DSR scheduling.

Moreover, eCos only supports 32 priority levels for constant time task scheduling,

while Seed kernel supports 512 priority levels.

2.3 μC/OS-II

μC/OS-II [10] is also a preemptive, real-time, multi-tasking kernel. However, Seed is more flexible and powerful thanμC/OS-II. For example, μC/OS-II supports

only 64 task priorities. Moreover, different tasks must be associated with different

priorities. This prevents the using of Round-Robin scheduling. Finally, μC/OS-II

adopts only preemptive multitasking without the possibility of non-preemptive

multitasking.

By contrast, Seed supports 512 task priorities and allows more than one tasks

share the same priority. Round-Robin scheduling, preemptive or non-preemptive

multitasking are all allowed in the Seed kernel.

2.4 Commercial RTOSes

There are many commercial real-time embedded kernels in the market, such as

WindowsCE[13], Nucleus[1], vxWORKS[23], QNX[16], Lynx[11] and etc. They

support real-time applications and are suitable for embedded systems. However, all of

them are proprietary. Some of them even do not open their source code. Seed is an

(13)

Chapter 3

Design and Implementation

In this chapter, we will describe the design goals and actual implementation of

the Seed kernel. In Section 3.1, we first give an overview of the kernel. Then, we

describe each Seed component from Section 3.2 to Section 3.8. Finally, we describe

the status of implementation in Section 3.9.

3.1 Kernel Overview

Seed OS kernel is designed for embedded systems and real-time systems. Due to

the limited memory and CPU resources of embedded system and the timing

requirements of real-time systems, Seed has following features:

z Flexibility

Since embedded systems are application-specific, it is important to

keep the kernel as flexible as possible. Seed kernel divides its code into

several components for flexibility. Each component can be replaced,

removed and modified without totally rewriting the kernel. The interfaces

and files of each kernel component are explicitly defined. In addition to a

component-based kernel, we implement a Seed component as flexible and

simple as we can. For example, when we create a task, we can specify its

time-slice value, option of preemptive or non-preemptive, and etc.

Furthermore, changing these values at run-time is allowed by the exported

interfaces of Seed.

z Deterministic Timing (Real-Time support)

Real time systems care not only the correctness of the computation, but

also when the computation is completed. Therefore, a key requirement of a

(14)

should consume only expected amounts of time. In non-real-time kernels,

their services may inject random delay into the application, and thus cause

the unexpected response time. On the other hand, the real-time kernels

(including Seed) have deterministic timing behaviors. Furthermore,

real-time kernels should offer constant (load-independent) timing. In other

words, a service consumes the same time to complete the job irrespective of

the workload. The constant timing is always considered when we develop

Seed kernel. With constant or deterministic timing, it is possible to analyze

the worst-case performance of the real-time software.

z Portability

Seed explicitly divides the kernel source code into hardware-dependent

part and hardware-independent part. The former is called Hardware

Abstraction Layer (HAL). The HAL abstracts the underlying hardware,

hence makes Seed portable. If we want to port Seed to another hardware

platform, all we have to do is modify the HAL. All other components do not

need to be changed at all.

z High performance

Since application is an embedded system should cooperate with the

kernel, there is little need to implement multiple protection modes. Thus

Seed selects single protection mode (i.e., kernel mode) for good

performance. Traditional OS, such as Linux, adopts a dual-mode scheme

(i.e. user mode and kernel mode) for kernel protection. Under this scheme,

additional code is needed for changing protection domains. According to the

previous research [4], single protection mode can save the time of system

calls. Besides, for the sake of better performance, the Seed kernel is

(15)

as C++ and JAVA.

Figure 3.1 shows the architecture of the Seed system. As shown in the figure, the

applications run on top of the OS, and the hardware is under the control of the OS.

Typical components in an OS are TCP/IP stack, file systems, window systems, and etc.

However, the kernel (e.g., Seed kernel) is the real nucleus of the whole operating

system. The kernel is the system resource manager that allocates resource (such as

CPU time, memory and I/O devices) to the tasks. As shown in the right part of Figure

3.1, Seed has following kernel components to manage the system:

z Task management z Interrupt management z Memory management z Timer management

z Message queue management z Semaphore management

z Hardware Abstraction Layer (HAL)

(16)

Application

Kernel components :

Figure 3.1 Seed Kernel Architecture

Hardware (Samsung SNDS100)

Seed Kernel

LWIP (TCP/IP)

Hardware Abstraction Layer (HAL) Semaphore Msg. Queue Memory Timer Task Seed OS Interrupt

(17)

3.1 Task Management

3.1.1 Design

A task (also called a process or a thread) is an instance of program in execution.

An application may divide its work into tasks, each of which is responsible for a

portion of the whole job. Each task has a Task Control Block (TCB), which contains

CPU registers, stack, and etc. Seed kernel provides the following features on task

management.

z Multi-tasking

Multi-tasking is the ability to support multiple concurrent tasks

running on the same CPU. It creates pseudo parallelism and maximizes the

use of the CPU. Besides, multi-tasking provides a modular construction

mechanism for applications, which allows the application programs to be

designed and maintained in an easier way.

z Multiple priorities

Each task can be assigned a priority when it is created by the

application designer. The priority ranges from 0 to 511, where 0 is the

highest priority and 511 is the lowest priority. Seed always schedules the

task with the highest priority to run.

z Preemptive

Preemptive multi-tasking means that the running task can be

interrupted at any time by another higher priority task. Oppositely, in the

case of non-preemptive multi-tasking, the scheduling happens only when a

task completes, or it explicitly releases the CPU. Seed kernel supports both

kinds of multi-tasking. If we don’t want a task to be preempted, we can

(18)

select preemptive multi-tasking for fast system responsiveness.

z Constant time scheduling

Seed always selects the highest priority task to run. In non-real-time

kernels, the time spent by a scheduler for choosing the next task to run is

usually non-deterministic. Some real-time kernels, including Seed, allow

the task scheduler to find out the task that should be run next in a short

constant time.(i.e., O(1) time) We will explain the details of the task

scheduling mechanism in Section 3.2.2.

z Time-Slicing ( Round-Robin scheduling )

Seed allows two or more tasks have the same priority. Each task runs

for a determined amount of time of time (called quantum), and then the

scheduler selects another task with the same priority to run. The time

quantum can be assigned while a task is created, or be changed at run-time.

Note that time-slicing is disabled if the task is non-preemptive.

At any given time, a Seed task is always in one of the following states: create,

running, ready, suspend, and terminate. As shown in Figure 3.2, a task enters the create state when it is created. When the task is inserted into the ready queue1 and waiting for execution, it is in the ready state. Once the scheduler selects the task to

execute, the task goes to the running state. When the task is suspended and waiting

for certain system resources, it will go into the suspend state. The task will be

resumed and enter into the ready state while the resource is available. Finally, the task

goes to the terminate state when it has been killed or its job is completed.

1

(19)

Create_Task ( )

Terminate

Create

Figure 3.2 Task States

3.1.2 Implementation

In this section, we describe the implementation of Seed scheduler and the task

ready queue.

We implemented Seed scheduler in a fashion similar to the μ C/OS-II

scheduler[10] . However, we extended it to support more priorities (i.e., 512 priorities)

and keep the scheduling job in a constant time. As shown in Figure 3.3, we represent

512 task priorities in an 8 × 8 × 8 cube data structure, Priority_Ready_Table. The

Priority_Ready_Table is an array of 64 elements, where each element is a 8-bit

bitmap. Each bit is used to indicate the existence of tasks with the corresponding

priority. For example, in Priority_Ready_Table [0][0], the binary value 00001000

means that there is at least one ready task with priority 3. To determinate which task

Ready

Suspend

Running

Task is terminated, or the job is completed Insert into ready queue Scheduler selects task to run Terminate_Task ( ) Resume_Task ( )

Task is preempted

Task is waiting for I/O or Event Task is resumed

(20)

to run, the scheduler will select the lowest priority number that has its bit set in the

Priority_Ready_Table. For the sake of efficiency, we use two data structure as the

indexes of this array, Priority_Ready_Row_Groups and Priority_Ready_Col_Groups.

Each of them is an 8-bit bitmap and each bit corresponds to a priority group.

Priority_Ready_Row_Groups is the row index of this array, and Priority_Ready_Col_Groups is the column index. For example, if the bit 0 of Priority_Ready_Row_Groups and the bit 0 of Priority_Ready_Col_Groups are set,

there is at least one task, with its priority between 0 to 7, ready for execution. This is

because the two indexes point to the element 0 of the array (i.e.,

Priority_Ready_Table [0][0]) , which has the bitmap that stands for priority 0 through

(21)

0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 Priority_Ready_Row_Groups 0 0 0 0 0 0 0 1 1 Priority_Ready_Table[8][8] Priority_Ready_ Col_Groups 1

There is at least one task with priority 3.

Figure 3.3 Data Structures for Task Scheduling

Using the data structures described above to find out the highest priority task, we

use a table-lookup approach. Figure 3.4 shows a mapping table with 256 (28) values

that is used for finding the highest priority task. In fact, it is a priority resolution table.

Given an index, the corresponding value in the table stands for the lowest set bit of

(22)

previously mentioned bitmaps. For example, if the element of Priority_Ready_Table

[0][0] is 8 (i.e., 1000b), we look up the value of Mapping_Table[8] , and the value 3.

It means that the lowest bit of 8 is bit 3, and hence the highest task priority is 3. By

using the Mapping_Table, we can find the highest task priority via three times of

table-lookup, which is shown in Figure 3.5. First, we look up the lowest bit of

Priority_Ready_Row_Groups and Priority_Ready_Col_Groups. With these two bits,

we can find out the corresponding bitmap of the Priority_Ready_Table. Finally we

look up the lowest bit of this bitmap.

UNSIGNED_CHAR Mapping_Table [256] = { 0, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 6, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 7, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 6, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0 };

Figure 3.4 Mapping Table for Finding the Highest Priority Task

Row = Mapping_Table [Priority_Ready_Row_Groups]; Col = Mapping_Table [Priority_Ready_Col_Groups];

highest_ready_priority = (UNSIGNED) ( (Row << 6) + (Col << 3) + Mapping_Table [Priority_Ready_Table[Row][Col]] );

Figure 3.5 Pseudo Code for Finding the Highest Priority Task

(23)

is fixed. However, when the number of tasks is quite small, the Seed scheduling time

may be slower than some non-real-time kernels. This is due to that a non-real-time

kernel usually adopts non-deterministic scheduling, which may find out the highest

priority rapidly when there are very few tasks. But the term real-time does not mean

as fast as possible. Instead, it requires consistent, repeatable, known timing

performance. Therefore, in order to achieve deterministic timing, the small and fixed

computation overhead of Seed scheduling is worthy.

After finding out the highest priority task, Seed will de-queue a task control

block from the ready queue. As shown in Figure 3.6, the Priority_Ready_Task_List is

an array of SEED_TASK (task control block) pointers. Each pointer stands for a single

priority, and points to a list of ready tasks (specifically, TCBs) with that priority. The

TCB list is a doubly-linked list so that we can insert and remove a TCB in a constant

(24)

Figure 3.6 Task Priority Ready Queues with Priorities

.1.3 Interface

ted by the task management component is as follows:

ecify

2.

3.

4. ask: This function terminates the task we specified.

3

The interface expor

1. Seed_Create_Task: This function creates a new task. The user can sp

the time-slice value, preemptive or non-preemptive, priority and so on.

Seed_Resume_Task: This function resumes a previously suspended or created task. It will call the scheduler to check if a reschedule is needed.

Seed_Suspend_Task: This function suspends the specified task. If it is the current running task, the function will invoke the scheduler to selects next

ready task to run.

Seed_Terminate_T

5. Seed_Relinquish_Task: This function will yield the control of CPU to next

same-priority task, and put the task to the end of the corresponding ready

SEED_TASK SEED_TASK SEED_TASK

Priority 1 SEED_TASK Priority 2 SEED_TASK SEED_TASK Priority 511

SEED_TASK SEED_TASK SEED_TASK

Priority 0

(25)

TCB list.

Seed_Task

6. _Sleep: This function suspends the calling task for the specified

7. n changes the priority of the

8.

9. lice: This function changes the time slice of the

The interface routines for internal use are as follows:

Seed_Initialize (i.e., the system

2. ng to execute

3. Scheduler: This function implements the task scheduling algorithm. It

4. ntext_Switch: This function is invoked to perform a task context number of timer ticks (1 timer tick = 10ms).

Seed_Change_Task_Priority: This functio

specified task to the new priority value. This function will call the scheduler

to check if Seed needs to preempt the executing task with new priority task.

Seed_Change_Task_Preemption: This function changes the preemption state of currently executing task. If the preemption value is changed from

non-preemptive to preemptive, it will call the scheduler to check if a

preemption is needed.

Seed_Change_Time_S

specified task to the specified value. If the new time slice value is zero, the

time slicing of the task is disabled.

1. Task_Initialize: This function is called by

initialization function). It is responsible for setting the initial value of the

internal variables and global data structures in task component.

Task_Start: This function will be invoked when the task is goi

at the first time. It will call the task entry function with the parameters of the

task.

Task_

is responsible for finding out the highest priority task, and checks the

preemption state of the executing task to see if a task context-switch is

needed.

(26)

switch. The context (i.e., CPU registers) of the original task is saved into

memory, and the context of the resumed task is loaded into the CPU.

Spinlock_Lock: This function is called to lock a spinlock that protect critica

5. l

6. e code

7. d when the time slice of a task is run

8. _Timeout: This function is called to process the task suspension timeout

9. sk scheduling. The

10. Lock_Scheduler

system resources (e.g., kernel data structures) from simultaneous access. If

other task has already held this spinlock, the calling task will perform context

switch and give the control of CPU to the task that hold the spinlock.

Spinlock_Unlock: This function is called to unlock the spinlock. Th

between Spinlock_lock function and Spinlock_Unlock function will become a

critical section that is mutual exclusive.

Task_Time_Slice: This function is calle

out. It is responsible for moving the task to the end of the corresponding TCB

list.

Task

condition. It will resume the task from the suspend state.

Lock_Scheduler: This function is used to prevent ta scheduler is temporarily stopped after calling this function.

Unlock_Scheduler: This function is the counterpart of function. It is used to continue task scheduling.

(27)

3.3 Interrupt Management

3.3.1 Design

Interrupt is a mechanism for providing immediate response to an external

hardware event. When an interrupt occurs, the CPU suspends the current path of

execution and transfers control to the appropriate ISR (Interrupt Service Routine).

Seed allows a component such as a device driver to register an ISR, un-register an

ISR with for an IRQ number (interrupt request number) dynamically. The HAL

interrupt component will recognize the IRQ, save the CPU context, execute to the ISR,

and restore the context of CPU. The details will be described in section 3.8.

In order to protect the internal data structures from simultaneous access, we

usually disable the interrupts when we are serving an interrupt. However, it is not

desirable to disable the interrupts for a long time in a real-time system. Therefore,

Seed adopts 2-stage interrupt handling scheme, which is also adopted by other

real-time kernels, e.g. the eCos RTOS [18]. The interrupt handling is separated into

two stages, ISR stage and DISR (Deferred Interrupt Service Routine) stage.

In the ISR stage, a normal ISR is executed with interrupts disabled. During the

execution, the ISR may activate a DISR to complete the service later. When the ISR is

finished, the DISR starts. A DISR is allowed to be run with interrupts enabled. Each

DISR has its own stack and control block, and hence it can temporarily be blocked for

synchronization or mutual exclusion purpose. In other words, a DISR is just like a

task except that it is activated by an ISR. Under this 2-stage interrupt handling

mechanism, the interrupts won’t be disabled for a long time.

The eCos kernel also supports DISR. However, the DISRs do not have priorities,

and hence that are executed in FIFO order. This might cause problems when a DISR

(28)

lower priority ISR. By contrast, there are eight priority levels available for Seed

her priority DISR (i.e., activated by a higher priority ISR) becomes

management system, we also take advantage of the mapping table to find DISRs. If a hig

ready, the lower priority DISR is preempted. And, DISRs with the same priority are

executed in the order they are activated. The same as the task scheduling time, the

time of scheduling a DISR is a small constant time.

3.3.2 Implementation

The implementation of the interrupt system is divided into two parts, namely the

ISR and the DISR components.

z ISR component

We define an array called IRQ_Handlers. Each element is a function

pointer to an ISR, and the IRQ number is used for indexing the array.

Therefore, an ISR can be registered and un-registered with this array

dynamically. When an interrupt occurs, the interrupt part of the HAL

component will get the IRQ number from the hardware register, and invoke

the corresponding ISR.

z DISR component

The data structures for implementing the DISR component are similar

with the Seed tasks. It has an 8-bit bitmap, named Active_DISR_Priority,

for the priority status. Since there are only eight priorities for DISRs, the

Active_DISR_Priority is enough to represent the priority status. Besides,

there is ready queue called Active_DISR_First with eight elements for

queuing DISRs. Each element contains a doubly-linked list of DISR control

blocks (i.e., SEED_DISR). Figure 3.7 shows an example. In this figure,

there are DISRs with priority 0 and 7. Therefore, the Active_DISR_Priority

(29)

out the highest priority DISR in a constant time period. It is worth to note

that the scheduler always selects the DISRs to run before running the tasks

in order to completing the interrupt service as fast as possible.

Active_DISR_First

SEED_DISR SEED_DISR SEED_DISR

3.3.3 Interface

The interface exported b

1. Seed_Register_ISR num

2. Seed_Unr routin

Figure 3.7 DISR Data Structures

y the interrupt system is shown in the following.

: This function registers the ISR for the specified IRQ

ber. If the IRQ number has been registered, it will replace the old one.

egister_ISR: This function un-register the interrupt service e.

Priority 1

Priority 7

SEED_DISR SEED_DISR SEED_DISR

Priority 0

NULL

Active_DISR_Priority

(30)

3. S b

4. S ISR. It will

insert the control block of the DISR into the corresponding ready queue. This

The interface routines for internal use are as follows.

1. Interrupt_Initialize: This function is invoked by Seed_Initialize (i.e., the

system ponsible for setting the initial value of

the internal variables and global data structures used by the interrupt system.

2. Forward_ISR: This function is called by the interrupt part of Seed HAL. It calls the corresponding ISR for the given IRQ number.

3. D t: This fu rapper to R funct e

invoked at the first time. It calls the DISR entry function. In addition, it

updates the related global data structures of the DISR after the DISR has eed_Create_DISR: This function creates a DISR and initializes its control lock.

eed_Activate_DISR: This function activates the specified D

function is usually called by an ISR.

initialization function). It is res

ISR_Star nction is a w the real DIS ion. It will b

(31)

3.4

m

3.4.1 Design

time-slic

components (e.g., task m e-sensitive applications. The basic time

tick, which is the time between two successive hardware timer interrupts. In

e classify the timers into two

types accord

The application tim

dynamically by the applications. T

they are exp

can be treated as a useful tool for app r

is the task tim

suspend for a specified tim

3.4.2 Implementation

The implementation of the timing system can be separated into the following two

arts:

Timer Interrupt Handling

Periodic timer interrupt is the base of whole timing system. The HAL of Seed

will initialize the hardware timer and interrupt controller (see Section 3.8). Each

time a timer interrupt happens, the time ISR (i.e., Timer_ISR function) increases

the system clock (i.e., jiffies), and decreases the time-slice value of the running

task and the remaining-time value of the running timer. If the time-slice or the

remaining-time value reaches zero, the Timer_ISR will activate the Timer_DISR,

Ti er Management

This component provides all timing facilities in Seed, including timer ISR,

ing and the timer service. The timer service is used frequently by other kernel

anagement) and tim

unit is

our current implementation, a tick is equal to 10 ms. W

ing to their usage, the application timers and the task timers.

ers can be created, deleted, enabled, and disabled

hese timers execute user-supplied routines when

ired. The user-supplied routine is specified while creating the timer, and

lication programming. The second kind of time

er. Every Seed task has a built-in task timer, which allows a task to

e period.

(32)

which processes the quantum expiration of the task (i.e., call the

Slice function), and handles the timer expiration. The timer

adjusting the entire list on every timer

Task_Time_

expiration either resumes the suspended task for the timeout of task timer, or

calls the user-specified expiration function of application timer.

Timer maintenance

The internal data structure for implementing a task timer or an application

timer is timer control block called BASIC_TIMER. As shown in Figure 3.8, the

active (i.e., enabled) timers are maintained in a doubly-linked list, and the

Active_Timer_List_First pointer references to the first timer (i.e. the running

timer) of the list. The timer list is maintained in the order of expiration time.

Each timer control block contains a remaining-time field, which represents the

timing difference between the expiration time of the timer and the expiration

time of its previous timer. When the field becomes zero, the timer expires. This

approach is used in order to avoid

interrupt.

Figure 3.8 Active Timer List

BASIC_TIMER Active_Timer_List_First

(33)

3.4.

The

pecified timeout

2. S

The

_Initialize: This function is called by Seed_Initialize (i.e., the system initialization function). It is responsible for setting the initial value of the

internal variables and global data structures in timer component.

2. Run_Timer: This function is used to enable an application or task timer. The

timers will be inserted into the active timer list.

3. Stop_Timer: This function is used to disable an application or task timer.

The timers will be removed the active timer list.

4. Timer_ISR: This function is the ISR of timer interrupt. It increases the

system clock and check the tim

5. Timer_DISR: This function is the DISR of timer interrupt. It will be

activated by Timer_ISR when the running timer is timeout or the current

task’s time-slice runs out.

3 Interface

interface exported by the timer system is shown in the following.

1. Seed_Create_Timer: This function creates an application timer. The

user-specified expiration function is executed when the s

value runs out.

eed_Control_Timer: This function is used to enable and disable the specified application timer.

3. Seed_Retrieve_System_Clock: This function returns the current value of the

system clock, which is the number of ticks since the system boots up. The

value increases by one every timer interrupt.

4. Seed_Set_System_Clock: This function sets the system clock to the new

specified value.

interface routines for internal use are as follows.

1. Timer

(34)

6. Timer_Expiration: This function is invoked by Timer_DISR. If a task timer

the suspended is expired, it will call the Task_Timeout function to resume

task. If an application timer is expired, it will call the user-specified

(35)

3.5 M

3.5.1 Design

Dyna

free functions. However e of malloc and free is generally non-deterministic due to the memory management algorithms. In addition, this

mechanism is easily to suffer from the fragmentation problem.

For this reason, in addition to the traditional mechanism, Seed provides an

alternative memory management mechanism which is also adopted by other real-time

kernels, such as μC/OS-II and Nucleus. This alternative mechanism allows the

applications to obtain fixed-sized memory blocks from a partition, which is made of a

contiguous memory area. All memory blocks are the same size in a partition. The

allocation and de-allocation of memory blocks is done in a small constant time. In

addition, this type of memory management also avoids the fragmentation problem.

The limitation of this approach is its inflexibility. If an application needs memory

blocks with different sizes, it has to create many partitions. This makes application

programming a little inconvenient. However, in order to achieve constant timing and

avoid fragmentation, it is still worthy to create partitions.

It deserves to be mentioned that Seed provides options for suspension when

allocating memory. When a task attempts to allocate a memory block from an empty

partition, it can suspend and wait for available block. The task can be resumed when a

block is returned to the partition. There are three kinds of suspension.

z Always suspend: The task always suspends and waits for a block. It is only resumed until a block is available.

z Suspend with a timeout: The task suspends for a block. However, it only waits for a specified timeout ticks.

emory Management

mic memory management is traditionally implemented in the malloc and

(36)

z No suspend: If there is no available block in the partition, the task just get r message without suspension.

pointer (i.e.,

allocated. E

pointer to the partition contro is useful when de-allocating

a block. It a

does not specify the corresponding p rol block when it de-allocates a block.

We prevent application from specifying the partition control block for the following an erro

Besides, if multiple tasks suspend on a single memory partition, the tasks are

resumed in one of the following, which can be specified when the memory partition

was created.

z FIFO (First-In-First-Out) order: Tasks are resumed in the order they were suspended.

z Priority order: Tasks are resumed in the order of their priorities.

This suspension mechanism is similar to Nucleus and μC/OS-II. However, μ

C/OS-II does not support FIFO suspending order, and it does not provide suspension

options when allocating a block from an empty memory partition.

.

3.5.2 Implementation

In this section, we describe how a memory partition is implemented. The internal

data structure of a memory partition is a partition control block called

SEED_PARITION. As shown in Figure 3.9, the partition control block manages a

contiguous memory area. It divides this area into fix-sized blocks, and contains a

free_list) that points to the first free block. The free blocks are linked as a

list by using the linking pointers, the first four bytes of the block data space. Block

allocation and de-allocation involves only the head of the list. Therefore, the time is

constant. Note that the linking pointer can used to store data when the block is

ach block has a four-byte overhead (i.e., block header) that contains a

l block. This reverse pointer

llows constant time de-allocation under the condition that the application

(37)

reaso If

system m drawback of using this pointer is that

it ad

artition.

n. the application returns the block to a wrong partition control block, the

ay crash. As we mentioned above, the

ds four-byte overhead to each block. This makes the available blocks in a

partition become fewer. For example, there will be only four 20-byte blocks available

in a 100-byte p

SE ON

(Partition Control Block)

Block Header Linking pointer ED_PARITI Block Header Linking pointer Block Header Linking pointer NULL free_list

Figure 3.9 Memory Partition Data Structure

The memory partition implementation of Seed is more robust than μC/OS-II.

Specifically, a Seed memory partition provides a reverse pointer to avoid system crash,

which is not available inμC/OS-II. On the other side, a Seed memory partition uses

less space overhead than Nucleus. The latter includes the linking pointers into the

(38)

As for the implementation of suspension, every partition control block has a

waiting list for suspended tasks that are sorted in FIFO or Priority order. If another

task returns a block back to the empty partition, Seed will resume the first waiting

task in the list and give the block directly to the resumed task.

e memory partition is shown in th

1. Seed_Create_Memory_Partition: This function creates a memory

partition with fixed-size blocks. The partition size, the block size, and the

task resuming order can be specified by the caller.

2. Seed_Delete_Memory_Partition: This f a previous created

memory partition. It resumes all the waiting on that partition.

3. Seed_Allocate_Memory_Block: This function allocates a memory block

from the partition. The suspension type is specified by the caller. Note that

the size of the block is already defined when the partition is created.

4. Seed_Free_Memory_Block: This function returns a memory block back to

the partition. If there are tasks waiting on this partition, this function will

resume the first task and give the block to it. Note that the caller does not

need to specify the corresponding partition.

e are as follows.

the in

Terminate_Task

3.5.3 Interface

The interface exported by th e following.

unction deletes

The interface routines for internal us

1. Memory_Partition_Initialize: This function is called by Seed_Initialize

(i.e., the system initialization function). It is responsible for setting the

initial value of ternal variables and global data structures in memory

partition component.

(39)

or Task_Timeout. It will remove the task from the waiting list of the

(40)

3.6 Me

3.6.1 Design

Message queue is a mechanism for tasks to communicate between each other.

Each message queue is capable of holding multiple messages. When a task sends a

message, it will be copied into the message queue. Then the receiving task will copy

the message out of the message queue. A message can be placed at the front of the

queue or at the end of the queue. A message consists of one or more bytes, which can

be specified while creating the queue. However, we suggest that applications set the

message size to the pointer size, that is to say, each message is a pointer. The pointer

can be initialized to point to some application’s data structure that will actually be

referenced by the receiver. By this way, copying a large message can be avoided. In

our implementation, the processing time of sending and receiving a message is

deterministic, and it is relative to the message size.

Seed provides a suspension service for message queue as the memory partition

does in Section 3.5.1. Here are two reasons for suspension. First, when a task is

attempting to send a message to a full message queue, it is suspended and then waits

for available space of the queue. The task is resumed when other task gets a message

from the queue. Second, when a task tries to receive a message from an empty queue,

it is suspended to wait for an incoming message. The task will be resumed when other

task sends a message to the queue. The suspension options (i.e., Always suspend,

Suspend with a timeout, and No suspend) and the suspension orders (i.e., FIFO order

and Priority order) are all the same with the memory partition in Section 3.5.1.

Besides, it is allowed to broadcast a message to all the waiting tasks with Seed

message queue.

(41)

3.6.2 Implementation

The internal of the message queue is a circular buffer, as shown in Figure 3.10.

plementation of suspension is similar to memory partition. There is also a

waiting list for suspending tasks. Note that if other tasks want to send a message into The implementation of Seed is similar to other real-time kernels. The read pointer

points to the first message of the queue, and the write pointer points to the location

where the next message will be inserted. However, if we send a message at the head

of the queue, the message will be inserted into the preceding entry of the read pointer.

The start pointer indicates the starting address of the queue area, and the end pointer

points to the ending address of the queue area. The read and write pointers can wrap

the queue to implement circular buffer.

Figure 3.10 Message Queue Data Structure

The im

start

read

end

(42)

the empty queue, Seed will resume the waiting task and directly copy this message to

fied by caller.

2. Seed_Delete_Message_Queue: This function deletes a created message

queue.

3. Seed_Send_Message_To_Queue: This function places a message at the tail

of the specified queue. If there is not enough queue space, a suspension is

allowed.

4. Seed_Send_Message_To_Front_Of_Queue: This function places a

message at the head of the specified queue. If there is no enough space in

the queue, a suspension is allowed.

5. Seed_Receive_Message_From_Queue: This function receives a message

from specified queue. If there is no message in the queue, a suspension is

allowed.

6. Seed_Boradcast_Message_To_Queue: This function broadcasts a message

to all tasks that are waiting for an incoming message with the specified

message qu

The

the resumed task without copying into the queue. This mechanism saves message

copying time.

3.6.3 Interface

The interface exported by the message queue is shown in the following.

1. Seed_Create_Message_Queue: This function creates a message queue

from a memory area specified by the caller. The queue size, message size,

and suspension order are speci

ssage queue. It resumes all the tasks waiting on that me

eue.

interface routines for internal use are shown as follows:

(43)

the system initialization function). It is responsible for setting the initial

value of the internal variables and global data structures in the message

queue component.

2. Message_Queue_Cleanup: This function is invoked by Terminate_Task or

eout. It will remove the suspending task from the waiting list of Task_Tim

(44)

3.7 Sem

3.7.1 Design

Sema for synchronizing the execution of the critical section

in an application. Seed pr

ranges from 0 to 2

mutual exclusion. T maphore are obtain and release. When

a task wants to get into the critical section (e.g., access the shared resource), it tries to

obtain the semaphore. If the semaphore is obtained successfully, the counter of the

semaphore will be decreased by one. Inversely, when a task leaves the critical section,

the task will release the semaphore and increases the counter by one.

However, if a task fails to obtain the semaphore (i.e., the counter of semaphore is

zero), the task may suspend on the waiting list until it is available. The suspension

options and suspension orders are the same with the memory partition and the

message queue (Section 3.5.1 and Section 3.6.1). These options and orders are free for

applications to choose. The optional timeout on obtain-semaphore suspension can be

used to recover from a deadlock.

Priority inversion is a common problem in real-time kernels. It occurs when a

higher priority task is suspended on a semaphore that a lower priority has. This

problem can be solved via the priority-inheritance protocol [22]. In this protocol,

kernel increases the priority of the lower priority task to the priority of the higher

priority task (i.e., inherit the priority of higher priority task). When the priority

inherited task release the semaphore, the priority is reverted to its original value. Seed

supports priority-inheritance for semaphores in order to help the higher priority task

obtaining the semaphore as soon as possible.

Note that theμC/OS-II kernel does not support a general priority-inheritance

aphore

phore is a mechanism

ovides counting semaphores. The value of each semaphore

32

-1. If the semaphore value is 1, it is a binary semaphore for

(45)

protocol. It requires the users to reserve some priority levels for priority-inheritance

n not allow two tasks to share the same priority. Seed kernel does not

prior

inal priority (i.e., invoking

aphore.

semaphore. If the counter of semaphore is zero, a suspension is allowed. usage since it ca

have such limitation, so that it can implement the general priority-inheritance

protocol.

3.7.2 Implementation

The internal structure of a semaphore is a 32-bit integer. Besides, there is also a

waiting list for the suspending tasks. If other tasks release a semaphore, Seed will

resume the waiting task and pass the semaphore directly to the resumed task.

When an application creates a semaphore, it can specify whether

ity-inheritance is enabled or not. If priority-inheritance is enabled and a task is

suspended on an un-available semaphore, the semaphore will check whether the

priority of owner task is lower than the suspending task. If so, the owner task will

inherit the highest priority among the suspending tasks and save the original priority

(i.e., invoking Inherit_Priority function). After the owner task releases the semaphore,

the priority of the owner task is reverted to the orig

Disinherit_Priority function).

3.7.3 Interface

The interface exported by the semaphore is shown in the following.

1. Seed_Create_Semaphore: This function creates a semaphore. The

counting value and the suspension order are specified by caller.

2. Seed_Delete_Semaphore: This function deletes a created semaphore. It

resumes all the tasks waiting on that sem

(46)

4. Seed_Release_Semaphore: This function releases an instance of

semaphore. It will resume and give the semaphore to the suspended task if it

is waiting.

The interface routines for internal use are shown as follows:

alize: This function is called by Seed_Initialize (i.e., the

Task or

1. Semaphore_Initi

system initialization function). It is responsible for setting the initial value

of the internal variables and global data structures in semaphore component.

2. Semaphore_Cleanup: This function is invoked by Terminate_

Task_Timeout. It will remove the suspending task from the waiting list of

the semaphore.

3. Inherit_Priority: This function is used to implement the priority

inheritance protocol. It helps the owner task to inherit higher priority of the

waiting task.

4. Disinherit_Priority: This function is used to implement the priority

(47)

3.8

r

In this sec

the hardware dependent portion of the kernel. We can port Seed kernel to another

hardware platform more efficiently by only replacing or modifying the HAL.

plementation as an example to introdu Interrupt, subsections.

3.8.1 Boot

As shown i

kernel image into the memory, and jumps to the boot part of the HAL (i.e., the entry

point of Se

devices. In other words, it contains the lo

board, it does following jobs:

save CPU contexts, branch exception handlers, and restore CPU contexts).

z System map initialization: It sets up the system memory mapping of the board.

z Stack assignment: It assigns stack space for each CPU operation modes. z Hardware devices initialization: It initializes hardware devices on the board

(e.g., hardware timer, interrupt controller, terminal driver and etc.).

After hardware initialization is finished, the boot part of HAL will invoke the

eed_Initialize function. This function is hardware-independent and is used to call the

initial functions of other Seed components. It creates an idle task and application tasks,

Ha dware Abstract Layer (HAL)

tion, we introduce the Hardware Abstraction Layer (HAL). The HAL is

Currently, Seed is running on SNDS100 board. And, we take our im

ce the HAL. The HAL are divided into four parts: Boot,

CPU Context and Devices. Each part of HAL is described in the following

n Figure 3.11, the default boot loader of SNDS100 loads the Seed

ed kernel). The boot part is responsible for initializing the hardware

w-level initialization functions. In SNDS100

z Vector table setting: It sets the vector table which corresponds to the ARM exception modes [9][21]. Then, it handles the branch of an exception (i.e.,

(48)

and invokes the scheduler to start these tasks.

Boot loader of SNDS100

itialize the interrupt controller at the beginning.

Then it ena

Service Routines (ISRs) with

In addition, the interrupt pa

hardware interrupt occurs,

1. e memory buffer which is a member of

2.

Figure 3.11 Seed Boot Flow

3.8.2 Interrupt

The interrupt part of HAL manages the hardware interrupt system. The

HAL_IRQ_Init function is used to in

bles the interrupts that we want to handle, and registers the Interrupt

corresponding IRQ numbers.

rt of HAL helps kernel to handle interrupts. When a

it takes following steps:

It saves the CPU contexts into th

task control block (i.e., jmpbuf). Because an interrupt may occur at any

time, it must save all of the CPU registers.

It recognizes the IRQ number by reading the hardware register. Then it

invokes the corresponding ISR.

3. After the ISR is finished, the interrupt part of HAL will check whether

there is a ready DISR. If there is a ready DISR, its previous saved context Boot part of HAL

Seed_Initialize function

Seed Kernel

Hardware-dependent

(49)

will be loaded.

4. If there is not a ready DISR and the interrupted task is preemptive, the

inter eck whether there is a higher priority task

ready to run. If there is a higher priority task, its previous saved context

. Otherwise, the kernel loads the context of the interrupted

task.

Besides, the interrupt part of HAL provides the interfaces to enable or disable

interrupts, name HAL_Disable_IRQ, respectively.

3.8.3 CPU Context

This part of HAL provides a set of , it provides

interfaces for saving and restoring the CPU context. When a task A is switched to

d invokes HAL_CS_Save_Context function to save the context of

ber of restored CPU

ay occur at any time,

all of the CPU registers are saved. However

the Task_C

registers (i.e., a1 to a4 in

3.8.4 Devices

This part of HAL

rupt part of HAL will ch

will be loaded

ly HAL_Enable_IRQ and

CPU primitives. Specifically

another task B, See

A and HAL_CS_Restore_Context function to restore the context of B. However, there

is still another interface called HAL_Interrupt_Restore_Context for context restoration.

This function is used to restore the context that was saved by interrupt part of HAL.

The difference between these two restoring functions is the num

registers. The HAL_Interrupt_Restore_Context function restore more registers than

the HAL_CS_Restore_Context function. Because an interrupt m

, the normal context switch only occurs at

ontext_Switch function, which does not care the content of argument

ARM CPU).

(50)

For examp timer and UART driver of SNDS100 are initialized by the

HAL_

initializes

HAL_UAR

device.

In addition, the data types of Seed are defined in a single header file for the case

of po

erefore, if

the type is different at other hardware platforms, we only have to modify this file. le, the hardware

Timer_Init and HAL_UART_Init functions, respectively. The HAL_Timer_Init

the timer controller and assigns the timer interrupt period as 10ms. The

T_Init initializes the UART device and sets a proper baud rate for that

rting. For example, the type UNSIGNED means a 32-bit unsigned long integer in

(51)

3.9 Implementation Status

In this section, we describe the status of the implementation.

3.9.1 Platform

Seed is currently implemented on Samsung SNDS100 Evaluation Board, which

is based on the S3C4510B/KS32C50100 microcontroller [19][20]. Samsung

S3C4510B i

RAM module, SDRAM, serial ports for console, and Ethernet interface. Figure 4.1

lustrates the SNDS100 block diagram.

Seed works correctly with the SNDS100 board. The Seed HAL is responsible for

anaging the SNDS100 board. The Ethernet and UART drivers are well ported and

erating correctly.

ed Kernel Components

The implemented and tested kernel components are shown as follow:

z Task management

z Interrupt management (ISR and DISR) z Memory partition

z Timer management

z Message queue management z Semaphore management

z Hardware Abstraction Layer (HAL)

s a 16/32-bit RISC microcontroller built around the ARM7TDMI RISC

processor. It integrates an Ethernet controller. Thus, it is a good choice for

Ethernet-based embedded systems. The S3C4510B can operate in a frequency up to

50MHz. Besides the S3C4510B, the SNDS100 Board also consists of boot EEPROM,

D

il

m

op

(52)

Figure 4.1 SNDS100 Block Diagram2

sted drivers on SNDS100 board are shown as follow:

3.9.4 LW

r ability, we ported a small TCP/IP stack

3.9.3 Implemented Drivers

The implemented and te

z UART driver z Timer driver z Ethernet driver

IP Integration

In o der to provide the Internet-access cap

2

(53)

called lwIP (i.e., lightweight IP) [5][7] to the Seed kernel. lwIP is an open source

implementation of TCP/IP stack. Its design goal is to reduce memory usage and code

size, making it suitable for use in an embedded system. lwIP defines a common

interface called OS emulation layer between its code and the underlying OS kernel.

To port lwIP to Seed kernel, we only have to modify this layer. This layer requires the

functionalities such as multi-tasking, memory management, timer, semaphore and

message queue. These functionalities are fully supported by Seed kernel services.

Table 3.1 shows the function mapping between OS emulation layer and the Seed

kernel. Each function in the OS emulation layer is mainly implemented by a single

Seed kernel function with argument adjustment.

Functions in OS Emulation Layer Seed Kernel Functions

sys_thread_new Seed_Create_Task sys_mbox_new Seed_Create_Message_Queue sys_mbox_free Seed_Delete_Message_Queue sys_mbox_post Seed_Send_Message_To_Queue sys_arch_mbox_fetch Seed_Receive_Message_From_Queue sys_sem_new Seed_Create_Semaphore

sys_ m_free se Seed_Delete_Semaphore

sys_arch_sem_wait Seed_Obtain_Semaphore

sy ses_ m_signal Seed_Release_Semaphore

Table 3.1 Function Mapping between lwIP OS Emulation Layer and Seed kernel

support lwIP. The network applications that currently run on lwIP / Seed are as Besides, we also ported on Ethernet driver to the SNDS100 board in order to

(54)

following:

z TCP Echo server z UDP Echo server z Simple HTTP server

(55)

Chapter 4

Experimental Results

In this chapter eriment results of Seed kernel. The code size

and primitiv We measure the

network performance in Section 4.2.

4.1 Basic Measurement

4.1.1 Code Size

The code was compiled for ARM7TDMI using ARM Developer Suite 1.2 [2].

The resulting size of the compiled code is shown in Table 4.1. The Code size column

shows the size of the compiled executable object code, and the Data size column

shows the data size used by the object code. The total code size of Seed OS is about

16K bytes and the total data size is about 35K. The libraries are some primitive

libraries for applications, such as string library, standard library (stdlib) and etc. The

kernel image generated by the linker is about 21K bytes. In conclusion, Seed kernel is

very small and is suitable for embedded systems whose hardware resources are

scarce.

Function Code size (bytes) Data size (bytes) , we present the exp

e performance measurement are presented in Section 4.1.

HAL 2356 27388 Task Management 3164 2500 Interrupt Management 1036 257 Timer Management 1404 1256 Memory Partition 664 0 Message Queue 2004 0

(56)

Semaphore 776 0

Other kernel services 956

Libraries 4248 3441

308

Total 16608 35150

Table 4.1 Code Size of Seed Kernel

Measurement

we measure the performance of the primary functions in Seed.

Table 4.2 Performance of Seed Kernel Functions

4.1.2 Primitive Performance

In this section,

The performance result is shown in Table 4.2. Note that interrupts are disabled during

the performance measurement. These results can be treated as a reference while

creating applications on Seed kernel.

Function Time (μ-sec) Cycles

Task_Schduler 16.079 843 Task_Context_Switch 18.081 948 Create_Task 47.207 2475 Resume_Task 8.545 448 Suspend_Task 14.763 774 Create_Message_Queue 10.147 532 Send_Message_To_Queue 16.479 864 Receive_Message_From_Queue 16.193 849 Create_Semaphore 4.101 215 Obtain_Semaphore 4.120 216 Release_Semaphore 7.706 404 Create_Memory_Partition 18.959 994 Allocate_Memory_Block 4.005 210 Free_Memory_Block 4.520 237 Create_Timer 21.954 1151

數據

Figure 3.1 shows the architecture of the Seed system. As shown in the figure, the
Figure 3.1 Seed Kernel Architecture
Figure 3.2 Task States
Figure 3.3 Data Structures for Task Scheduling
+7

參考文獻

相關文件

After the Opium War, Britain occupied Hong Kong and began its colonial administration. Hong Kong has also developed into an important commercial and trading port. In a society

The teacher needs to plant the seed for ideas by describing a conflict before asking the students to start writing the acrostic script.. Once the students have read and understood the

利用 determinant 我 們可以判斷一個 square matrix 是否為 invertible, 也可幫助我們找到一個 invertible matrix 的 inverse, 甚至將聯立方成組的解寫下.

Then, we tested the influence of θ for the rate of convergence of Algorithm 4.1, by using this algorithm with α = 15 and four different θ to solve a test ex- ample generated as

Numerical results are reported for some convex second-order cone programs (SOCPs) by solving the unconstrained minimization reformulation of the KKT optimality conditions,

Particularly, combining the numerical results of the two papers, we may obtain such a conclusion that the merit function method based on ϕ p has a better a global convergence and

By exploiting the Cartesian P -properties for a nonlinear transformation, we show that the class of regularized merit functions provides a global error bound for the solution of

˙Please visit the Outpatient Clinic of Family Please visit the Outpatient Clinic of Family Medicine Division for a follow-up diagnosis and