1. CMEM——高速缓存一致性问题的解决
多核设计中,共享的二级高速缓存之间数据可能不一致,不同CPU内核的私有高速缓存也可能存在数据不一致,称为高速缓存的一致性问题。解决一致性问题的方法从整体上分可以分成软件方法和硬件方法两种,各有其优势。Davinci采用软件解决方案。
1) 数据完整性。CE中的CMEM模块是用来做共享内存分配的,因为应用程序是运行在MVista Linux上的,在应用程序里malloc到的buffer都是虚拟地址,实际的物理空间不一定连续,当把这个指针传递给算法的时候,数据完整性问题就出现了,因为算法是运行在DSP/BIOS上的,这是一个只有实地址的世界。为了解决这个问题,在共享缓存动态申请空间的时候,就要调用CMEM API。CMEM驱动模式可以用来在ARM上分配连续的物理缓冲区。
2) CACHE一致性问题。在ARM和DSP内核中都有CACHE用来提高使用外部存储的效率。所有的内核在当它们进行读写的时候,都管理着与它们相关的CAHCE的一致性。但是,当数据经共享内存从一个内核发送到另一个内核时,内核是从不进行CACHE的管理的,因为它们无法互相得知。像虚拟地址问题一样,只要编程者注意到的话这个问题是很容易解决的。当客户端写一个客户端存根函数(stub)来对要发送到服务器端的一个变量或者缓冲区进行CACHE回写时,服务器端就写服务端存根函数(stub)来使得收到的这些变量和缓冲区无效。
2. 模块cmemk.ko介绍
模块cmemk.ko为ARM和DSP通信提供连续的内存,装载的格式为:
insmod cmemk.ko pools=4x30000, 2x500000 phys_start=0x0 phys_end=0x3000000 \
pools_1=4x65536 phys_start_1=0x80000000 phys_end_1=0x80010000
这条命令表明:
(1)在内存0x0~0x2ffffff上开辟了两个内存池,第一个由4个30000字节的缓存组成,第二个由2个500000字节的缓存组成。
(2)在内存0x80000000~0x8000ffff上开辟了一个由4个65536字节缓存组成的内存池。(注:低版本的cmem只支持一块内存)
按照Davinci内存的划分,cmem的内存空间位于linux和DSP使用的内存之间,在dvsdk2.0中cmem内存空间为118~128M(低版本的dvsdk为120~128M,不过低版本的dvsdk的DSP server程序128M之后的很大一块也没有使用,cmem大一点也没事,不过2.0中DSP server程序内存使用从128M开始)
dvsdk2.0中,cmem模块目录为:
[root@localhost cmem]# pwd
/opt/dvsdk_2_00_00_22/linuxutils_2_23_01/packages/ti/sdo/linuxutils/cmem
cmem提供的接口在demo中没有出现,而是被中间件进行了封装。dvsdk1.3中内存的分配使用了CE中OSAL包中Memory模块的 Memory_contigAlloc()函数,dvsdk2.0的demo使用了DMAI模块(在CE基础上进一步进行了封装)。
CMEM是一个连续物理存储空间分配模块,使得ARM端Linux进程和DSP端算法之间能够共享缓冲区。当应用程序需要在共享缓存区动态申请一个连续的物理空间时,通过调用CMEM的API可以实现,申请得到的空间可以供DSP端访问,进行算法处理时数据的传递与处理。
在DVSDK中集成了CMEM模块,CMEM模块安装在Linux服务器下的路径为:/opt/dvevm_1_20/cmem_1_02
在Linux服务器的控制台下,需进行如下操作实现编译:
Host # cd /opt/dvevm_1_20/cmem_1_02/packages/ti/sdo/linuxutils/cmem
Host # make all
Host #make install
运行后,即对cmem模块进行了编译,编译文件为在目录src/module下生成的cmem.ko模块,并将cmem.ko和测试文件安装到了目标板的/opt/nfs/opt/dvsdemos目录下。
DVSDK中的CMEM Demo提供了测试程序:apitest能够测试CMEM的API功能,translate能够测试虚拟地址与实物理地址之间的转换功能。