- 1. 什么是 Remote Service
- 2. 代码库中 Remote Service 的实现在哪里?
- 3. 执行过程 —— Linux Remote Service
- 4. 执行过程 —— Sysbios Remote Service
- 5. 两种系统的remote service实现有什么不同
1. 什么是 Remote Service
Remote Service 是 PSDK 中 VisionApps 层实现的一套 远程调用模型,允许用户通过简易的 API 实现通过 IPC 调用远程核心上的函数或服务。这些函数或服务是控制类而不是执行实时算法。
Remote Service 服务命令在单个线程中执行,因此对同一个 CPU(包含异构芯片和MPU) 的多个请求将被序列化。一旦 Remote Service 的一个服务命令开始执行,就会运行到完成状态,然后才会转移到另一个服务命令。
Remote Service 的 API 的重点是简单性,而不是低延迟和效率。开发者想获得最佳通信性能,应该调用 IPC 本身。 IPC 本身的介绍在本栏其他专题中。
2. 代码库中 Remote Service 的实现在哪里?
基于vision_apps中的remote_service工程 vision_apps/utils/remote_service
每个源码文件的功能
| COMMON | app_remote_service_test.c | 关于测试程序的回调注册 |
| SYSBIOS\FREERTOS\QNX | app_remote_service.c | 依赖相关系统的API的实现。这里包含的芯片有 C6x,C7x |
| LINUX | app_remote_service_linux.c | 依赖Linux IPC实现,支持MPU,MCU,DSP的远程通信。这里包含的芯片有A72,X86,X86_64 |
这里重点总结 Linux + sysbios 的 Remote Service 的实现逻辑。
3. 执行过程 —— Linux Remote Service
3.1. 底层关键实现 —— RPMSG CHAR
此部分具体说明间 psdk_rtos/docs/user_guide/developer_notes_ipc.html
RPMSG 是顶层 API 实现,具体工作依赖 IPC 驱动程序和 VRING。
VRING 是一段芯片间的共享内存,用于保存 Message 。
Hardware - Mailbox 主要提供基于硬件中断 (interrupt) 的事件。本质上是持有 VRING ID 的很小的 HW 队列。
RPMSG CHAR 是 RPMSG 在用户空间的 API。提供一个文件 IO 接口 (/dev/rpmsgX) 用于读写 Message 。提供如 Select 的操作 Wait 接口,提供 RPMSG_char_helper 等简化接口。
参考API ti_rpmsg_char.h
3.2. 调用RPMSG CHAR —— Remote Service
RX==receive,接收,从开启到现在接收封包的情况,是下行流量。 TX==Transmit,发送,从开启到现在发送封包的情况,是上行流量。
- appRemoteServiceInit
- init pthread mutex and lock
- create tx. rpmsg_char_open wiht rpmsg_cpu_id,get file discriptor and local end point addr
- appRemoteServiceRegister
- save app_remote_service_handler_t with service_name at app_remote_service_obj_t
- appRemoteServiceRun
- copy content from input buffer to app_remote_service_obj_t→rpmsg_tx_msg_buf
- write app_remote_service_obj_t→rpmsg_tx_msg_buf to file discriptor , self cpu → dst cpu
- if APP_REMOTE_SERVICE_FLAG_NO_WAIT_ACK, return. else next.
- wait and read message form file discriptor to app_remote_service_obj_t→rpmsg_tx_msg_buf. dst cpu → self cpu
- write app_remote_service_obj_t→rpmsg_tx_msg_buf to input buffer
- appRemoteServiceUnRegister
- remove app_remote_service_handler_t with service_name from app_remote_service_obj_t
- appRemoteServiceDeInit
- delete pthread mutex and lock
- rpmsg_char_close with rpmsg handler
4. 执行过程 —— Sysbios Remote Service
编译依赖 CORE=c7x_1 相关编译文件 pdk_jacinto_08_00_00_37/packages/ti/osal/src/src_common_nonos.mk
VisionApps 的 Sysbios Remote Service 实现有一个迷惑行为。在同一的 IPC 接口下实现一套 Sysbios ( c7x , c6x 等设备上运行的版本 ) 的版本 ( 具体见 vision_apps/utils/ipc/src/app_ipc_rtos.c ),同时在 Remote Service 接口下实现 Sysbios 版本时并未引用前者的 IPC 实现转而直接调用底层设备的 IPC 实现( 具体见 pdk_jacinto_08_00_00_37/packages/ti/drv/ipc )。故,这里主要描述调用逻辑。
4.1. 调用设备IPC的过程
Task 是rtos的线程模型。 Semaphore 是rtos的信号量模型
- appRemoteServiceInit
- init semaphore
- create tx and rx ipc.
- create rx task
- start thread → loop
- recv rx message
- call app_remote_service_handler_t
- register perf task
- start thread → loop
- init test and printf
- appRemoteServiceCreateRpmsgRxTask
- save app_remote_service_handler_t with service_name at app_remote_service_obj_t
- appRemoteServiceRun
- copy content from input buffer to app_remote_service_obj_t→rpmsg_tx_msg_buf
- ipc send app_remote_service_obj_t→rpmsg_tx_msg_buf to tx
- if APP_REMOTE_SERVICE_FLAG_NO_WAIT_ACK, return. else next.
- ipc recv and write app_remote_service_obj_t→rpmsg_tx_msg_buf
- appRemoteServiceUnRegister
- remove app_remote_service_handler_t with service_name from app_remote_service_obj_t
- appRemoteServiceDeInit
- deinit test
- stop and delete task
- delete tx rx ipc
- delete semaphore
5. 两种系统的remote service实现有什么不同
目前看来,sysbios实现在不开启APP_REMOTE_SERVICE_FLAG_NO_WAIT_ACK情况下可做到异步调用,而linux实现完全是同步的。
有待实际验证。