Qualcomm Share Memory

发现baidu文库里有个smem机制总结全的,顺便分享下

QUALCOMMAPMODEM之间的share memory通过把共享内存空间分成N个不定长数据块,其中SMEM_HEAP_INFO记录每个数据块的地址信息,是否已经分配等,(只能一个宿主先分配),当然SMEM_HEAP_INFO本身也是一个数据块。各个宿主CPU用这些数据块依照对应的数据结构通信,包括PROC_COMM, smem_find,以及建立在特定数据块上的循环缓冲区smd通道,还有建立在特定通道的函数调用RPC

(共享内存2个基本点:1在本身内存内记录分配信息  2互斥访问或数据一致性  

       3(可选).如果要快速响应的必须加相互中断通知)

 

地址空间的映射与管理

SMEM_HEAP:(该图版本较老)

typedef enum

{ SMEM_MEM_FIRST,

  SMEM_PROC_COMM = SMEM_MEM_FIRST,

  SMEM_FIRST_FIXED_BUFFER = SMEM_PROC_COMM,

  SMEM_HEAP_INFO,

  ……

} smem_mem_type;1Mshare memory分为N个条目。最终实际固定了每个条目的起始地址和长度。  (详见APlinux kernelsmd.csmem_alloc2分配函数,可知不能通常意义的malloc,只是简单的动态的在尾部增长数据块,不能正真意义的回收内存空间;

总共是1M的共享内存,其中64SMD通道占用64×8K了大部分空间)


struct smem_shared {
    struct smem_proc_comm proc_comm[4];
    unsigned version[32];
    struct smem_heap_info heap_info;
    struct smem_heap_entry heap_toc[SMD_HEAP_SIZE];   // SMD_HEAP_SIZE=512
};//
这个结构对齐到share memory 的起始地址,就是1M共享内存空间的映射。第1个条目为proc_comm.其中包括最重要的条目heap_info.这个条目记录了1M share memory的每个条目的起始地址和长度。

上述结构体包含的struct smem_heap_info记录整个SM空间的alloc情况,当前的申请地址和剩余空间。

上述结构体包含的struct smem_heap_entry 是记录每个条目的地址空间信息,这个一个最多记载512个条目地址信息的数组,经常是依据smem_mem_type条目号来寻找地址信息。

 

 


APMODEM等通信的几种策略机制:

1.在底层数据块层次的使用是PROC_COMM,主要是最低层次处理器间通信,不建议扩展。主要是CPU各路电源,时钟,重启等高优先级的问题。每个处理器只占用4各字节。
代码实现见msm_proc_comm函数。就是写2个字节,发中断给另外的CPU,等待回应。

2.
另外一个机制是smem_allocsmem_get_entrysmem_find。对我们目前来说,主要应用是是MODEM端写一些结构的数据到SHARED MEMORYAP端在合适的时候去取。
这一部分的代码在MODEM分配内存,从AP传递,其中的几个内存管理函数比如smem_alloc是对我们屏蔽的(不能真正意义的回收free)。记住一般是MODEM端从AP传递,反向传递不建议。

3.下面是建立在smem_alloc这个机制上面的SMD。就是循环缓冲区,一端不停的写,另一端不停的读。类似于进程间通信,对上层包装成串口驱动一样的设备。实现机制同样是写数据和中断。读数据回调上层的注册函数。实现代码见smd.c,可不关心,和我们没太多联系。
使用SMD机制通道的接口是串口驱动类似的接口,smd_open,smd_write,smd_read,smd_read_avail.  不清楚可参考smd_nema.c。比如 smd_open("GPSNMEA", &nmea_devp->ch, nmea_devp, nmea_notify);其中 nmea_notify是有数据要读的回调函数。在 nmea_notify里面去看smd_read_avail多少可读,然后smd_read去读。写就直接调smd_write
目前SMD36组通道,一般成对使用。一个MODEMAP,一个APMODEM。目前有GPSDS, DIAG ,BT ,RPC等使用。

SMD循环缓冲区的应用较多,可在kernel中搜索smd_open,有

smd_open("SMD_DIAG", &ctxt->ch, ctxt, smd_diag_notify);

smd_open(p->chname, &p->ch, dev, smd_net_notify);//RMNET

smd_open("GPSNMEA", &nmea_devp->ch, nmea_devp, nmea_notify);

smd_open("SMD_RPCCALL", &smd_channel, NULL, rpcrouter_smdnotify); //smd_rpcrouter.c

smd_open(name, &info->ch, info, smd_tty_notify);   //smd_tty.c 虚拟出TTY设备给应用


4.最后是RPC。这个就是远程函数调用。实现机制是建立在SMD通道之上的一个机制。使用SMD通道2,命名为RPCCALL,通道3 RPCRPY。这个见smd_rpcrouter_device.csmd_rpcrouter.c。主要用法是APP调用MODEM的函数,其中可选项是MODEM端执行完函数后,是否回调APP的一个函数。在RPC中,留了一个OEM_RAPI给我们扩展。具体扩展见qualcomm文档80-VM896-1(附件)。可在KERNEL或应用程序扩展。(应用程序扩展编译时要注意不要包文档里面要求的头文件,否则编译有问题,其他按文档要求就可以)。

RPC:这个的应用最多;

比如AMSS调用kernel上报电池电量在msm_battery.c             msm_rpc_register_client("battery", BATTERY_RPC_PROG,BATTERY_RPC_VER_2_1,

      1, msm_batt_cb_func);注册clinet端函数。对应AMSSservies端。

 

msm_rpc_register_XXX----à Smd_rpcrouter_clients.c&Smd_rpcrouter_servies.c----(通过msm_rpc_write等函数接口)---------à smd_rpcrouter.c--àrpcrouter_smd_xprt.c--àsmd_open

 

另外smd_rpcrouter.c 中的rpcrouter_init ----->msm_rpcrouter_init_devicessmd_rpcrouter_device.c)建立一个class_create(THIS_MODULE, "oncrpc");设备节点。

smd_rpcrouter_device.c实现这个驱动节点的write ;read;poll,ioctl等标准操作。这些操作通过msm_rpc_write等同样调用smd_rpcrouter.c的接口。

应用层的vender/qcom/proprietary/oncrpcliboncrpc.so操作这个驱动节点。(这样在上层直接建议与MODEM的通信,可以不在kernel开源自己的代码)

              Hard/msm7K/librpc的librpc.so操作这个驱动节点。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值