MessageQ模块:主核(核0)在将图像文件输入共享内存后,需要将输入图像缓存和输出图像缓存的地址打包成消息,传递给从核。总之,MessageQ是用来传递少量信息的,一般是地址,标志位之类的参数,不是传递大规模数组用的。对于大规模的数组,可以利用messageQ传递其首地址。
MessageQ模块的主要特点:
1. 实现了处理期间变长消息的传递,所需要传递的消息一般超过32bit;
2. 其消息的传递都是通过操作消息队列来实现的;
3. 每个消息队列可以有多个写者,但只能有一个读者,而每个任务(task)可以对多个消息队列进行读写;
4. 一个宿主在准备接收消息时,必须先创建消息队列,而在发送消息前,需要打开预定的接收消息队列;
很关键的一点就是 谁接收,谁创建( messageQ_create() )
谁发送,谁打开( messageQ_open() )
MessageQ的使用过程:
一、cfg文件的配置
var MessageQ = xdc.useModule('ti.sdo.ipc.MessageQ');
var Ipc = xdc.useModule('ti.sdo.ipc.Ipc');
var HeapBufMP = xdc.useModule('ti.sdo.ipc.heaps.HeapBufMP');
var MultiProc = xdc.useModule('ti.sdo.utils.MultiProc');
/* BIOS/XDC modules */
var BIOS = xdc.useModule(‘ti.sysbios.BIOS’);
BIOS.heapSize = 0x8000;
BIOS.heapSection = “systemHeap”;
二、heapBufMP的创建
heapBufMP的创建在主核完成(应该也可以在从核创建)
HeapBufMP_Handle heapHandle; HeapBufMP_Params heapBufParams;
/*Create the heap that will be used to allocate messages. */ HeapBufMP_Params_init(&heapBufParams); heapBufParams.regionId = 0; heapBufParams.name = HEAP_NAME; heapBufParams.numBlocks = 16; heapBufParams.align = 128; //对齐方式 heapBufParams.blockSize = sizeof(MessageQ_MsgHeader); heapHandle = HeapBufMP_create(&heapBufParams); if (heapHandle == NULL) { System_abort("HeapBufMP_create failed\n" ); } do { status = HeapBufMP_open(HEAP_NAME, &heapHandle); if (status < 0) { Task_sleep(1); } } while (status < 0);
三、messageQ的创建
谁接收,谁创建的原则。如果是主核通知从核,那么需要在从核函数中进行创建。
//从核 MessageQ_Msg msg; MessageQ_Handle messageQ; MessageQ_QueueId remoteQueueId; Int status; HeapBufMP_Handle heapHandle; /* Register this heap with MessageQ */ MessageQ_registerHeap((IHeap_Handle)heapHandle, HEAPID);
/* Create the local message queue */ messageQ = MessageQ_create(localQueueName, NULL); if (messageQ == NULL) { System_abort("MessageQ_create failed\n" ); }
四、messageQ打开
谁发送,谁打开。主核要通知从核一些事情,那么在从核创建了messageQ之后,主核来打开这个messageQ。打开之后分配空间。
status = MessageQ_open(slaveQueueName[i], &remoteQueueId[i]);
//给头部分配空间
msg[i] = MessageQ_alloc(HEAPID, sizeof(MessageQ_MsgHeader));
if (msg[i] == NULL)
{
System_abort("MessageQ_alloc failed\n" );
}
五、messageQ发送
主核在打开之后,完成数据的发送。这里的remoteQueueId是上一步MessageQ_open的输出
/****************************************************************/ /* broadcast messages to core 0 - core number_of_cores-1 */ /****************************************************************/ void BroadcastMessages( MessageQ_QueueId *remoteQueueId, MessageQ_Msg *msg, const UInt16 msgId, const UInt16 number_of_cores ) { Int status; Int i;
/* Send messages to process the cores */ for(i = 0;i < number_of_cores;i++) { //设置msg中的msgId MessageQ_setMsgId(msg[i], msgId); /* 发送messageQ 从核创建的messageQ */ status = MessageQ_put(remoteQueueId[i], msg[i]); if (status < 0) { System_abort("MessageQ_put had a failure/error\n"); } }
}
六、messageQ接收
对于messageQ接收来说,从核需要接收数据,因此在从核完成接收过程。接收完毕之后进行从核内部自己的处理
status = MessageQ_get(messageQ, &msg, MessageQ_FOREVER); if (status < 0) { System_abort("This should not happen since timeout is forever\n"); }
//判断收到的msg的ID是否等于1 if(MessageQ_getMsgId(msg) == 1) { mc_process(); }
总结一下:
主核如果给从核发送messageQ,步骤如下
1 主核创建heapBufMP
2 从核创建messageQ messageQ_create()
3 主核打开messageQ messageQ_open()
4 主核分配空间 messageQ_alloc()
5 主核发送messageQ messageQ_put()
6 从核接收messageQ messageQ_get()
7 从核处理函数
整体流程结束。下一篇介绍一个具体的messageQ项目。