接上一章:NCS初探--基于nrf5340的双核测试

此次使用NCS自带的samples:entropy_nrf53,这个例子分为两部分,一部分是应用核代码,一部分是网络核代码,两部分代码完全分开,打开工程时,应用核代码选择cpuapp,网络核代码选择cpunet:

此工程在网络核上使用了RNG(随机数发生器,只能在网络核上使用),然后应用核通过RPC(Remote Procedure Call 远程过程调用)去获取网络核上的数据,相当于是一个应用核和网络核数据通信的例子。

基本流程为:

1.建立一个通信组,注意此通信组在应用核和网络核都要建立,且要参数一样。

2.应用核和网络核通过互相向通信组里发送和捕捉命令和事件完成通信。在这个例子里,应用核发送命令ID为1、2、3的命令和事件ID为1的事件给网络核,网络核捕捉到这些命令或事件会发送命令ID为4的命令或事件ID为2的事件给应用核。

两个核之间所要传递的数据就夹杂在命令或者事件里,其中命令和事件的区别是:

命令需要响应,而事件不需要。

基于这些了解,我们看一下代码。本章不涉及底层代码实现原理,只是介绍库的使用方法!

网络核与应用核对应代码

打开网络核main.c会发现里面除了一句打印什么都没有,所有细节都在entropy_ser.c里:

首先在文件最下面有整个初始化的入口,细节不再展开,大致流程为把rpc的初始化函数注册在了某个段内,该段会在OS初始化时,循环加载里面的函数,达到自动初始化的目的,加载时机由POST_KERNEL 指定,在段内顺序由 CONFIG_APPLICATION_INIT_PRIORITY指定。rpc初始化时传入的错误回调函数有两个功能:

1.打印错误码

2.杀死线程

网络核初始化结束,我们看一下应用核初始化代码:

首先是获取网络核初始化状态,整个流程具体代码如下图:

这里比较关键的函数为 int nrf_rpc_cbor_cmd(const struct nrf_rpc_group *group, uint8_t cmd,struct nrf_rpc_cbor_ctx *ctx,nrf_rpc_cbor_handler_t handler, void *handler_data);

它的作用就是向 group 里发送一条命令ID为 cmd 的命令,ctx 为固定的结构体,必须要用 NRF_RPC_CBOR_ALLOC 分配,发送完之后 cmd 的响应处理回调函数为 handlerhandler_data 会传递给 handler ,是 cmd 响应数据的指针。上文中已经提到,命令是需要响应的,而事件不需要。

group 这个上文也说过,应用核和网络核都要注册,且要一样,应用核中有:

网络核中有:

宏原型:

参数依次为:群组名称,字符串名称(唯一),ack回调函数,ack回调数据指针,错误回调函数。

可以看到后三个参数都可以为NULL!

继续回到获取远程初始化状态,使用 nrf_rpc_cbor_cmd 函数向 entropy_group 发送了一条ID为 RPC_COMMAND_ENTROPY_INIT(0x01) 的命令,这个命令ID是我们自己提供,范围在0~254,然后我们用 rsp_error_code_handle 函数去处理命令的响应数据。

而网络核对命令的处理如下:

可以看到关键就在于注册了和应用核里面一样的群组里面的,命令ID为0x01的解码器,并给它提供了回调函数,也就是在群组 entropy_group 里接到 0x01的命令就调用 entropy_init_handler 函数。而且在这里我们看到了怎么把一个 int64 型数据通过响应命令发给应用核,即调用:CborError cbor_encode_int(CborEncoder *encoder, int64_t value),这里 encoder 为ctx.encoder,value 即想要传递的数据。

从这里也可以看出来,两个核之间通信并不是使用的原始数据,而是由发送端编码,接收端解码,所有数据统一使用CBOR编码格式。

应用核解码如下:

这里有一个固定格式,即从Cbor类型的数据里解析数据时,要先判断数据类型,否则用错误的解析方式会引发不可预测的结果,每种数据类型都有它自己的解析方式!

