据我了解应该有3种方式,IPC中断,notify,MessageQ。
1、IPC中断
1)IPC中断事件号91
2)选择中断向量
#define IPC_VECTID 8
3)中断配置
Hwi_Params hwiParams;
/* 中断配置 */
Hwi_Params_init(&hwiParams);
hwiParams.arg = (UArg)IPC_VECTID;
hwiParams.eventId = 91;
hwiParams.enableInt = TRUE;
Hwi_create(IPC_VECTID, (Hwi_FuncPtr)IsrMultiIpc, &hwiParams, NULL);
中断处理函数可以post信号量为后续处理
4)触发IPC中断
IPCGRx寄存器bit0置位触发IPC中断,高28位可以携带信息
/* IPCGR Info */
static volatile UINT iIPCGRInfo[8] =
{
IPCGR0,
IPCGR1,
IPCGR2,
IPCGR3,
IPCGR4,
IPCGR5,
IPCGR6,
IPCGR7
};
ERR IpcSendEvent(UINT coreId, UINT payLoad)
{
*(volatile UINT *)(iIPCGRInfo[coreId]) = (payLoad & 0xfffffff0);
*(volatile UINT *)(iIPCGRInfo[coreId]) |= 1;
RET_OK;
}
5)携带信息从IPCARx读取
/* IPCAR Info */
static volatile UINT iIPCARInfo[8] =
{
IPCAR0,
IPCAR1,
IPCAR2,
IPCAR3,
IPCAR4,
IPCAR5,
IPCAR6,
IPCAR7
};
UINT IpcGetEvent(UINT coreId)
{
volatile UINT payLoad;
payLoad = *(volatile UINT *)(iIPCARInfo[coreId]);
payLoad = payLoad & 0xfffffff0;
return payLoad;
}
2、notify
多核通信采用主从方式,core0主,其余从核
1)注册notify事件,主核注册从核notify事件,从核注册主核notify事件
#define INTERRUPT_LINE 0
#define EVENTID 10
if (coreId == DSP_CORE_0)
{
for (idx = 1; idx < DSP_CORE_NUM; idx++)
{
Notify_registerEvent(idx, INTERRUPT_LINE, EVENTID, (Notify_FnNotifyCbck)IsrMultiNotify, NULL);
}
}
else
{
Notify_registerEvent(DSP_CORE_0, INTERRUPT_LINE, EVENTID, (Notify_FnNotifyCbck)IsrMultiNotify, NULL);
}
注册回调可以post信号量为后续处理
2)notify事件发送
ERR NotifySendEvent(UINT coreId, UINT payLoad)
{
Notify_sendEvent(coreId, INTERRUPT_LINE, EVENTID, payLoad, TRUE);
RET_OK;
}
3、IPC or notify 数据发送
IPC 和 notify能发送的数据有限,只能作为核间事件通知。发送数据可以自定义共享队列。
基本思路是通过IPC中断或者notify事件,post信号量通知核间通信事件,读取共享队列获取核间通信数据。
#define SHARE_QUEUE_DEFAULE_LEN (256)
typedef struct
{
volatile UINT arg0;
volatile UINT arg1;
volatile UINT arg2;
volatile void *ptr;
}QUEUE_ELE;
typedef struct
{
volatile UINT wIdx;
volatile UINT rIdx;
volatile UINT queueLen;
volatile QUEUE_ELE ele[SHARE_QUEUE_DEFAULE_LEN];
}SHARE_QUEUE;
共享队列放在4M共享内存,DDR也可以。以上的数据结构只是个范例,arg可以作为cmd控制字,ptr指向核间通信的数据,少量数据可以放在共享内存,大数据放在DDR。
封装共享队列读写接口
BOOL ShareQueuePut(SHARE_QUEUE *pSQ, QUEUE_ELE *ele)
{
UINT r, w, irq;
UINT len;
BOOL bFound = FALSE;
if(pSQ == NULL || ele == NULL)
{
PRT("ShareQueuePut: ERR! pSQ:%x, ele:%x\n",pSQ, ele);
return FALSE;
}
len = pSQ->queueLen ? pSQ->queueLen : SHARE_QUEUE_DEFAULE_LEN;
r = pSQ->rIdx;
w = pSQ->wIdx;
if(FORWARD(w, len) != r)
{
memcpy((void *)&pSQ->ele[w], ele, sizeof(QUEUE_ELE));
pSQ->wIdx = FORWARD(w, len);
bFound = TRUE;
}
return bFound;
}
BOOL ShareQueueGet(SHARE_QUEUE *pSQ, QUEUE_ELE *ele)
{
UINT r, w, irq;
UINT len;
BOOL bFound = FALSE;
if(pSQ == NULL || ele == NULL)
{
PRT("ShareQueueGet: ERR! pSQ:%x, ele:%x\n",pSQ, ele);
return FALSE;
}
len = pSQ->queueLen ? pSQ->queueLen : SHARE_QUEUE_DEFAULE_LEN;
r = pSQ->rIdx;
w = pSQ->wIdx;
if(r != w)
{
memcpy(ele, (void *)&pSQ->ele[r], sizeof(QUEUE_ELE));
pSQ->rIdx = FORWARD(r, len);
bFound = TRUE;
}
return bFound;
}