1.接口 是一系列声明的函数集合,接口是双向的。接口需要定义一组命令函数,这些函数由接口提供者实现,还可以定义一组“事件”函数,这些函数由接口的使用者实现。
nesC-file:
incliudes-listopt interface
...
interface:
interface identigier {declaration-list}
storage-class-specifier:also one of command event async
2.组件 分模块和配件两类。每个模块实现具有一定功能的子系统,配件负责将各个子系统连接成完整的应用。
nesC-file:
includes-listopt module
includes-listopt configuration
...
module: module identifier specification module-implementation
configuration:
configuration identifier specitication configuration-implementation
3. 模块 是组件的逻辑功能实体,主要包括命令、事件、任务等的具体实现。模块中可以使用和提供多个接口,在接口说明完之后就是模块的执行部分。也就是该模块如何通过调用命令和处理事件实现其功能。
module:
module identifier specification module-implementation
module-implementation:
implementation {translation-unit}
3.1 模块定义的说明
translation-unit 必须实现模块提供接口声明的全部命令和模块使用接口声明的所有事件。
简单命令或事件的实现要满足具有command或event存储类型的C函数标准语法。如果async关键字包含在命令中或事件的声明中,则在它的实现中也要被包含进来。具有接口参数的参数命令或事件的实现语法也要满足具有command或event存储类型的C函数定义的语法,且在C函数定义的普通参数前面具有以方括号括起来的参数前缀。e.g.
command result_t Send.send[unit8_t id](unit16_t address,unit8_t length,TOS_MsgPtr msg)
{
...
return SUCCESS;
}
3.2 命令调用和事件通知
postfix-expression:
postfix-expression [argument-expression-list]
call-kindopt primary (argument-expression-listopt)
...
call-kind:one of call signal post
简单命令a可以使用call a(...)来调用,singal a(...)用来通知一个简单事件 a。
3.3 任务
一个任务是一个返回类型为void且无参数的task存储类型的函数,它是一个可以被调度的逻辑实体,类似于传统操作系统中的进程/线程概念。一个任务可以有一个预先声明,例如:task void myTask()。
提交任务时要使用post前缀,post将任务挂入队列中,并立即返回。任务提交成功后,post返回为1,否则返回0。post表达式的类型是unsigned char,定义如下:
storage-class-specifier:also one of
task
call-kind:also one of
post
4.配件
配件的作用是用过接口把不同的组件连接起来,使之成为逻辑和功能的统一体。编译系统最终根据配件找到各相关组件,编译并生成可执行文件。不论简单还是复杂,配件的基本结构都是一样的。
configuration:
configuration identifier specification configuration-implementation
configuration-implementation
implementation {component-listopt connection-list}
组件列表中列出用来实现此配件的组件列表,定义了这些组件是怎么互相连接以及如何与配件的规范连接在一起的。这里把配件规范中的规范元素称为“外部规范元素”,而把在配件的组件中的规范元素成为"内部规范元素"。
4.1 组件列表
组件列表定义了用来实现配件的组件。这些组件可以在配件中重命名,因而能偶避免与配件规范元素名字的冲突,并简化程序编写。
component-list:
components
component-list components
components:
components component-line;
component-line:
renamed-identifier
component-line,renamed-identifier
renamed-identifier:
identifier
identifier as identifier
当有两个组件使用as导致重名时,会产生一个编译错误。一个组件始终只有一个实例。如果组件K在不同配件中被使用,或者在同一个配件中被使用两次,则程序中也只会有一个组件的实例存在。
4.2 连接
连接用来把定义的元素(接口、命令、事件等)联系在一起,已完成相互之间的电泳。连接的语法定义如下:
connection-list:
connection
connection-list connection
connection:
endpoint=endpoint
endpoint->endpoint
endpoint<-endpoint
endpoint:
identifier-path
identifier-path[argument-expression-list]
identifier-path
identifier
identifier-path.identifier
连接语句连接两个终点,一个终点的identifier-path指明了一个规范元素。可选项argument-expression-list定义了接口参数。如果一个终点的规范元素是参数化的,而且这个终点没有确定的参数值,则这个终点称为“参数化的终点”。
连接语句的类型有三种:
1.endpoint1=endpoint2 这是一个包含一个外部规范元素的连接,这种连接语句可以有效得使两个规范元素等价。设S1是endpoint1的规范元素,S2是endp2的规范元素,则该语句要求满足下列条件:
S1是内部的,S2是外部的(或者相反),而且S1和S2都是被提供或是被使用的;
S1和S2都是外部的,而且一个被提供,一个被使用。
2.endpoint1->endpoint2。这是一个种包含两个内部规范原素的连接。该连接把endpoint1定义的被使用的规范原色连接到endpoint2定义的被提供的规范元素上。
3.endpoint1<-endpoint2。这种连接等价于2