Add mailbox based inter-processor communication
This commit is contained in:
@ -11,22 +11,9 @@
|
||||
|
||||
|
||||
enum SYS_CMD_ID {
|
||||
SYS_CMD_INFO_TRANS = 0x50,
|
||||
SYS_CMD_INFO_LINUX_INIT_DONE,
|
||||
SYS_CMD_INFO_RTOS_INIT_DONE,
|
||||
SYS_CMD_INFO_STOP_ISR,
|
||||
SYS_CMD_INFO_STOP_ISR_DONE,
|
||||
SYS_CMD_INFO_LINUX,
|
||||
SYS_CMD_INFO_RTOS,
|
||||
SYS_CMD_SYNC_TIME,
|
||||
SYS_CMD_INFO_DUMP_MSG,
|
||||
SYS_CMD_INFO_DUMP_EN,
|
||||
SYS_CMD_INFO_DUMP_DIS,
|
||||
SYS_CMD_INFO_DUMP_JPG,
|
||||
SYS_CMD_INFO_TRACE_SNAPSHOT_START,
|
||||
SYS_CMD_INFO_TRACE_SNAPSHOT_STOP,
|
||||
SYS_CMD_INFO_TRACE_STREAM_START,
|
||||
SYS_CMD_INFO_TRACE_STREAM_STOP,
|
||||
CMD_TEST_A = 0x10,
|
||||
CMD_TEST_B,
|
||||
CMD_TEST_C,
|
||||
SYS_CMD_INFO_LIMIT,
|
||||
};
|
||||
|
||||
|
||||
@ -19,49 +19,80 @@
|
||||
#include "cvi_spinlock.h"
|
||||
|
||||
|
||||
//#define __DEBUG__
|
||||
|
||||
// #define __DEBUG__
|
||||
#ifdef __DEBUG__
|
||||
#define debug_printf printf
|
||||
#else
|
||||
#define debug_printf(...)
|
||||
#endif
|
||||
|
||||
typedef struct _TASK_CTX_S {
|
||||
char name[32];
|
||||
u16 stack_size;
|
||||
UBaseType_t priority;
|
||||
void (*runTask)(void *pvParameters);
|
||||
u8 queLength;
|
||||
QueueHandle_t queHandle;
|
||||
} TASK_CTX_S;
|
||||
|
||||
/****************************************************************************
|
||||
* Function prototypes
|
||||
****************************************************************************/
|
||||
|
||||
|
||||
void prvQueueISR(void);
|
||||
void prvCmdQuRunTask(void *pvParameters);
|
||||
|
||||
|
||||
/****************************************************************************
|
||||
* Global parameters
|
||||
****************************************************************************/
|
||||
|
||||
TASK_CTX_S gTaskCtx[1] = {
|
||||
{
|
||||
.name = "CMDQU",
|
||||
.stack_size = configMINIMAL_STACK_SIZE,
|
||||
.priority = tskIDLE_PRIORITY + 5,
|
||||
.runTask = prvCmdQuRunTask,
|
||||
.queLength = 30,
|
||||
.queHandle = NULL,
|
||||
},
|
||||
};
|
||||
|
||||
/* mailbox parameters */
|
||||
volatile struct mailbox_set_register *mbox_reg;
|
||||
volatile struct mailbox_done_register *mbox_done_reg;
|
||||
volatile unsigned long *mailbox_context; // mailbox buffer context is 64 Bytess
|
||||
|
||||
|
||||
|
||||
/****************************************************************************
|
||||
* Function definitions
|
||||
****************************************************************************/
|
||||
|
||||
|
||||
|
||||
|
||||
DEFINE_CVI_SPINLOCK(mailbox_lock, SPIN_MBOX);
|
||||
|
||||
void main_create_tasks(void)
|
||||
{
|
||||
u8 i = 0;
|
||||
|
||||
#define TASK_INIT(_idx) \
|
||||
do { \
|
||||
gTaskCtx[_idx].queHandle = xQueueCreate(gTaskCtx[_idx].queLength, sizeof(cmdqu_t)); \
|
||||
if (gTaskCtx[_idx].queHandle != NULL && gTaskCtx[_idx].runTask != NULL) { \
|
||||
xTaskCreate(gTaskCtx[_idx].runTask, gTaskCtx[_idx].name, gTaskCtx[_idx].stack_size, \
|
||||
NULL, gTaskCtx[_idx].priority, NULL); \
|
||||
} \
|
||||
} while(0)
|
||||
|
||||
for (; i < ARRAY_SIZE(gTaskCtx); i++) {
|
||||
TASK_INIT(i);
|
||||
}
|
||||
}
|
||||
|
||||
void main_cvirtos(void)
|
||||
{
|
||||
printf("create cvi task\n");
|
||||
|
||||
|
||||
/* Start the tasks and timer running. */
|
||||
request_irq(MBOX_INT_C906_2ND, prvQueueISR, 0, "mailbox", (void *)0);
|
||||
main_create_tasks();
|
||||
/* Start the tasks and timer running. */
|
||||
vTaskStartScheduler();
|
||||
|
||||
|
||||
/* If all is well, the scheduler will now be running, and the following
|
||||
@ -77,3 +108,160 @@ void main_cvirtos(void)
|
||||
for (;;)
|
||||
;
|
||||
}
|
||||
|
||||
void prvCmdQuRunTask(void *pvParameters)
|
||||
{
|
||||
/* Remove compiler warning about unused parameter. */
|
||||
(void)pvParameters;
|
||||
|
||||
cmdqu_t rtos_cmdq;
|
||||
cmdqu_t *cmdq;
|
||||
cmdqu_t *rtos_cmdqu_t;
|
||||
static int stop_ip = 0;
|
||||
int ret = 0;
|
||||
int flags;
|
||||
int valid;
|
||||
int send_to_cpu = SEND_TO_CPU1;
|
||||
|
||||
unsigned int reg_base = MAILBOX_REG_BASE;
|
||||
|
||||
/* to compatible code with linux side */
|
||||
cmdq = &rtos_cmdq;
|
||||
mbox_reg = (struct mailbox_set_register *) reg_base;
|
||||
mbox_done_reg = (struct mailbox_done_register *) (reg_base + 2);
|
||||
mailbox_context = (unsigned long *) (MAILBOX_REG_BUFF);
|
||||
|
||||
cvi_spinlock_init();
|
||||
printf("prvCmdQuRunTask run\n");
|
||||
|
||||
for (;;) {
|
||||
xQueueReceive(gTaskCtx[0].queHandle, &rtos_cmdq, portMAX_DELAY);
|
||||
|
||||
switch (rtos_cmdq.cmd_id) {
|
||||
case CMD_TEST_A:
|
||||
//do something
|
||||
//send to C906B
|
||||
rtos_cmdq.cmd_id = CMD_TEST_A;
|
||||
rtos_cmdq.param_ptr = 0x12345678;
|
||||
rtos_cmdq.resv.valid.rtos_valid = 1;
|
||||
rtos_cmdq.resv.valid.linux_valid = 0;
|
||||
printf("recv cmd(%d) from C906B...send [0x%x] to C906B\n", rtos_cmdq.cmd_id, rtos_cmdq.param_ptr);
|
||||
goto send_label;
|
||||
case CMD_TEST_B:
|
||||
//nothing to do
|
||||
printf("nothing to do...\n");
|
||||
break;
|
||||
case CMD_TEST_C:
|
||||
rtos_cmdq.cmd_id = CMD_TEST_C;
|
||||
rtos_cmdq.param_ptr = 0x55aa;
|
||||
rtos_cmdq.resv.valid.rtos_valid = 1;
|
||||
rtos_cmdq.resv.valid.linux_valid = 0;
|
||||
printf("recv cmd(%d) from C906B...send [0x%x] to C906B\n", rtos_cmdq.cmd_id, rtos_cmdq.param_ptr);
|
||||
goto send_label;
|
||||
default:
|
||||
send_label:
|
||||
/* used to send command to linux*/
|
||||
rtos_cmdqu_t = (cmdqu_t *) mailbox_context;
|
||||
|
||||
debug_printf("RTOS_CMDQU_SEND %d\n", send_to_cpu);
|
||||
debug_printf("ip_id=%d cmd_id=%d param_ptr=%x\n", cmdq->ip_id, cmdq->cmd_id, (unsigned int)cmdq->param_ptr);
|
||||
debug_printf("mailbox_context = %x\n", mailbox_context);
|
||||
debug_printf("linux_cmdqu_t = %x\n", rtos_cmdqu_t);
|
||||
debug_printf("cmdq->ip_id = %d\n", cmdq->ip_id);
|
||||
debug_printf("cmdq->cmd_id = %d\n", cmdq->cmd_id);
|
||||
debug_printf("cmdq->block = %d\n", cmdq->block);
|
||||
debug_printf("cmdq->para_ptr = %x\n", cmdq->param_ptr);
|
||||
|
||||
drv_spin_lock_irqsave(&mailbox_lock, flags);
|
||||
if (flags == MAILBOX_LOCK_FAILED) {
|
||||
printf("[%s][%d] drv_spin_lock_irqsave failed! ip_id = %d , cmd_id = %d\n" , cmdq->ip_id , cmdq->cmd_id);
|
||||
break;
|
||||
}
|
||||
|
||||
for (valid = 0; valid < MAILBOX_MAX_NUM; valid++) {
|
||||
if (rtos_cmdqu_t->resv.valid.linux_valid == 0 && rtos_cmdqu_t->resv.valid.rtos_valid == 0) {
|
||||
// mailbox buffer context is 4 bytes write access
|
||||
int *ptr = (int *)rtos_cmdqu_t;
|
||||
|
||||
cmdq->resv.valid.rtos_valid = 1;
|
||||
*ptr = ((cmdq->ip_id << 0) | (cmdq->cmd_id << 8) | (cmdq->block << 15) |
|
||||
(cmdq->resv.valid.linux_valid << 16) |
|
||||
(cmdq->resv.valid.rtos_valid << 24));
|
||||
rtos_cmdqu_t->param_ptr = cmdq->param_ptr;
|
||||
debug_printf("rtos_cmdqu_t->linux_valid = %d\n", rtos_cmdqu_t->resv.valid.linux_valid);
|
||||
debug_printf("rtos_cmdqu_t->rtos_valid = %d\n", rtos_cmdqu_t->resv.valid.rtos_valid);
|
||||
debug_printf("rtos_cmdqu_t->ip_id =%x %d\n", &rtos_cmdqu_t->ip_id, rtos_cmdqu_t->ip_id);
|
||||
debug_printf("rtos_cmdqu_t->cmd_id = %d\n", rtos_cmdqu_t->cmd_id);
|
||||
debug_printf("rtos_cmdqu_t->block = %d\n", rtos_cmdqu_t->block);
|
||||
debug_printf("rtos_cmdqu_t->param_ptr addr=%x %x\n", &rtos_cmdqu_t->param_ptr, rtos_cmdqu_t->param_ptr);
|
||||
debug_printf("*ptr = %x\n", *ptr);
|
||||
// clear mailbox
|
||||
mbox_reg->cpu_mbox_set[send_to_cpu].cpu_mbox_int_clr.mbox_int_clr = (1 << valid);
|
||||
// trigger mailbox valid to rtos
|
||||
mbox_reg->cpu_mbox_en[send_to_cpu].mbox_info |= (1 << valid);
|
||||
mbox_reg->mbox_set.mbox_set = (1 << valid);
|
||||
break;
|
||||
}
|
||||
rtos_cmdqu_t++;
|
||||
}
|
||||
drv_spin_unlock_irqrestore(&mailbox_lock, flags);
|
||||
if (valid >= MAILBOX_MAX_NUM) {
|
||||
printf("No valid mailbox is available\n");
|
||||
return -1;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void prvQueueISR(void)
|
||||
{
|
||||
printf("prvQueueISR\n");
|
||||
unsigned char set_val;
|
||||
unsigned char valid_val;
|
||||
int i;
|
||||
cmdqu_t *cmdq;
|
||||
BaseType_t YieldRequired = pdFALSE;
|
||||
|
||||
set_val = mbox_reg->cpu_mbox_set[RECEIVE_CPU].cpu_mbox_int_int.mbox_int;
|
||||
|
||||
if (set_val) {
|
||||
for(i = 0; i < MAILBOX_MAX_NUM; i++) {
|
||||
valid_val = set_val & (1 << i);
|
||||
|
||||
if (valid_val) {
|
||||
cmdqu_t rtos_cmdq;
|
||||
cmdq = (cmdqu_t *)(mailbox_context) + i;
|
||||
|
||||
debug_printf("mailbox_context =%x\n", mailbox_context);
|
||||
debug_printf("sizeof mailbox_context =%x\n", sizeof(cmdqu_t));
|
||||
/* mailbox buffer context is send from linux, clear mailbox interrupt */
|
||||
mbox_reg->cpu_mbox_set[RECEIVE_CPU].cpu_mbox_int_clr.mbox_int_clr = valid_val;
|
||||
// need to disable enable bit
|
||||
mbox_reg->cpu_mbox_en[RECEIVE_CPU].mbox_info &= ~valid_val;
|
||||
|
||||
// copy cmdq context (8 bytes) to buffer ASAP
|
||||
*((unsigned long *) &rtos_cmdq) = *((unsigned long *)cmdq);
|
||||
/* need to clear mailbox interrupt before clear mailbox buffer */
|
||||
*((unsigned long*) cmdq) = 0;
|
||||
|
||||
/* mailbox buffer context is send from linux*/
|
||||
if (rtos_cmdq.resv.valid.linux_valid == 1) {
|
||||
debug_printf("cmdq=%x\n", cmdq);
|
||||
debug_printf("cmdq->ip_id =%d\n", rtos_cmdq.ip_id);
|
||||
debug_printf("cmdq->cmd_id =%d\n", rtos_cmdq.cmd_id);
|
||||
debug_printf("cmdq->param_ptr =%x\n", rtos_cmdq.param_ptr);
|
||||
debug_printf("cmdq->block =%x\n", rtos_cmdq.block);
|
||||
debug_printf("cmdq->linux_valid =%d\n", rtos_cmdq.resv.valid.linux_valid);
|
||||
debug_printf("cmdq->rtos_valid =%x\n", rtos_cmdq.resv.valid.rtos_valid);
|
||||
|
||||
xQueueSendFromISR(gTaskCtx[0].queHandle, &rtos_cmdq, &YieldRequired);
|
||||
|
||||
portYIELD_FROM_ISR(YieldRequired);
|
||||
} else
|
||||
printf("rtos cmdq is not valid %d, ip=%d , cmd=%d\n",
|
||||
rtos_cmdq.resv.valid.rtos_valid, rtos_cmdq.ip_id, rtos_cmdq.cmd_id);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -103,6 +103,7 @@ within this file. */
|
||||
void vApplicationMallocFailedHook(void);
|
||||
void vApplicationIdleHook(void);
|
||||
void vApplicationStackOverflowHook(TaskHandle_t pxTask, char *pcTaskName);
|
||||
void vApplicationTickHook(void);
|
||||
|
||||
/* configAPPLICATION_ALLOCATED_HEAP is set to 1 in FreeRTOSConfig.h so the
|
||||
application can define the array used as the FreeRTOS heap. This is done so the
|
||||
@ -220,6 +221,17 @@ void vApplicationIdleHook(void)
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void vApplicationTickHook(void)
|
||||
{
|
||||
#ifdef FULL_DEMO
|
||||
{
|
||||
/* Only the comprehensive demo actually uses the tick hook. */
|
||||
extern void vFullDemoTickHook(void);
|
||||
vFullDemoTickHook();
|
||||
}
|
||||
#endif
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* configUSE_STATIC_ALLOCATION is set to 1, so the application must provide an
|
||||
implementation of vApplicationGetIdleTaskMemory() to provide the memory that is
|
||||
|
||||
Reference in New Issue
Block a user