eRPC是一个开源的适用于多核嵌入式系统的远程过程调用框架,它专门为紧密耦合的系统设计,使用纯C语言实现远程功能,并且代码量小(<5KB)。本文从ePRC的上手使用开始,然后对其框架原理、开销和性能进行简单分析。
快速开始eRPC由NXP创建,提供了一种简单的通过本地函数调用远程系统上的软件方法的机制。
其特点是:
一种创建client/server应用的简单方法
跨平台的erpcgen工具生成填充代码
简单的传输层设计,它甚至提供了同样是NXP开发的rpmsg-lite的IPC传输层
Server可以是阻塞或非阻塞的
快速使用:
编写IDL文件
生成填充代码
导入eRPC公共文件和接口文件
添加传输层驱动
编写应用程序
IDL文件编写创建的idl文件 idl_example.erpc
12345@output_dir("idl_example_source")@types_header("idl_example_common.h")program idl_exampleimport "idl_test.erpc"
program
可选的program语句用于指定整个输入的名称。该名称用于输出文件名,最终的文件名为program_group_xxx。
import
通过import关键字,包含另一个IDL文件。
注解
注解以”@”字符开头,参数以”()”写入。注解提供了一种方法,用以通知eRPC生成器有关代码部分的特定请求。
@output(string):表示生成文件将输出到string指定的目录
@types_header(string):表示所有的声明(如typedef和struct)将会被移至指定的头文件中。这样可以避免重复定义的错误
创建具体的接口定义文件 idl_test.erpc
1234567const int32 matrix_size = 5type Matrix = int32[maxtrix_size][matrix_size];enum enumPrintType { BUILT_IN_TYPES, STRUCT_TYPE, ARRAY_TYPE,}
内置类型
IDL
C
IDL
C
bool
bool
uint8
uint8_t
int8
int8_t
uint16
uint16_t
int16
int16_t
uint32
uint32_t
int32
int32_t
uint64
uint64_t
int64
int64_t
float
float
string
char*
double
double
数组
IDL
C
int32[10] variable
int32_t variable[10];
int32[10] [6] variable
int32_t variable[10] [6];
别名
type _aliasName = _originalType
常量
使用const关键字定义常量
枚举
IDL的enum定义会生成对应的C枚举类型,区别在于输出的C枚举类型中会增加匹配名称的typedef
12345678910111213141516struct erpc_data_t { int32_t val; byref float b;}struct foo { int32 discriminator; union(discriminator) { case BUILT_IN_TYPES: int32 num case STRUCT_TYPE: erpc_data_t data case ARRAY_TYPE: Matrix m } value}
结构体
IDL文件定义的结构体,输出文件中会额外添加typedef别名。当结构体的成员声明前使用”byref”关键字时,结构的成员将通过引用序列化。
联合体
封装型的联合体:联合体是结构体的一部分,需要结构体的其他成员作为联合体的鉴定符。
非封装的联合体:如果把联合体定义在全局空间,则需要使用@discriminator(string)指定鉴别符。
鉴定符,也就是说要指定union具体是那种类型
1234struct A { int32 discriminator; unionType data @discriminator(discriminator);}
123456789@group("test")@include("idl_example_common.h")@idl(2)interface PrintService { oneway erpc_print(in int32 index); test_binary_allDirectionLength(binary a @length(p1), in binary b, inout binary d, in uint32 p1) -> void; test_list_allDirectionLength(list
@group(string)
接口可以通过group注解来进行组织,该名字会体现在输出文件中
@include(string)
string是将要包含的头文件名
@id(number)
设置interface/方法的ID号,该ID号必须唯一
Interface
接口包含一个或多个函数,这个函数在客户端使用,在服务端实现
oneway
表明该函数是单向函数
in/out/inout
指定参数的方向
@length
指定变量的长度
@retain
阻止server释放变量的空间
eRPC框架类图
程序流程图
资源消耗eRPC基础框架的代码空间约为3~4KB
FileName
Code
RO Data
RW Data
erpc_basic_codec.o
624
192
0
erpc_client_manager.o
414
40
0
erpc_crc16.o
8
0
0
erpc_message_buffer.o
158
0
0
erpc_server.o
122
0
0
erpc_simple_server.o
514
44
0
erpc_port_freertos.o
30
0
0
erpc_client_setup.o
242
24
24
erpc_server_setup.o
162
0
24
erpc_setup_mbf_dynamic.o
76
32
8
需要指出的是,eRPC的框架代码虽然体积不大,但是生成的shim code体积还是比较大的。
序列化字节流分析
Client->Serverd0 00 5e 79 00 01 01 01 01 00 00 00 01 00 00 00 01 00 00 00 01 00 00 00 01 00 00 00 01 00 00 00 01 00 00 00 01 00 00 00 01 00 00 00 01 00 00 00 01 00 00 00 01 00 00 00 01 00 00 00 01 00 00 00 01 00 00 00 01 00 00 00 01 00 00 00 01 00 00 00 01 00 00 00 01 00 00 00 01 00 00 00 01 00 00 00 01 00 00 00 01 00 00 00 01 00 00 00 01 00 00 00 01 00 00 00 01 00 00 00 01 00 00 00 01 00 00 00 01 00 00 00 01 00 00 00 01 00 00 00 01 00 00 00 01 00 00 00 01 00 00 00 01 00 00 00 01 00 00 00 01 00 00 00 01 00 00 00 01 00 00 00 01 00 00 00 01 00 00 00 01 00 00 00 01 00 00 00 01 00 00 00 01 00 00 00 01 00 00 00 01 00 00 00 01 00 00 00 01 00 00 00d0 00 5e 79:h.m_messageSize = 0x00d0, h.m_crc = 0x795e00 01 01 01:header = 0x01010100,其中kBasicCodecVersion = 0x01, service = 0x01, request = 0x01, messageType = kInvocationMessage01 00 00 00:sequence = 0x00000001后续的200个字节是2个554(row*col*element_size)的matrix实参。