CAmkES Tutorial
强烈推荐阅读
https://github.com/seL4/camkes-tool/blob/master/docs/index.md
中的Terminology章节,下面就对我的阅读和理解做一个记录
Terminology
Abstract Syntax Tree (AST)
抽象语法树:用形式化语言书写的文本的一个语法结构
这段代码可以变成下面这棵AST
与AST相对的是一个C(oncrete)ST,区别就是CST是在编译的过程中得到的一个Parce Tree,就会比AST要增加一些上下文相关的分析。
Architecture Description Language (ADL) 体系描述语言
这里是特指CAmkES input sepecification language
Assembly 概括
作为一个系统中的成分,作用是概括一个系统的组成。
可以被想做是对整个系统的完全的描述。一个系统至少需要包括一个Assembly. 如果一个系统有多个assembly,也就相当于有一个Assembly把所有的assembly中的组成和配置全部包括进来。
Attribute 参数
对于组成 (Component) 和连接器 (Connector) 都会有一些相关的规定了类型的额外数据。
在定义组成和连接时需要描述这些参数的名称和类型。
这些参数的数值会在实例化的时候状态,这样一个填写就称作setting。
如果没有初始化,那么就会使用默认值,如果有别名,而且别名的默认不同,那么就会使用别名的默认。
Component 组成成分
一个功能性的实体,在这里Component更像class,作为一个概念而不是一个实例存在
component foo f,描述了一个实例f,它的类型是foo
Composition
一个Component和Connector的实例组成一个系统。它们合在一起就是一个Composition。它在形式化规范中是必要的。会放在概要块中,并包含一个可选的配置。
Compound Component 复合组成成分
一个具有Coposition节的Component,同时可能有一个配置的节
Configuration
一个描述setting的容器。是一个放置给定系统的参数分配的句法的元素
Connection
一个Connector的实例,一个Connection会连接两个实例。Connector的实例并不会在任何具体的方式上特殊化这个Connector,所以很容易混淆这两个概念。
Connector
在两个实例之间的连接的类型。类似Component的概念,是一个理论的抽象,而Connection是具体的实现。
Consumes
一个Component接收事件的接口。如果说一个组成部分Consume了一个具体的事件,表示这个组成部分可以接收和处理这个事件。
Dataport
Component使用的端口接口。一个Component的数据端口在其运行时可以作为共享内存的区域。
Direction
参数传递的方向,in:调用者传给被调用者,out:被调用者传给调用者
Inout:双向传递,refin: 等价于in,不过在C的后端会被优化成pass-by-reference(引用传递)
Emits
Component发出事件的接口。如果一个Component释放了一个事件,就说明它产生了一个这个类型的事件。
Event
一个Component的异步的信号。完完全全由它们的identifier来做解释,它本身只是一个数字的值,有点像中断号的传递。
Exported Interface
对于内部的一个组成部分的实现来说,它的接口就是内部的Component实现的同一个名字的接口。
外部的接口,就是去暴露出一些接口,同时潜在的在内部来完善这些接口。
Instance
具体的实现,这里特指Component的实现。
Interface
一个抽象的交互point。interface的子类包括了procedure,event 和 port
Internal Connection
在一个复合类型中声明的连接两个实例的接口的连接。
Maybe
接口可以使用maybe关键字来声明这个接口是可选的(optional)。
可选的接口不需要与其他的接口相连,C语言中与可选的接口相连的部分(函数以及dataport的指针)称为弱符号,如果可选的接口没有任何相连,那么这些相关的Symbol就会缺乏定义,就会在运行的时候取NULL的值
Method 方法
函数
Parameter 参数
一个函数方法引用的数据。相当于函数的参数。
Port
一种在语义上代表共享内存的接口。
Procedure
一个在语义上表示函数调用的接口。包括了一系列可以被单独调用的方法。
Setting
把一组参数赋值的分配。它不负责定义类型,这些类型会在Component和Connector中定义
Struct
可以作为参数类型的一种复合类型
Uses
一个Component所调用的程序接口。一个Component包括并实现了这个程序中所有对函数的调用。
Virtual Interface
一个复合的组成部分的接口,但是没有被其实现,而是其内部的某个Component的接口的别名。
Example
struct cat {
int paws;
string name;
}
procedure thing {
int func(in int x);
}
component foo {
control;
uses thing t1;
emits sig s1;
dataport buffer b1;
attribute cat kitty;
}
component bar {
provides thing t2;
consumes sig s2;
dataport buffer b2;
}
assembly {
composition {
component foo f;
component bar b;
connection RPC c1(from f.t1, to b.t2);
connection Notification c2(from f.s1, to b.s2);
connection SharedData c3(from f.b1, to b.b2);
}
configuration {
f.kitty = {"name": "meows", "paws": 4};
}
}
CAmkES Tutorial 实验部分
CAmkES-0
camkes hello world
hello.camkes文件:只有一个Component Client
/*
* CAmkES tutorial part 0: just a component.
*/
component Client {
control;
}
assembly {
composition {
component Client client;
}
}
CMakeLists.txt中的相关核心代码:
find_package(camkes-tool REQUIRED)
camkes_tool_setup_camkes_build_environment()
DeclareCAmkESComponent(Client SOURCES client.c)
DeclareCAmkESRootserver(hello.camkes)
GenerateCAmkESRootserver()
# utility CMake functions for the tutorials (not required in normal, non-tutorial applications)
set(FINISH_COMPLETION_TEXT "Hello CAmkES World")
set(START_COMPLETION_TEXT "Hello CAmkES World")
configure_file(${SEL4_TUTORIALS_DIR}/tools/expect.py ${CMAKE_BINARY_DIR}/check @ONLY)
这章节没有什么需要修改的地方,就是按照指令执行就可以了。
不过还是可以看到比如说这里不再是RootTask而是RootServer
CAmkES-1
Background
介绍了Component和Connection和Interface的概念。
Component是逻辑上的代码和资源的组。他们只能通过静态定义的接口来与其他的Component交流。
Connection是一种两个Component之间交流方法的表示。实现的方法有共享内存、同步IPC、notification或者其他提供的操作。在这个lab中,会使用同步的IPC。在实现的语句中,他们被压缩成了seL4_Call这个系统调用。
Interface就是别的Component访问自己时,自己所开放的方法。具体分为Dataport, Procedural interfaces, Notifications. 这个lab中使用的时Procedure的方式。
Exercise
第一步是修改assembly,就直接找猫画虎,把Empty给改成需要的两个
第二步是增加一个Connection,提示我们去查看github上面的readme,可以看到Connection的定义方式是通过seL4RPCCall这个函数
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Jl7f5wrB-1653277951600)(C:\Users\user\AppData\Roaming\Typora\typora-user-images\image-20220426204859802.png)]
hello-1.camkes文件:
component EmptyComponent {
}
component Client {
control;
uses HelloSimple hello;
}
component Echo {
provides HelloSimple hello;
}
assembly {
composition {
// Exercise1: 删除Empty,增加Client和Echo
component Client client;
component Echo echo;
/* hint 1: use seL4RPCCall as the connector (or you could use seL4RPC if you prefer)
* hint 2: look at
* https://github.com/seL4/camkes-tool/blob/master/docs/index.md#creating- an-application
*/
connection seL4RPCCall hello_con(from client.hello, to echo.hello);
}
}
第三步是补充HelloSimple这个程序段,根据提示,需要写一个函数say_hello,没有返回值,传入一个string作为参数
interface/HelloSimple.idl4
/* Simple RPC interface */
procedure HelloSimple {
/* TODO define RPC functions */
/* hint 1: define at least one function that takes a string as input parameter. call it say_hello. no return value
* hint 2: look at https://github.com/seL4/camkes-tool/blob/master/docs/index.md#creating-an-application
*/
void say_hello(in string str);
};
第四步是实现RPC的hello程序(但实际上已经实现了,这里需要注意一下这个函数名 = 接口名_接口中的函数名)
components/Echo/echo.c
/*
* CAmkES tutorial part 1: components with RPC. Server part.
*/
#include <stdio.h>
/* generated header for our component */
#include <camkes.h>
/* TASK 5: implement the RPC function. */
/* hint 1: the name of the function to implement is a composition of an interface name and a function name:
* i.e.: <interface>_<function>
* hint 2: the interfaces available are defined by the component, e.g. in hello-1.camkes
* hint 3: the function name is defined by the interface definition, e.g. in interfaces/HelloSimple.idl4
* hint 4: so the function would be: hello_say_hello()
* hint 5: the CAmkES 'string' type maps to 'const char *' in C
* hint 6: make the function print out a mesage using printf
* hint 7: look at https://github.com/seL4/camkes-tool/blob/master/docs/index.md#creating-an-application
*/
void hello_say_hello(const char *str) {
printf("Component %s saying: %s\n", get_instance_name(), str);
}
第五步是在Client中调用
/*
* CAmkES tutorial part 1: components with RPC. Client part.
*/
#include <stdio.h>
/* generated header for our component */
#include <camkes.h>
/* run the control thread */
int run(void) {
printf("Starting the client\n");
printf("-------------------\n");
/* TODO: invoke the RPC function */
/* hint 1: the name of the function to invoke is a composition of an interface name and a function name:
* i.e.: <interface>_<function>
* hint 2: the interfaces available are defined by the component, e.g. in hello-1.camkes
* hint 3: the function name is defined by the interface definition, e.g. in interfaces/HelloSimple.idl4
* hint 4: so the function would be: hello_say_hello()
* hint 5: look at https://github.com/seL4/camkes-tool/blob/master/docs/index.md#creating-an-application
*/
char *shello = "hello world";
hello_say_hello(shello);
printf("After the client\n");
return 0;
}
CAmkES-2
这个Lab的任务是放在代码中的
TASK 1,2
在Client.camkes中:
定义一个事件,这里事件和函数不一样,它不需要像上面一样去实现一个HelloSimple类,而是直接写一个类名就可以,而不需要实现,提示中你写一个string类型也可以,在这里我们还是写一个自己编造的类名。而在Procedure中想要释放一个事件就是 时间名_emit() 就可以了。
component Client {
/* include definitions of typedefs for the dataports */
include "str_buf.h";
/* this component has a control thread */
control;
/* TASK 1: the event interfaces */
/* hint 1: specify 2 interfaces: one "emits" and one "consumes"
* hint 2: you can use an arbitrary string as the interface type (it doesn't get used)
* hint 3: look at https://github.com/seL4/camkes-tool/blob/master/docs/index.md#an-example-of-events
*/
emits MyEvent ce;
consumes MyEvent cs;
/* TASK 2: the dataport interfaces */
/* hint 1: specify 3 interfaces: one of type "Buf", one of type "str_buf_t" and one of type "ptr_buf_t"
* hint 2: for the definition of these types see "str_buf.h".
* hint 3: look at https://github.com/seL4/camkes-tool/blob/master/docs/index.md#an-example-of-dataports
*/
dataport Buf d1;
dataport str_buf_t d2;
dataport ptr_buf_t d3;
}
TASK2要实现一个dataport的接口,其实和普通的接口很类似只是把interface改成了dataport。只是这里特指可以传数据的接口,同时也在str_buf.h中定义了相关的数据类型:
/*
* CAmkES tutorial part 2: events and dataports
*/
#ifndef __STR_BUF_H__
#define __STR_BUF_H__
#include <camkes/dataport.h>
#define NUM_STRINGS 5
#define STR_LEN 256
/* for a typed dataport containing strings */
typedef struct {
int n;
char str[NUM_STRINGS][STR_LEN];
} str_buf_t;
#define MAX_PTRS 20
/* for a typed dataport containing dataport pointers */
typedef struct {
int n;
dataport_ptr_t ptr[MAX_PTRS];
} ptr_buf_t;
#endif
TASK 3,4
都在Echo.camkes中,和1,2类似就不多讲了
component Echo {
/* include definitions of typedefs for the dataports */
include "str_buf.h";
/* TASK 3: the event interfaces */
/* hint 1: specify 2 interfaces: one "emits" and one "consumes"
* hint 2: you can use an arbitrary string as the interface type (it doesn't get used)
* hint 3: look at https://github.com/seL4/camkes-tool/blob/master/docs/index.md#an-example-of-events
*/
emits MyEvent ee;
consumes MyEvent es;
/* TASK 4: the dataport interfaces */
/* hint 1: specify 3 interfaces: one of type "Buf", one of type "str_buf_t" and one of type "ptr_buf_t"
* hint 3: look at https://github.com/seL4/camkes-tool/blob/master/docs/index.md#an-example-of-dataports
*/
dataport Buf d1;
dataport str_buf_t d2;
dataport ptr_buf_t d3;
}
TASK 5,6,7,8
修改 hello-2.camkes,大概就是使用一些函数来把之前的定义连接起来,同时给之前的访问加上控制的权限和限制。
/*
* CAmkES tutorial part 2: events and dataports
*/
import <std_connector.camkes>;
/* import component defintions */
import "components/Client/Client.camkes";
import "components/Echo/Echo.camkes";
assembly {
composition {
/* component instances */
component Client client;
component Echo echo;
/* TASK 5: Event connections */
/* hint 1: connect each "emits" interface in a component to the "consumes" interface in the other
* hint 2: use seL4Notification as the connector
* hint 3: look at https://github.com/seL4/camkes-tool/blob/master/docs/index.md#an-example-of-events
*/
connection seL4Notification channel(from client.ce, to echo.es);
connection seL4Notification channel(from echo.ee, to client.cs);
/* TASK 6: Dataport connections */
/* hint 1: connect the corresponding dataport interfaces of the components to each other
* hint 2: use seL4SharedData as the connector
* hint 3: look at https://github.com/seL4/camkes-tool/blob/master/docs/index.md#an-example-of-dataports
*/
connection seL4SharedData channel1(from client.d1, to echo.d1);
connection seL4SharedData channel2(from client.d2, to echo.d2);
connection seL4SharedData channel3(from client.d3, to echo.d3);
}
configuration {
/* TASK 7: set component priorities */
/* hint 1: component priority is specified as an attribute with the name <component name>.priority
* hint 2: the highest priority is represented by 255, the lowest by 0
*/
client.priority = 100;
echo.priority = 90;
/* TASK 8: restrict access to dataports */
/* hint 1: use attribute <component>.<interface_name>_access for each component and interface
* hint 2: appropriate values for the to_access and from_access attributes are: "R" or "W"
* hint 4: make the "Buf" dataport read only for the Echo component
* hint 3: make the "str_buf_t" dataport read only for the Client component
*/
echo.d1_access = "R";
client.d2_access = "R";
}
}
TASK 9-16
client.c 中
主要是根据提示写入一些内容,可以对照str_buf.h中的内容,先放入字符串的数量,然后放入字符串的内容。
其中d1表示Client写入的dataport,d2表示Echo写入的dataport,分别进行一次Client的写入,和Client的读取,以及一次错误的尝试
/*
* CAmkES tutorial part 2: events and dataports
*/
#include <stdio.h>
#include <string.h>
#include <camkes/dataport.h>
/* generated header for our component */
#include <camkes.h>
/* strings to send across to the other component */
char *s_arr[NUM_STRINGS] = { "hello", "world", "how", "are", "you?" };
/* run the control thread */
int run(void) {
printf("%s: Starting the client\n", get_instance_name());
/* TASK 9: copy strings to an untyped dataport */
/* hint 1: use the "Buf" dataport as defined in the Client.camkes file
* hint 2: to access the dataport use the interface name as defined in Client.camkes.
* For example if you defined it as "dataport Buf d" then you would use "d" to refer to the dataport in C.
* hint 3: first write the number of strings (NUM_STRINGS) to the dataport
* hint 4: then copy all the strings from "s_arr" to the dataport.
* hint 5: look at https://github.com/seL4/camkes-tool/blob/master/docs/index.md#an-example-of-dataports
*/
*(int *)d1 = NUM_STRINGS;
int p = 4;
for(int i = 0; i < NUM_STRINGS; ++i){
strncpy((char*)d1 + p, s_arr[i], 10);
p += STR_LEN;
}
/* TASK 10: emit event to signal that the data is available */
/* hint 1: use the function <interface_name>_emit
* hint 2: look at https://github.com/seL4/camkes-tool/blob/master/docs/index.md#an-example-of-events
*/
ce_emit();
/* TASK 11: wait to get an event back signalling that the reply data is avaialble */
/* hint 1: use the function <interface_name>_wait
* hint 2: look at https://github.com/seL4/camkes-tool/blob/master/docs/index.md#an-example-of-events
*/
cs_wait();
/* TASK 12: read the reply data from a typed dataport */
/* hint 1: use the "str_buf_t" dataport as defined in the Client.camkes file
* hint 2: to access the dataport use the interface name as defined in Client.camkes.
* For example if you defined it as "dataport str_buf_t d_typed" then you would use "d_typed" to refer to the dataport in C.
* hint 3: for the definition of "str_buf_t" see "str_buf.h".
* hint 4: use the "n" field to determine the number of strings in the dataport
* hint 5: print out the specified number of strings from the "str" field
* hint 6: look at https://github.com/seL4/camkes-tool/blob/master/docs/index.md#an-example-of-dataports
*/
printf("%d\n", d2->n);
for(int i = 0; i < d2->n; ++i){
printf("%s\n", d2->str[i]);
}
/* TASK 13: send the data over again, this time using two dataports, one
* untyped dataport containing the data, and one typed dataport containing
* dataport pointers pointing to data in the untyped, dataport.
*/
/* hint 1: for the untyped dataport use the "Buf" dataport as defined in the Client.camkes file
* hint 2: for the typed dataport use the "ptr_buf_t" dataport as defined in the Client.camkes file
* hint 3: for the definition of "ptr_buf_t" see "str_buf.h".
* hint 4: copy all the strings from "s_arr" into the untyped dataport
* hint 5: use the "n" field of the typed dataport to specify the number of dataport pointers (NUM_STRINGS)
* hint 6: use the "ptr" field of the typed dataport to store the dataport pointers
* hint 7: use the function "dataport_wrap_ptr()" to create a dataport pointer from a regular pointer
* hint 8: the dataport pointers should point into the untyped dataport
* hint 9: for more information about dataport pointers see: https://github.com/seL4/camkes-tool/blob/master/docs/index.md
*/
d3->n = 1;
d3->ptr[0] = dataport_wrap_ptr(d1);
/* TASK 14: emit event to signal that the data is available */
/* hint 1: we've already done this before */
ce_emit();
/* TASK 15: wait to get an event back signalling that data has been read */
/* hint 1: we've already done this before */
cs_wait();
printf("%s: the next instruction will cause a vm fault due to permissions\n", get_instance_name());
/* TASK 16: test the read and write permissions on the dataport.
* When we try to write to a read-only dataport, we will get a VM fault.
*/
/* hint 1: try to assign a value to a field of the "str_buf_t" dataport */
d2->n = 3;
return 0;
}
TASK 17-25
在echo.c中增加相应的内容
/*
* CAmkES tutorial part 2: events and dataports
*/
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <camkes/dataport.h>
#include <sel4utils/sel4_zf_logif.h>
/* generated header for our component */
#include <camkes.h>
/* hepler function to modify a string to make it all uppercase */
void uppercase(char *str) {
while (*str != '\0') {
*str = toupper(*str);
str++;
}
}
void callback_handler_2(void *a);
/* this callback handler is meant to be invoked when the first event
* arrives on the "consumes" event interface.
* Note: the callback handler must be explicitly registered before the
* callback will be invoked.
* Also the registration is one-shot only, if it wants to be invoked
* when a new event arrives then it must re-register itself. Or it can
* also register a different handler.
*/
void callback_handler_1(void *a) {
/* TASK 19: read some data from the untyped dataport */
/* hint 1: use the "Buf" dataport as defined in the Echo.camkes file
* hint 2: to access the dataport use the interface name as defined in Echo.camkes.
* For example if you defined it as "dataport Buf d" then you would use "d" to refer to the dataport in C.
* hint 3: first read the number of strings from the dataport
* hint 4: then print each string from the dataport
* hint 5: look at https://github.com/seL4/camkes-tool/blob/master/docs/index.md#an-example-of-dataports
*/
/* TASK 20: put a modified copy of the data from the untyped dataport into the typed dataport */
/* hint 1: modify each string by making it upper case, use the function "uppercase"
* hint 2: read from the "Buf" dataport as above
* hint 3: write to the "str_buf_t" dataport as defined in the Echo.camkes file
* hint 4: to access the dataport use the interface name as defined in Echo.camkes.
* For example if you defined it as "dataport str_buf_t d_typed" then you would use "d_typed" to refer to the dataport in C.
* hint 5: for the definition of "str_buf_t" see "str_buf.h"
* hint 6: use the "n" field to specify the number of strings in the dataport
* hint 7: copy the specified number of strings from the "Buf" dataport to the "str" field
* hint 8: look at https://github.com/seL4/camkes-tool/blob/master/docs/index.md#an-example-of-dataports
* hint 9: you could combine this TASK with the previous one in a single loop if you want
*/
d2->n = *(int*)d1;
char* p = (char*)d1 + 4;
for(int i = 0; i < d2->n; ++i){
strncpy(d2->str[i], p, 10);
p += STR_LEN;
}
/* TASK 21: register the second callback for this event. */
/* hint 1: use the function <interface name>_reg_callback()
* hint 2: register the function "callback_handler_2"
* hint 3: pass NULL as the extra argument to the callback
* hint 4: look at https://github.com/seL4/camkes-tool/blob/master/docs/index.md#an-example-of-events
*/
if(es_reg_callback(&callback_handler_2, NULL) != 0)
printf("callback fail");
/* TASK 22: notify the client that there is new data available for it */
/* hint 1: use the function <interface_name>_emit
* hint 2: look at https://github.com/seL4/camkes-tool/blob/master/docs/index.md#an-example-of-events
*/
ee_emit();
}
/* this callback handler is meant to be invoked the second time an event
* arrives on the "consumes" event interface.
* Note: the callback handler must be explicitly registered before the
* callback will be invoked.
* Also the registration is one-shot only, if it wants to be invoked
* when a new event arrives then it must re-register itself. Or it can
* also register a different handler.
*/
void callback_handler_2(void *a) {
/* TASK 23: read some data from the dataports. specifically:
* read a dataport pointer from one of the typed dataports, then use
* that pointer to access data in the untyped dataport.
*/
/* hint 1: for the untyped dataport use the "Buf" dataport as defined in the Echo.camkes file
* hint 2: for the typed dataport use the "ptr_buf_t" dataport as defined in the Echo.camkes file
* hint 3: for the definition of "ptr_buf_t" see "str_buf.h".
* hint 4: the "n" field of the typed dataport specifies the number of dataport pointers
* hint 5: the "ptr" field of the typed dataport contains the dataport pointers
* hint 6: use the function "dataport_unwrap_ptr()" to create a regular pointer from a dataport pointer
* hint 7: for more information about dataport pointers see: https://github.com/seL4/camkes-tool/blob/master/docs/index.md
* hint 8: print out the string pointed to by each dataport pointer
*/
dataport_ptr_t dp = d3->ptr[0];
void* vp = dataport_unwrap_ptr(dp);
int n = *(int*)vp;
char* p = (char*)vp + 4;
for(int i = 0; i < n; ++i){
char tmp[10];
strncpy(tmp, p, 10);
p += STR_LEN;
printf("%s ", tmp);
}
printf("\n");
/* TASK 24: register the original callback handler for this event */
/* hint 1: use the function <interface name>_reg_callback()
* hint 2: register the function "callback_handler_1"
* hint 3: pass NULL as the extra argument to the callback
* hint 4: look at https://github.com/seL4/camkes-tool/blob/master/docs/index.md#an-example-of-events
*/
if(es_reg_callback(&callback_handler_1, NULL) != 0)
printf("callback fail");
/* TASK 25: notify the client that we are done reading the data */
/* hint 1: use the function <interface_name>_emit
* hint 2: look at https://github.com/seL4/camkes-tool/blob/master/docs/index.md#an-example-of-events
*/
ee_emit();
}
/* this function is invoked to initialise the echo event interface before it
* becomes active. */
/* TASK 17: replace "echo" with the actual name of the "consumes" event interface */
/* hint 1: use the interface name as defined in Echo.camkes.
* For example if you defined it as "consumes TheEvent c_event" then you would use "c_event".
*/
void es__init(void) {
/* TASK 18: register the first callback handler for this interface */
/* hint 1: use the function <interface name>_reg_callback()
* hint 2: register the function "callback_handler_1"
* hint 3: pass NULL as the extra argument to the callback
* hint 4: look at https://github.com/seL4/camkes-tool/blob/master/docs/index.md#an-example-of-events
*/
if(es_reg_callback(&callback_handler_1, NULL) != 0)
printf("callback fail");
}
CAmkES-3
/*
* CAmkES device driver tutorial.
*/
import <std_connector.camkes>;
/* import the component definitions */
import "components/Client/Client.camkes";
import "components/Timer/Timer.camkes";
/* A valid CAmkES assembly must have at least one component. As the starting point for
* this tutorial does not have any valid components we declare an empty one that does nothing
* just to construct a valid spec. Once you have added some components to the composition
* you can remove this if you want, although it will cause no harm being left in */
component EmptyComponent {
}
assembly {
composition {
component EmptyComponent empty;
/* Part 1, TASK 1: component instances */
/* hint 1: one hardware component and one driver component
* hint 2: look at
* https://github.com/seL4/camkes-tool/blob/master/docs/index.md#creating-an-application
*/
component Timerbase hardware; // 硬件类
component Timer timer; // 驱动类
/* Part 2, TASK 1: component instances */
/* hint 1: a single TimerDTB component
* hint 2: look at
* https://github.com/seL4/camkes-tool/blob/master/docs/index.md#creating-an-application
*/
component TimerDTB timerDTB;
/* this is the component interface. This starts commented out as there it must have
* its 'hello' interface connected, which initially we cannot do. Uncomment this once
* you can uncomment the 'timer interface connection' below */
component Client client;
/* Part 1, TASK 2: connections */
/* hint 1: use seL4HardwareMMIO to connect device memory
* hint 2: use seL4HardwareInterrupt to connect interrupt
* hint 3: look at
* https://github.com/seL4/camkes-tool/blob/master/docs/index.md#creating-an-application
*/
/* Part 2, TASK 2: connections */
/* hint 1: connect the dummy_source and timer interfaces
* hint 2: the dummy_source should be the 'from' end
* hint 3: look at
* https://github.com/seL4/camkes-tool/blob/master/docs/index.md#creating-an-application
*/
/* timer interface connection */
/* uncomment this (and the insantiation of 'client' above) once there is a timer component,
* note that you may need to rename timer in 'to timer.hello' to match the name of the timer
* component above
*/
// connection seL4RPCCall hello_timer(from client.hello, to timer.hello);
}
configuration {
/* Part 1, TASK 3: hardware resources */
/* Timer and Timerbase:
* hint 1: find out the device memory address and IRQ number from the hardware data sheet
* hint 2: look at
* https://github.com/seL4/camkes-tool/blob/master/docs/index.md#hardware-components
*/
/* Part 2, TASK 3: hardware resources */
/* TimerDTB:
* check components/Timer/Timer.camkes
*/
/* assign an initial value to semaphore */
// timer.sem_value = 0;
}
}