heap = (IHeap_Handle)SharedRegion_getHeap(regionId); // 通过区域ID获得共享区域的堆句柄
buf = Memory_alloc(heap, size, align, NULL); // 通过堆分配区域内存
参数分析:
1)regionId: 是区域ID,在静态添加中.cfg文件中通过SharedRegion.setEntryMeta中设置的,如果不知道,可以通过SharedRegion_getId()根据特定的地址来获得当前区域Id,或者通过SharedRegion_getIdByName()根据区域的名称来获得区域Id。
2)buf: 分配的内存缓冲区指针,
3)heap: 可用于分配内存的堆句柄
4)size: 分配的内存缓冲区大小
5)align: 对齐参数
添加相应头文件:
主任务函数中添加:
(3)地址转换:在一个拥有共享内存区域的环境中,一个主要的问题是这些共享区域在不同处理器上可能会被映射到不同地址空间,即同样一块共享内存区域在不同处理的本地地址空间的逻辑位置是不同,因此此时就需要在不同处理器之间转换的地址指针。先前在静态设置中将SharedRegion.translate选项设置为true,则需要做地址转换。而设置为false时,不同处理器上同一样的内存缓冲区其对应地址都是相同,所以不需要做地址转换。这里为了描述共享内存间的地址转换过程,我们将其设置为true(默认)。
首先需要介绍两个概念:
共享区域地址SRPtr:共享区域地址是当前内存缓冲区在共享区域SharedRegion上的地址,可以视为全局地址,指向同一内存的SRPtr地址在所有处理器上都是相同,所以我们给其他核传递的就是这个地址。共享区域指针(SRPtr)是一个32位指针,其由一个ID和其偏移组成。一个SRPtr的最重要的位是用于表明ID号的,而ID号表明当前区域入口在查找表中的位置。
本地地址addr:共享区域地址SRPtr是不能在本地使用,一般情况下,需要转换成本地地址才能被本地处理器使用。
关于地址转换的几个函数:
SharedRegion_getPtr()根据共享区域指针来获得本地指针
SharedRegion_getSRPtr()根据给定的本地指针及区域ID来获得当前共享区域指针
主核将共享区域地址指针通过MessageQ传递给了从核,然后在从核上进行相应的地址转换,得到本地地址
(4)缓存Cache问题
主核在往内存写数据时,很有可能只是将数据写Cache中,还没有写入到内存中去,所以这个时候,从核肯定不能从内存中读到写入数据。这个问题非常重要,困扰我一两天了=_=||,解决方法是将回写Cache。具体步骤:
a). 导入头文件
#include<ti/sysbios/hal/Cache.h>
b). 给内存写入数据后,回写Cache
Void Cache_wb(Ptr blockPtr, SizeT byteCnt, Bits16 type,
Bool wait);
blockPrt是指内存地址,byteCnt指回写数据大小,type指缓存类型,wait指是否等待。回写全部Cache可以调用Void Cache_wbAll();
c). 在从内存读出数据前,先让Cache失效
Void Cache_disable(Bits16 type);
type指缓存类型,这里可以选择Cache_Type_ALL,即全部缓存
三、Notify模块
上一节我们介绍了Notify模块,这一节就不详细说了,本节的Notify模块主要有以下几个要点
(1)首先要保证各核之间存在连接,因为8个核都要连接,所以可以直接设为
(2)虽然只有主核向从核发送消息,但主核和从核之间都要注册事件
(3)设置注册函数,主要完成地址传递,另外这里需要设置一个信号量(信号量的设置第5节有),从核只有地址传递后才能激活信号量,开始读取内存数据
(4)主核给从核发送可以读取数据事件
(5)主核一直等信号量激活
四、例程结果分析
通过上面结果,可以看出核1-7完美读取了核0写入共享内存的数据。
需要注意的是有些情况下,即使在需要地址转换的情况下,各处理器的本地地址也有可能是相同的,就像本节的例子,但是当共享内存区域的数据成份比较复杂时,同一区域在不同处理器的本地地址就很可能不同了,所以地址转换是非常有必要的。