OMAP-L138 双核通信实例 Example01
使用的开发板:广州创龙公司的 TL138_1808_6748-EVM
run.sh
###########################################################
#!/bin
set -x
./slaveloader startup DSP server_dsp.xe674
./app_host DSP
./slaveloader shutdown DSP
###########################################################
运行结果:
ARM 端程序:
1)main():
在主函数中,首先检查参数的有效性,然后调用 Main_main()函数
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
解析命令行:
status = Main_parseArgs(argc, argv);
=============================================================
Int Main_parseArgs(Int argc, Char *argv[])
=============================================================
(1)
终止 SysLink:
SysLink_destroy();
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2)Main_main()
初始化 SysLink:
SysLink_setup();
调用 SysLink 的装载回调信号:
remoteProcId = MultiProc_getId(Main_remoteProcName);//获取 DSP 端处理器的 ID
static String Main_remoteProcName = “DSP”;
status=Ipc_control(remoteProcId,Ipc_CONTROLCMD_LOADCALLBACK,NULL);
调用 SysLink 的开始回调函数
status=Ipc_control(remoteProcId,Ipc_CONTROLCMD_STARTCALLBACK,NULL);
应用程序执行阶段
status = App_exec(remoteProcId);
=======================================================================
Int App_exec(UInt16 remoteProcId)
=======================================================================
3)App_exec()
首先是创建一个信号量对象:
Module_semH = OsalSemaphore_create(OsalSemaphore_Type_Counting);
static OsalSemaphore_Handle Module_semH = NULL;//全局对象
注册通知回调函数
status = Notify_registerEventSingle(remoteProcId,
SystemCfg_LineId, SystemCfg_EventId, App_notifyCB, (UArg)NULL);
App_notifyCB: 回调函数名
(UArg)NULL: 回调函数的参数,这里没有指定参数
等待通知事件,使用的是信号量机制。当没有通知事件时,函数自旋等待。
OsalSemaphore_pend(Module_semH, OSALSEMAPHORE_WAIT_FOREVER);
#define OSALSEMAPHORE_WAIT_FOREVER
此参数表示不会发生超时等待。
(~((UInt32) 0u))
注销通知回调函数
status = Notify_unregisterEventSingle(remoteProcId,
SystemCfg_LineId, SystemCfg_EventId);
删除同步对象
OsalSemaphore_delete(&Module_semH);
4)App_notifyCB()
当 ARM 端接收到来自 DSP 端的通知事件时,将会调用回调函数,在回调函数里可以执行自
己想要之行的程序。
释放信号量,表明已经收到了信号:
OsalSemaphore_post(Module_semH);
当回调函数一旦释放信号量的时候,等待信号量的函数将不会自旋。
DSP 端程序
1)main()
在主函数中,首先定义错误块标志,多任务参数。
Error_Block
Task_Params
eb;
taskParams;
在使用错误块之前必须要初始化:
Error_init(&eb);
创建主线程,在 BIOS 中的 main()函数中不能使能中断
初始化任务参数:
Task_Params_init(&taskParams);
taskParams.instance->name = "smain";//任务实例名
taskParams.arg0 = (UArg)argc;
taskParams.arg1 = (UArg)argv;
taskParams.stackSize = 0x1000;
//任务使用的参数 argc
//任务使用的参数 argv
//任务使用的堆栈大小
启动任务,任务的函数名是 smain():
Task_create(smain, &taskParams, &eb);
启动任务调度:
BIOS_start();
2)smain()
该函数执行的线程是主要执行的程序。
初始化服务模块:
Server_init();
启动 IPC,该函数只能被一个线程调用
status = Ipc_start();
与远程处理器(ARM)进行关联,返回远程处理器 ID:
remoteProcId = MultiProc_getId("HOST");
连接远程处理器,这将会使 Ipc_control()函数返回,不再阻塞:
status = Ipc_attach(remoteProcId);
程序执行服务:
status = Server_run(remoteProcId);
结束程序服务:
断开与远程处理的连接:
status = Ipc_detach(remoteProcId);
停止 IPC,只允许一个线程调用:
Ipc_stop();
终止服务模块:
Server_exit();
3)Server_init()
在该函数里,首先会判断模块是否初始化完成,然后与 xdc.runtime 注册获得一个诊断掩码。
if (Module_curInit++ != 0) {
//返回表示还在初始中
return;
}
result = Registry_addModule(&Registry_CURDESC, MODULE_NAME);//注册模块
判断模块是否注册成功:
Assert_isTrue(result == Registry_SUCCESS, (Assert_Id)NULL);
4)Server_run()
在该函数中,首先会等待,直到远程处理器已经注册了通知回调信号(通过调用 Ipc_control())。
发送事件通知,并等待时间是否发送成功:
status = Notify_sendEvent(remoteProcId, SystemCfg_LineId,
SystemCfg_EventId, 0, TRUE);
payload 为该函数的第三个参数,这里为 0,也可以发送其他的参数,需要在远程处理器中对
不同的参数使用不同的处理。
至此一个简单的 Helloworld 双核程序就结束了,这里使用的处理非常的简单,毕竟是第一个
双核程序,主要是理清思路,为后续编程打下基础。
由于时间紧促,水平有限,出现错误在所难免,还请大家多多批评指正。如果对
双核开发也感兴趣,可以关注我的新浪微博,还可以给我发邮件。
邮箱:lishangfeng@stu.xidian.edu.cn
新浪微博:尚贤博学