答:简单回答下问题。
1. 这个在bf609_ezkit的软件包中就有一些MCAPI例程。mpeg4_enc软件包中也有相关的应用(双核编码,每一个核编码一半的图像数据),这个例程使用MCAPI来进行核间通信,看起来更标准化,单初学者会感到很复杂。
2. 你应该看下bf609的芯片手册,有中文版的。主要关注内存地址的映射。至于速度就自己测了。
3. 简单的就是信号量了,全局变量。
总结下3个问题:
bf609的内存可以分为三部分:L1 L2 L3。
其中L1对于两个核心来说是独立的, 两个核心有自己的L1。coreA的L1,coreB是无法访问到的。
而L2和L3就是共享的。两个核都可以访问的到。
为了防止访问冲突。cces在创建工程的时候就会自动的生成两个和内存相关的文件。
startup_ldf目录下的app_cplbtab.c和app.ldf文件。
这两个文件对内存进行了划分。两个和的project目录下都有对应的文件。
其中app_cplbtab.c负责管理当前内核可以访问的内存区域。以及对应内存区域的访问方式。
比如core0中一段描述:
{0x00000000, (ENUM_DCPLB_DATA_16MB | CACHE_MEM_MODE)},
{0x01000000, (ENUM_DCPLB_DATA_16MB | CPLB_DNOCACHE)},
{0x02000000, (ENUM_DCPLB_DATA_16MB | CACHE_MEM_MODE)},
{0x03000000, (ENUM_DCPLB_DATA_16MB | CACHE_MEM_MODE)},
{0x04000000, (ENUM_DCPLB_DATA_16MB | CACHE_MEM_MODE)},
{0x05000000, (ENUM_DCPLB_DATA_16MB | CPLB_DNOCACHE)},
{0x06000000, (ENUM_DCPLB_DATA_16MB | CPLB_READONLY_ACCESS)},
{0x07000000, (ENUM_DCPLB_DATA_16MB | CPLB_READONLY_ACCESS)},
这一共是128MB的内存空间。
CACHE_MEM_MODE 开CACHE
CPLB_DNOCACHE 关cache
CPLB_READONLY_ACCESS 只对的。
前两个就不说了,第三个表明,该区域的内存对于core0来说是只读的,不可写。如果写的话就会产生错误。
一个cplb错误。debug时候控制台就会是红字提示。(不过貌似DMA可以随意访问到)。
如果我们将{0x05000000, (ENUM_DCPLB_DATA_16MB | CPLB_DNOCACHE)},删除的话,
那么这段空间对于当前内核来说,就是不可见的。如果通过绝对地址来访问的话,也会产生cplb错误。
比如 char *p = 0x05000000; *p = 1; 这样的代码在执行的时候就会出错。因为该地址对于当前内核来说是不可见的。(DMA除外)
而char *p = 0x01000000; *p = 1; 这样的代码执行起来没有大的问题。
这应该是Blackfin DSP的内存保护机制。不过类似这样通过绝对地址访问的代码通常是很危险的。
你要保证你访问的内存地址是安全的,不会被系统用到。
再去看看ldf文件。我自己对ldf的文件了解的不是很多。只是会用而已。从使用的观点来描述。
ldf文件描述了具体内存空间的分布。
比如ldf文件开头定义了这些段:
MEM_SDRAM_BANK0 { TYPE(RAM) START(0x00000004) END(0x00ffffff) WIDTH(8) }
MEM_SDRAM_BANK1 { TYPE(RAM) START(0x01000000) END(0x01ffffff) WIDTH(8) }
MEM_SDRAM_BANK2 { TYPE(RAM) START(0x02000000) END(0x02ffffff) WIDTH(8) }
MEM_SDRAM_BANK3 { TYPE(RAM) START(0x03000000) END(0x03ffffff) WIDTH(8) }
这些是64MB的内存空间。表明当前coreA中的一些数据和代码都放在了DDR2的前64MB内存中。
后面会有对这些内存空间的具体定义。比如代码段,数据段,堆栈等。
有了这些定义,就可以保证,工具链在连接生成可执行程序时,不会访问到其他的内存空间。
L1和L2类似。
你去看下coreB project中的cplbtab.c和app.ldf文件。会发现有同样的内存定义。只是内存的地址和参数是不一样的。
既然懒的看英文文档,那就要通过多试验多对比来发现他们的原理。
默认情况下新生成的project。L2和L3是这么定义的。
L2分为三部分。ICC两个核心都可见,是共享区域,内存地址是一样的(这是MCAPI用于通信的)。 另外两个区域coreA和coreB各占一个,内存地址是不一样的。
L3就分为两部分。 coreA占用前一半,coreB占用后一半。
上述就是内存布局的一个简单的描述。
知道了内存的布局,结合自己以前学习的进程间通信的方式。就不难想出使用共享内存的方法。
把coreA和coreB看做两个独立的程序。两个程序都有自己的main函数。那两个程序如何通信呢?
如果带有操作系统的话,可以使用共享内存,共享内存的地址就是一个文件描述符。 对于Blackfin这种没有MMU的芯片
来说就很简单了,直接通过绝对地址就OK了。那共享内存怎么创建的呢? 前面不是说过对于两个核来说 L2和L3都是共享的吗?
对边在L2和L3开辟一段空间就行了。共享的地址,你知,coreA知,coreB也知。
这里完全抛开MCAPI的方式来实现共享内存。(MCAPI没用过,一直懒的去看)
我们定义两个共享内存,分别放在L2和L3中。一个作为双核通信用到的变量标记,一个作为大的缓冲区。
L2的速度要比L3快,因为L2的共享内存用于核间通信时的信号量。 L3就是缓冲区了。
L2的共享内存就用现成的。
MEM_L2_SRAM_ICC { TYPE(RAM) START(0xC8080000) END(0xC808041F) WIDTH(8) }
这个段的定义,在两个核中是完全一模一样的。
L3的共享内存需要修改各自的cplb和ldf文件。我们把整个DDR2最后8MB空间作为共享内存。
coreA的cplbtab.c这么改: 这样的话coreA就可以访问该内存空间了。
{0x07000000, (ENUM_DCPLB_DATA_16MB | CPLB_READONLY_ACCESS)}, --》{0x07000000, (ENUM_DCPLB_DATA_16MB | CACHE_MEM_MODE)},
coreA的ldf:
不改。