从这里看到如果网络核初始化成功,则会发送错误码为0的响应信息,应用核在得到响应后,把返回的数据先判断是否为int类型,如果类型正确,会把数据存在 handler_data 里,也就是上层函数的 result 里return,最后在main()里判断是否为0。

接下来看应用核怎么获取entropy设备的数据:

传入一个buf长度为10的指针来存从网络核获取到的数据:

和之前不一样的是:

1.我们把要接收的数据长度(10)放进容器内发送给网络核了

2.我们把结构体 result 的指针给响应处理函数了,确保读出来的数据可以返回到上层函数。

与之前一样,网络核要注册命令ID为 0x02 的解码器:

可以看到,这几个命令都用的同一个回调函数,只是在触发回调的时候传入的参数不同,而在回调中通过判断传入的哪个参数去判断是哪个命令触发的回调。

由于应用核在命令中发送给网络核一个buf长度,所以网络核在接收到数据后,先得到这个长度,然后再从设备entropy中获取这么多数据,发送回给应用核:

可以看到在返回给应用核的数据中,我们先填充的是错误码,再填充了10个字节的数据。

在应用核中数据解析为:

上面这种方式是应用核在发送cmd时,提供一个处理函数去处理响应返回的数据,下面则是不提供处理函数,直接处理返回数据:

可以看到和之前调用的发送函数相比,少了两个参数,分别是回调函数和回调函数的入参指针。而解码方式其实一模一样,不过需要注意的是,必须添加 nrf_rpc_cbor_decoding_done(&ctx.value);

就和malloc()和free()一样,这里不添加会出现内存问题。

下面是事件的使用:

在main里有:

可以看到传入参数为buf长度和回调函数,回调函数内容为:

就是简单的打印。继续看事件的发送,如下:

可以看到调用的函数没有处理回调,因为事件就是单向的。

在网络核,我们收到这个事件,所做处理如下:

可以看到,和之前一样把数据放在容器里面,然后调用了事件发送函数,给应用核也发送了一个事件,而在应用核中,有注册这个事件的解码器:

这里callback在应用核第一次发送事件时初始化,其他内容和之前的几个大同小异。

之前两个发送 cmd 的流程都是,应用核发送,网络核响应,最后一个 cmd 发送流程为:应用核发送 cmd ,网络核收到后没有直接响应而是先也给应用核发送一个 cmd 再响应,应用核收到后响应。

首先,main()里:

和上个事件发送差不多,发送函数则和第一个获取远程初始化状态差不多:

可以看到发送了长度数据,然后提供了一个处理回调函数,而在网络核上有:

首先注册了命令解码器,然后在回调里调用 entropy_get_result ,然后用 rsp_error_code_send 去响应。发送数据函数如下:

应用核也注册了cmd解码器,收到信息后也需要响应:

可以看到和之前事件回调是同一个函数,只是多了一个响应。

在函数使用过程中,函数名后缀为_no_err 的,表示此函数没有返回,因为它的返回值会直接发送给错误回调函数,而想要自己处理的,可以使用同名但没有后缀的函数。

关于工程说明可以参考文件夹entropy_nrf53下README.rst,RPC使用说明可以参考nrfxlib/nrf_rpc/doc/usage.rst ,大部分函数注释可以参考文件 nrf_rpc_cbor.h 和 nrf_rpc.h 。

