双核处理器中,不管要实现什么功能,ARM
核和DSP
核的通信始终是放在首位的,在嵌入式Linux
中通过DSPLink
来实现ARM
与DSP
通信,DSPLink
在Ubuntu10.04
主机中交叉编译完成后生成dsplinkk.ko
模块,放在嵌入式Linux
文件系统中,在ARM
核中跑起嵌入式Linux
后运行omapl138#insmod
dsplinkk.ko
加载dsplink
驱动模块,运行ARM
端的可执行程序:./readwritegpp readwrite.out 293601280 1024 10000
其中readwritegpp
是ARM
端的可执行程序,readwrite.out
是DSP
端的程序,293601280
是DSP
执行的内存地址,1024
是为程序分配的缓存大小,10000
是执行次数。
首先是ARM
端的程序
#
if defined
(DA8XXGEM
)
- if
( LINKCFG_config.dspConfigs
[processorId]->dspObject->doDspCtrl
- == DSP_BootMode_NoBoot)
{
- /* strDspAddr(c_int00 address)
and .args address are
not required
- *
for noboot mode. ShmBaseAddr
is not provided since
- * DSPLINK_shmBaseAddress
is provided in linker commnad file.
- */
- strShmAddr =
"0x0" ;
- strDspAddr =
"0x0" ;
- strArgsAddr =
"0x0" ;
- RDWR_shmAddr = RDWR_Atoll
(strShmAddr)
;
- RDWR_dspAddr = RDWR_Atoll
(strDspAddr)
;
- RDWR_argsAddr = RDWR_Atoll
(strArgsAddr)
;
- /*
For No bootmode Hard coding the values
- * since DSP side app
is using the same values
- */
- strNumIterations =
"1000";
- numIterations = atoi
(strNumIterations)
;
if ( LINKCFG_config.dspConfigs [processorId]->dspObject->doDspCtrl
== DSP_BootMode_NoBoot)
如上图在DSPLink
的Programers Guide
文档中,DSPLink
启动dsp
的模式有3
种方式,
而DSP_BootMode_NoBoot
是指既不下载DSP
端的程序也不跑DSP
,一般都不会配置成这种模式,如果要修改配置成其他模式则需要在dsplink/BUILD/ CFG_OMAPL138GEM_SHMEM.c
中修改LINKCFG_Dsp这个数据结构,
STATIC LINKCFG_Dsp LINKCFG_dspObject
=
- {
- "DA8XXGEM",
/* NAME
: Name of the DSP */
- DspArch_C64x,
/* ARCHITECTURE
: DSP architecture */
- "COFF",
/* LOADERNAME
: Name of the DSP executable loader
*/
- FALSE,
/* AUTOSTART
: Autostart the DSP
(Not supported)
*/
- "DEFAULT.OUT",
/* EXECUTABLE
: Executable for autostart
*/
- DSP_BootMode_Boot_Pwr,
/* DOPOWERCTRL
: Link does the Power Ctrl of DSP.
*/
- RESETCTRLADDR,
/* RESUMEADDR
: Resume address
*/
- RESETCTRLADDR,
/* RESETVECTOR
: Reset Vector for the DSP
*/
- RESETCTRLSIZE,
/* RESETCODESIZE
:
- …………………….
- } ;
如上,一般启动模式都是
DSP_BootMode_Boot_Pwr:
STATIC LINKCFG_Dsp LINKCFG_dspObject
=
- {
- "DA8XXGEM",
/* NAME
: Name of the DSP */
- DspArch_C64x,
/* ARCHITECTURE
: DSP architecture */
- "COFF",
/* LOADERNAME
: Name of the DSP executable loader
*/
- FALSE,
/* AUTOSTART
: Autostart the DSP
(Not supported)
*/
- "DEFAULT.OUT",
/* EXECUTABLE
: Executable for autostart
*/
- DSP_BootMode_Boot_Pwr,
/* DOPOWERCTRL
: Link does the Power Ctrl of DSP.
*/
- RESETCTRLADDR,
/* RESUMEADDR
: Resume address
*/
- RESETCTRLADDR,
/* RESETVECTOR
: Reset Vector for the DSP
*/
- RESETCTRLSIZE,
/* RESETCODESIZE
:
- …………………….
- } ;
接下来是主函数
RDWR_Main ( dspExecutable,
strDspAddress,
dspAddress,
strBufferSize,
bufferSize,
strNumIterations,
numIterations,
processorId) ; }
简要的,主函数主要有三个模块,
status = RDWR_Create (dspExecutable,
strBufferSize,
strNumIterations,
processorId) ;
status = RDWR_Execute (dspAddress,
bufferSize,
numIterations,
processorId) ;
RDWR_Delete (processorId) ;
即创建,运行,删除。
创建函数RDWR_Create
主要是用PROC
模块初始化加载dsp
端程序,用POOL
模块映射ARM
与DSP
的内存空间,初始化消息机制MSGQ
。主要内容如下:
status = PROC_setup (NULL) ;
status = PROC_attach (processorId, NULL) ;
status = POOL_open (POOL_makePoolId(processorId, SAMPLE_POOL_ID),
&SamplePoolAttrs) ;
status = MSGQ_open (SampleGppMsgqName, &SampleGppMsgq, NULL) ;
status =
PROC_load (processorId, dspExecutable, NUM_ARGS, args) ;
status = PROC_start (processorId) ;
status = MSGQ_transportOpen (processorId, &mqtAttrs) ;
status = MSGQ_locate (SampleDspMsgqName,
&SampleDspMsgq,
&syncLocateAttrs) ;
PROC_load()加载dsp
的程序,POOL_open()如下图,用于配置共享内存,使ARM
与DSP
端内存空间映射一致
且POOL_open()函数是消息机制MSGQ函数调用前的必经步骤,
然后调用MSGQ_open
(),MSGQ_transportOpen
(),MSGQ_locate
()等初始化一个消息队列,然后调用MSGQ_alloc
()在现有的pool
内存池里面分配出一个samplemessage
结构体,写入需要传送的消息数据,这里从内存区分配地址,可以保证samplemessage
使用的是dsp
和gpp
共享内存区的地址,之后调用MSGQ_put
函数把这个消息放到消息队列。