NCS初探--基于nRF5340的双核通信相关推荐

  1. NCS再探--nRF5340 Audio

    1.前情提要 官方文档介绍: nRF5340 Audio - nRF Connect SDK 1.9.99 documentation 截止到本文发布,该应用仅仅是实验性的.LE Audio强制要求支 ...

  2. Davinci DM6446 Codec Engine双核通信环境的搭建

    根据前几篇文章,一个DM6446的系统已经架构完成.但是有很多人都喜欢TI的机制,毕竟双核软件开发对很多工程师来说是非常麻烦的事情,既然TI提供开发套件和开发包,那么直接做OEM就可以了,底层的东西不 ...

  3. OMAP的双核通信机制Codec Engine

    OMAP的双核通信主要是架构在Codec Engine,它是介于应用程序和具体算法之间的软件模块,其中的VISA API通过Stub和Skeleton访问Engine SPI最终调用具体的算法.Cod ...

  4. php 基于socket的基本通信

    php 基于socket的基本通信 1.前言 Socket是应用层与TCP/IP协议族通信的中间软件抽象层,它是一组接口.在设计模式中,Socket其实就是一个门面模式,它把复杂的TCP/IP协议族隐 ...

  5. 怎么用matlab建立双机系统,基于MATLAB的双机通信的实现

    第 卷第 期< 年 月 华 东 交 通 大 学 学 报 」 飞 朗 而 , 文章编号 一 以刀 能 一 以巧 一 基 于 的双机通信 的实现 曹青松 , 周继 惠 , 熊国 良 华东交通大学 机 ...

  6. Linux c 基于内存的进程通信—共享内存、共享队列(消息队列)

    基于内存的进程通信: 1.      内核共享内存 编程模型:     1.1.创建共享内存,得到一个ID  shmget 1.2.把ID影射成虚拟地址(挂载)  shmat 1.3.使用虚拟地址访问 ...

  7. 基于Android和WI-FI通信的智能家居系统

    针对传统智能家居系统存在的操作复杂.可移动性差.升级维护成本高等缺点,本文提出了一种基于Android的智能家居系统的设计和实现方案.采用了具有Android操作系统的智能手机或平板电脑作为家居控制终 ...

  8. 递归锁、信号量、GIL锁、基于多线程的socket通信和进程池线程池

    递归锁.信号量.GIL锁.基于多线程的socket通信和进程池线程池 递归锁 死锁现象:是指两个或两个以上的进程和线程因抢夺计算机资源而产生的一种互相等待的现象 from threading impo ...

  9. recv原理、高阶版黏包解决方案、基于UDP的socket通信

    recv原理.高阶版黏包解决方案.基于UDP的socket通信 recv原理 源码解释: Receive up to buffersize bytes from the socket. 接收来自soc ...

最新文章

  1. 统一异常处理+错误编码设计方案
  2. OPENCV裁剪图片
  3. C#微信公众平台开发—高级群发接口
  4. Visual Studio 2013 Update 2 RTM 发布
  5. union all怎么用在循环里_ai软件怎么使用?ai里基本功能怎么用?
  6. nfs服务器远程访问,NFS远程共享存储
  7. 【Java】浅析Math类
  8. 【AD】如何删除AD20右下角Title
  9. gateway中的局部过滤器_vue 过滤器
  10. 数据库设计规范化的五个要求
  11. 工作流引擎厂商有哪些_国内主要工作流厂商分析
  12. JAVA毕业设计婚纱摄影网设计计算机源码+lw文档+系统+调试部署+数据库
  13. 最新iOS面试题:APP性能优化(①系列更新)
  14. C语言:解决九宫格问题
  15. 爬虫(29)mongodb(下)
  16. 线下活动报名|增长骇客:如何利用数据「玩」出新意
  17. NAB展会BOSMA博冠8K全系8K摄像机产品惊艳亮相
  18. mysql inner join 链接三个或多个表
  19. html制作菱锥旋转,怎样用几何画板实现三棱锥的旋转
  20. Handle的用法实例

热门文章

  1. javabean的含义_javaBean概念
  2. 如何做好图表的色彩搭配?
  3. 【爬虫实践】爬取官方新闻标题、正文、时间
  4. WebDAV之葫芦儿·派盘+网盘精灵
  5. Flutter有局限,拥抱Swift!优酷Mac迁移Swift实践
  6. 从struts2回到struts的学习--DynaActionForm(不用手写actionForm.java)
  7. 创建自定义AlertDialog
  8. 2023 299的怀旧QQ直播视频直播间搭建 附软件和教程
  9. 【BZOJ2054】疯狂的馒头
  10. java计算机毕业设计Vue社区蔬果商城源码+mysql数据库+系统+lw文档+部署