autochip RVC

目录

RVC RTOS 代码流程分析

创建vBackcarGPIOMonitorTask监控线程

 获取backcar gpio的值

接收eBCStartEvent 事件

autochip ipc arm1&arm2核间通信

构建ipc_chan  将chan list node 挂到chan->dev->ipc_list 上获取ipc msg

 memcpy_fromio 获取send 到arm1 上的ipc msg

 将ipc msg 拷贝到内核的buf

 Kernel  backcar 接收RVC_IPC_KEY_ARM2_NOTIFY

IPC send

更新msg_free

 获取chan msg 发送到ipc msg

backcar 使用backcardrv ioctl 发送ipc msg

RVC  hal 层

通过metazone 获取METAZONE_BACKCAR_VDO_SOURCE的值

通过backcardrv文件节点获取msg

 arm 2 上的rtos 获取倒车的gpio的信息通过backcar驱动解析后将event事件挂在notify_event_list

arm ap 侧使用驱动read的接口获取backcardrv arm2 的msg

hal层rvcDataChangeNotify将回调java注册callback函数

 java层backcar service 注册hal 回调函数

backcar service  callbac函数 sendmsg EVENT_TYPE_RVC_DATA_CHANGE给app 

触发app start RVC


RVC RTOS 代码流程分析

dtsi 中配置的gpio 用于触发RVC 

g_device_dtb_info->avin_info.gpio_trigger_backcar

vendor/autochips/proprietary/tinysys/viss/os/drivers/backcar/

/*********************************************************************
 * Task for handle backcar events: start/stop/update/suspend/resume.
 *********************************************************************/
void vBackcarMainTask( void *pvParameters )
{
    //TickType_t xQueueReceiveWait = pdMS_TO_TICKS( 0 );
    BCEventType_t xBCEventType = eBCNoneEvent;
    RVCData_t xRVCData;
    BC_INFO("backcar main task start. videoin viss time: %dms\n", get_current_time_ms());

    (void)pvParameters;

    /*check backcar status and notify apm first to ensure LOGO/ANI can show in time*/
    BC_INFO("backcarGPIO_NUM=%d\r\n", backcarGPIO_NUM);
    if( pdPASS != xBCGPIOInit( backcarGPIO_NUM ) )
    {
        BC_ERR("init backcar gpio fail\r\n");
    }

    xBCEventType = xBCGPIOGetCurEvent();
    if( eBCStopEvent == xBCEventType )
    {
        BC_INFO("backcar at stop status before backcar init \r\n");
        if( NULL != pxBCCallback )
        {
            pxBCCallback( xBCEventType );
        }
    }

    if( pdFAIL == xBCModulesInit() )
    {
        BC_ERR("backcar task init failed \r\n");
        if( eBCStartEvent == xBCEventType )
        {
            xBCEventType = eBCStopEvent;
            pxBCCallback( xBCEventType );
        }
    }

    for( ; ; )
    {
        if( NULL == xBCEventQueue )
        {
            BC_ERR("backcar event queue is null \r\n");
            break;
        }

        if( pdPASS == xQueueReceive( xBCEventQueue, &xBCEventType, portMAX_DELAY ) ) //always block for events
        {
            BC_INFO("backcar event received: %d \r\n", xBCEventType);

            if( pdTRUE == xStopHandleEvent )
            {
                BC_INFO("viss rvc will exit, stop handle any rvc event!\r\n");
                continue;
            }

            switch( xBCEventType )
            {
            case eBCStartEvent:
                BC_INFO("get start event. videoin viss time: %dms\n", get_current_time_ms());
                if( xArm1BCIsReady || !xScreenMCUOn || !xDisplayPowerOn )
                {
                    BC_INFO("arm1 backcar is ready or screen is off, do not respond to eBCStartEvent\r\n");
                    break;
                }
                if( pdPASS != xBackcarShow() )
                {
                    BC_ERR("backcar start failed \r\n");
                    break;
                }

                if( NULL != pxBCCallback )
                {
                    pxBCCallback( xBCEventType );
                }
                g_xRVCCurDataSet.lRVCStatus = 0;
                memset( &xRVCData, 0, sizeof( RVCData_t ) );
                strcpy( xRVCData.ipc_key, RVC_IPC_KEY_ARM2_NOTIFY );
                xRVCData.type = RVC_DATA_RVC_STATUS;
                xRVCData.data[0] = g_xRVCCurDataSet.lRVCStatus;
                xBackcarSendMsgToArm1( (void *)&xRVCData );
                break;

            case eBCStopEvent:
                                if( !xScreenMCUOn || !xDisplayPowerOn )
                {
                    BC_INFO("screen is off, do not respond to eBCStopEvent\r\n");
                    break;
                }

                if( pdPASS != xBackcarHide() )
                {
                    BC_ERR("backcar stop failed \r\n");
                }

                if( xArm1BCIsReady )
                {
                    BC_INFO("arm1 backcar is ready, quit arm2 backcar forever\r\n");
                    xStopHandleEvent = pdTRUE;
                    xBCEventType = eBCQuitEvent;
                }

                if( NULL != pxBCCallback )
                {
                    pxBCCallback( xBCEventType );
                }
                g_xRVCCurDataSet.lRVCStatus = 1;
                memset( &xRVCData, 0, sizeof( RVCData_t ) );
                strcpy( xRVCData.ipc_key, RVC_IPC_KEY_ARM2_NOTIFY );
                xRVCData.type = RVC_DATA_RVC_STATUS;
                xRVCData.data[0] = g_xRVCCurDataSet.lRVCStatus;
                xBackcarSendMsgToArm1( (void *)&xRVCData );
                break;

            case eBCUpdateEvent:
                if( pdPASS != xBackcarUpdate() )
                {
                    BC_ERR("backcar update failed \r\n");
                    break;
                }
                break;

            case eBCSuspendEvent:
                if( pdPASS != xBackcarSuspend() )
                {
                    BC_ERR("backcar suspend failed \r\n");
                    break;
                }
                break;

            case eBCResumeEvent:
                if( pdPASS != xBackcarResume() )
                {
                    BC_ERR("backcar resume failed \r\n");
                    break;
                }
                break;

            default:
                BC_ERR("backcar unknown event occured \r\n");
                break;
            }
        }
    }

    vTaskDelete(NULL);
}

创建vBackcarGPIOMonitorTask监控线程

触发倒车eBCStartEvent

/**********************************************************************
 * Task for monitor backcar switch event through polling gpio value
 **********************************************************************/
void vBackcarGPIOMonitorTask( void *pvParameters )
{
    TickType_t xDelay = pdMS_TO_TICKS( 200 );
    TickType_t xQueueSendWait = pdMS_TO_TICKS( 0 ); //no wait, if queue is full and send fail, do not change last gpio value, wait for next task circle to send
    int lCurGPIOVal = gpioUNKNOWN;
    int lLastGPIOVal = gpioUNKNOWN;
    BCEventType_t xBCEventType = eBCNoneEvent;

    BC_INFO("backcar gpio monitor task start\r\n");
    (void)pvParameters;

    for( ; ; )
    {
        if( NULL == xBCEventQueue )
        {
            BC_ERR("backcar event queue is null \r\n");
            goto end;
        }
        //获取gpio_trigger_backcar gpio value
        lCurGPIOVal = lBCGPIOGetValue();
        if( lLastGPIOVal != lCurGPIOVal )
        {
            if( gpioHIGH == lCurGPIOVal )
            {
                BC_INFO("[%d ms] _lyq backcar start event occured \r\n",get_current_time_ms());
                //触发倒车
                xBCEventType = eBCStartEvent;
            }
            else if( gpioLOW == lCurGPIOVal )
            {
                BC_INFO("_lyq backcar stop event occured \r\n");
                //结束倒车
                xBCEventType = eBCStopEvent;
            }
            else
            {
                BC_ERR("backcar unknow event occured \r\n");
                goto end;
            }
            //Notice: if many other events sent to queue after xQueueReset and before xQueueSend. this event may send fail
            xQueueReset( xBCEventQueue ); //clean event queue.The interface always return pdPASS since FreeRTOS V7.2.0
            if( pdPASS != xQueueSend( xBCEventQueue, &xBCEventType, xQueueSendWait ) )
            {
                BC_ERR("send backcar start/stop event to queue fail \r\n");
                goto end;
            }
            lLastGPIOVal = lCurGPIOVal;
        }
        xDelay = pdMS_TO_TICKS( 10 );
        vTaskDelay( xDelay );
        continue;

end:
        xBCEventType = eBCNoneEvent;
        xDelay = pdMS_TO_TICKS( 100 ); //change frequence of checking gpio value  when error accured
        vTaskDelay( xDelay );
    }

    vTaskDelete(NULL);
}

 获取backcar gpio的值

static int lBCGPIOGetValue()
{
    int lGPIOValue = gpioUNKNOWN;
    if( ulBCGPIONum != 0 )
    {
        lGPIOValue = xGpioGetPinValue( ulBCGPIONum );
    }
    return lGPIOValue;
}
int xGpioGetPinValue(long lPin)
{
        unsigned int ext_info = 0;
        unsigned int group = 0, offset = 0;
        unsigned int value = 0;

        if (lPin >= GPIO_NUM) {
                GPIO_ERR("Input pin number is %ld, Not support!\n", lPin);
                return -1;
        }

        ext_info = gpio_ext_info[lPin];

        group = GET_GROUP_NUM(ext_info);
        if (group == GPIO_UNSUPPORT) {
                GPIO_INFO("Input pin number is %ld, Not support!\n", lPin);
                return -1;
        }
        offset = GET_GROUP_OFFSET(ext_info);

        value = gpio_hal_input_value_get(group);

        return (value >> offset & GPIO_BITMASK);
}

接收eBCStartEvent 事件

发送RVC_IPC_KEY_ARM2_NOTIFY给arm1 ap 侧


/*********************************************************************
 * Task for handle backcar events: start/stop/update/suspend/resume.
 *********************************************************************/
void vBackcarMainTask( void *pvParameters )
{
    //TickType_t xQueueReceiveWait = pdMS_TO_TICKS( 0 );
    BCEventType_t xBCEventType = eBCNoneEvent;
    RVCData_t xRVCData;
    BC_INFO("backcar main task start. videoin viss time: %dms\n", get_current_time_ms());

    (void)pvParameters;

    /*check backcar status and notify apm first to ensure LOGO/ANI can show in time*/
    BC_INFO("backcarGPIO_NUM=%d\r\n", backcarGPIO_NUM);
    if( pdPASS != xBCGPIOInit( backcarGPIO_NUM ) )
    {
        BC_ERR("init backcar gpio fail\r\n");
    }

    xBCEventType = xBCGPIOGetCurEvent();
    if( eBCStopEvent == xBCEventType )
    {
        BC_INFO("backcar at stop status before backcar init \r\n");
        if( NULL != pxBCCallback )
        {
            pxBCCallback( xBCEventType );
        }
    }

    if( pdFAIL == xBCModulesInit() )
    {
        BC_ERR("backcar task init failed \r\n");
        if( eBCStartEvent == xBCEventType )
        {
            xBCEventType = eBCStopEvent;
            pxBCCallback( xBCEventType );
        }
    }

    for( ; ; )
    {
        if( NULL == xBCEventQueue )
        {
            BC_ERR("backcar event queue is null \r\n");
            break;
        }

        if( pdPASS == xQueueReceive( xBCEventQueue, &xBCEventType, portMAX_DELAY ) ) //always block for events
        {
            BC_INFO("backcar event received: %d \r\n", xBCEventType);

            if( pdTRUE == xStopHandleEvent )
            {
                BC_INFO("viss rvc will exit, stop handle any rvc event!\r\n");
                continue;
            }

            switch( xBCEventType )
            {
            case eBCStartEvent:
                BC_INFO("get start event. videoin viss time: %dms\n",   get_current_time_ms());
                if( xArm1BCIsReady || !xScreenMCUOn || !xDisplayPowerOn )
                {
                    BC_INFO("arm1 backcar is ready or screen is off, do not respond to eBCStartEvent\r\n");
                    break;
                }
                if( pdPASS != xBackcarShow() )
                {
                    BC_ERR("backcar start failed \r\n");
                    break;
                }

                if( NULL != pxBCCallback )
                {
                    pxBCCallback( xBCEventType );
                }
                //arm2 对arm1 发送ipc 消息
                g_xRVCCurDataSet.lRVCStatus = 0;
                memset( &xRVCData, 0, sizeof( RVCData_t ) );
                strcpy( xRVCData.ipc_key, RVC_IPC_KEY_ARM2_NOTIFY );
                xRVCData.type = RVC_DATA_RVC_STATUS;
                xRVCData.data[0] = g_xRVCCurDataSet.lRVCStatus;
                xBackcarSendMsgToArm1( (void *)&xRVCData );
                break;

            case eBCStopEvent:
                                if( !xScreenMCUOn || !xDisplayPowerOn )
                {
                    BC_INFO("screen is off, do not respond to eBCStopEvent\r\n");
                    break;
                }

                if( pdPASS != xBackcarHide() )
                {
                    BC_ERR("backcar stop failed \r\n");
                }

                if( xArm1BCIsReady )
                {
                    BC_INFO("arm1 backcar is ready, quit arm2 backcar forever\r\n");
                    xStopHandleEvent = pdTRUE;
                    xBCEventType = eBCQuitEvent;
                }

                if( NULL != pxBCCallback )
                {
                    pxBCCallback( xBCEventType );
                }
                g_xRVCCurDataSet.lRVCStatus = 1;
                memset( &xRVCData, 0, sizeof( RVCData_t ) );
                strcpy( xRVCData.ipc_key, RVC_IPC_KEY_ARM2_NOTIFY );
                xRVCData.type = RVC_DATA_RVC_STATUS;
                xRVCData.data[0] = g_xRVCCurDataSet.lRVCStatus;
                xBackcarSendMsgToArm1( (void *)&xRVCData );
                break;

            case eBCUpdateEvent:
                if( pdPASS != xBackcarUpdate() )
                {
                    BC_ERR("backcar update failed \r\n");
                    break;
                }
                break;

            case eBCSuspendEvent:
                if( pdPASS != xBackcarSuspend() )
                {
                    BC_ERR("backcar suspend failed \r\n");
                    break;
                }
                break;

            case eBCResumeEvent:
                if( pdPASS != xBackcarResume() )
                {
                    BC_ERR("backcar resume failed \r\n");
                    break;
                }
                break;

            default:
                BC_ERR("backcar unknown event occured \r\n");
                break;
            }
        }
    }

    vTaskDelete(NULL);
}

autochip ipc arm1&arm2核间通信

构建ipc_chan  将chan list node 挂到chan->dev->ipc_list 上获取ipc msg

#define ipc_request_chan_detailed(proc, direction, snd, rcv) \
163  ({                                                           \
164          ipc_chan_t *__chan = ipc_request_chan(proc, direction);  \
165          if (__chan) {                                            \
166                  strncpy(__chan->sender, snd, 8);                     \
167                  strncpy(__chan->receiver, rcv, 8);                   \
168          }                                                        \
169          __chan;                                                  \
170  })

482  ipc_chan_t *ipc_request_chan(enum IPC_CORE proc, enum IPC_DIRECTION direction)
483  {
484          ipc_chan_t *chan = NULL;
485  
486          if (proc != CORE_VEHICLE) {
487                  pr_err("[AIPC] %s unsupport communicate with core=%d\n", __func__,
488                         proc);
489                  return NULL;
490          }
491  
492          chan = kzalloc(sizeof(ipc_chan_t), GFP_KERNEL);
493          if (!chan) {
494                  pr_err("[AIPC] %s no memory\n", __func__);
495                  return NULL;
496          }
497  
498          spin_lock_init(&chan->lock);
499  
500          if (direction == MSGSEND) {        //send
501                  chan->dev = dev_ap2viss;
502          } else if (direction == MSGRECV) { 
                       //receive
                       //接收msg
503                  chan->dev = dev_viss2ap;
504                  init_waitqueue_head(&chan->wait);
505  
506                  mutex_lock(&ipc_mutex);
                    //将chan list node 挂到chan->dev->ipc_list 上获取ipc msg
507                  list_add(&chan->list_node, &(chan->dev->ipc_list));
508                  chan->dev->idr_ref++;
509                  mutex_unlock(&ipc_mutex);
510          }
511  
512          return chan;
513  }
514  
515  EXPORT_SYMBOL_GPL(ipc_request_chan);

 memcpy_fromio 获取send 到arm1 上的ipc msg

Linux-IO端口、IO内存详解_memcpy_fromio-优快云博客

static void ipc_find_work(struct work_struct *work)
145  {
146          uint8_t first_entry = 0;
147          ipc_msg_t *ipc_msg = NULL;
148          ipc_chan_t *chan = NULL;
149          ipc_chan_dev_t *dev = dev_viss2ap;        // AP <- VEHICLE
150          void *msg;
151          unsigned idx = 0;
152          unsigned long flags;
153  
154          // 2. account all.
155          mutex_lock(&ipc_mutex);
156          while (ipc_hal_responder_get_number_valid(dev->oid, dev->rid)) {
157                  first_entry = ipc_hal_responder_get_first_valid(dev->oid, dev->rid);
158                  ipc_msg =
159                      (ipc_msg_t *) (dev->base_addr + first_entry * IPC_PACKET_SIZE);
160  
                   //循环遍历ipc_list的list_node  匹配receiver
161                  list_for_each_entry(chan, &dev->ipc_list, list_node) {
162                          if (!strncmp(chan->receiver, ipc_msg->receiver, 8)) {
163                                  //pr_info("[AIPC] the lucker %s\n", chan->receiver);
164                                  spin_lock_irqsave(&chan->lock, flags);
165                                  if (chan->msg_count == IPC_MSG_QUEUE_LEN) {
166                                          spin_unlock_irqrestore(&chan->lock, flags);
167                                          continue;
168                                  }
169  
170                                  idx = chan->msg_free;
171                                  //判断ipc msg不为空 
172                                  if (ipc_msg->msg && ipc_msg->size) {
173                                          msg = kmalloc(ipc_msg->size, GFP_KERNEL);
174                                          if (!msg) {
175                                                  pr_err("[AIPC] %s no memory\n",
                                                       __func__);
176                                                  spin_unlock_irqrestore(&chan->lock,
                                                                   flags);
177                                                  continue;
178                                          }
179                                         //获取ipc msg 保存到chan msg_data
180                                          memcpy_fromio(msg, ipc_msg->msg,
                                                              ipc_msg->size);
181                                          chan->msg_data[idx].msg = msg;
182                                          chan->msg_data[idx].size = ipc_msg->size;
183                                  } else {
184                                          chan->msg_data[idx].msg = NULL;
185                                          chan->msg_data[idx].size = 0;
186                                  }
187  
188                                  pr_debug("[AIPC] ipc_find_work %s->%s, %s, %d, %u,                                                   %u\n", chan->sender, chan->receiver,
189                                          (char *)(chan->msg_data[idx].msg), chan-       
                                                     >msg_data[idx].size,
190                                          chan->msg_count, chan->msg_free);
191  
192                                  chan->msg_count++;
193  
194                                  if (idx == IPC_MSG_QUEUE_LEN - 1)
195                                          chan->msg_free = 0;
196                                  else
197                                          chan->msg_free++;
198  
199                                  spin_unlock_irqrestore(&chan->lock, flags);
200  
201                                  wake_up_interruptible(&chan->wait);
202                          }
203                  }//1: no luck receiver, publish ,account it
204  
205                  ipc_ack(dev);
206          }
207          mutex_unlock(&ipc_mutex);
208  }
 #define ipc_receivemsg_timeout(c, m, s, t)                   \
183  ({                                                           \
184          int __rc = 0;                                                  \
185          __rc = ipc_receive_timeout(c, t);                        \
186          if (__rc == 0) {                                         \
187                  __rc = (int)ipc_read(c, m, s);                       \
188          }                                                        \
189          __rc;                                                    \
190  })
191  
192  #define ipc_receive(c) ipc_receive_timeout(c, 0)
193  
194  #define ipc_receivemsg(c, m, s) ipc_receivemsg_timeout(c, m, s, 0)

 将ipc msg 拷贝到内核的buf

ssize_t ipc_read(ipc_chan_t *chan, void *buf, size_t nbytes)
309  {
310          unsigned long flags;
311          ssize_t n = 0;
312          unsigned idx = 0;
313          unsigned count = 0;
314  
315          spin_lock_irqsave(&chan->lock, flags);
316          count = chan->msg_count;
317          if (count == 0) {
318                  spin_unlock_irqrestore(&chan->lock, flags);
319                  return 0;
320          }
321  
322          idx = chan->msg_free;
323          if (idx >= count)
324                  idx -= count;
325          else //初始化 msg_free
326                  idx += IPC_MSG_QUEUE_LEN - count;
327  
328          pr_debug("[AIPC] ipc_read %s->%s, %s, %d, %u, %u\n", chan->sender, chan-                                                                                    >receiver,
329                          (char *)(chan->msg_data[idx].msg), chan->msg_data[idx].size,
330                          chan->msg_count, chan->msg_free);
331  
332          n = nbytes < chan->msg_data[idx].size ? nbytes : chan->msg_data[idx].size;
333          if (chan->msg_data[idx].msg && n) {
334                  memcpy(buf, chan->msg_data[idx].msg, n);
335          }
336  
337          if (chan->msg_data[idx].msg){
338                  kfree(chan->msg_data[idx].msg);
339                  chan->msg_data[idx].msg = NULL;
340          }
341  
342          chan->msg_count--;
343  
344          spin_unlock_irqrestore(&chan->lock, flags);
345  
346          return n;
347  }
348  
349  EXPORT_SYMBOL_GPL(ipc_read);

 Kernel  backcar 接收RVC_IPC_KEY_ARM2_NOTIFY

 #ifndef CONFIG_BACKCAR_NO_ARM2
202  static int backcar_ipc_receive_thread(void *data)
203  {
204          int ret = 0;
205          char arm2_msg[ipcMSG_LENGTH] = {0,};
206          struct rvc_data received_rvc_data;
207          struct arm2_rvc_event *event = NULL;
208          BACKCAR_LOG(BACKCAR_INFO, "backcar_ipc_receive_thread start\n");
209  
210          do {
211                  if (!g_ipc_receive_chan) {
212                          BACKCAR_LOG(BACKCAR_INFO, "ipc receive chan is null, request                                                 chan first.\n");
                           //一个创建ipc recevice chan 
                           //sender= g_ipc_arm1_ap 
                           //receiver=g_ipc_arm2_rvc
213                          g_ipc_receive_chan = ipc_request_chan_detailed(CORE_VEHICLE,                                                 MSGRECV, , g_ipc_arm1_ap);
214                          if (!g_ipc_receive_chan) {
215                                  BACKCAR_LOG(BACKCAR_ERR, "ipc request receive chan                                                         fail\n");
216                                  continue;
217                          }
218                  }
219  
220                  memset(arm2_msg, 0, sizeof(arm2_msg));
                     //IPC通信接收小核 arm2的msg
221                  ret = ipc_receivemsg(g_ipc_receive_chan, arm2_msg, ipcMSG_LENGTH);
222                  if (ret < 0) {
223                          BACKCAR_LOG(BACKCAR_ERR, "ipc receive fail %d\n", ret);
224                          continue;
225                  }
226  
227                  BACKCAR_LOG(BACKCAR_DEBUG, "ipc receive arm2_msg %s\n", arm2_msg);
228                  if (!strncmp(cIpcMsgRcvArm2BCExit, arm2_msg, ipcMSG_LENGTH)) {
229                          BACKCAR_LOG(BACKCAR_INFO, "backcar receive msg %s success \n",                                                     cIpcMsgRcvArm2BCExit);
230                          if (NULL != g_ioctlwaitq) {
231                                  wake_up(g_ioctlwaitq);
232                          } else {
233                          BACKCAR_LOG(BACKCAR_WARNING, "g_ioctl waitq has been waked.                                                         but not by arm2 msg\n");
234                          }
235                  } else {
236                          memset(&received_rvc_data, 0, sizeof(struct rvc_data));
237                          memcpy(&received_rvc_data, arm2_msg, ipcMSG_LENGTH);
238                          if (0 == strcmp(received_rvc_data.ipc_key,                                                         RVC_IPC_KEY_ARM2_RESPOND)) {
239                                  BACKCAR_LOG(BACKCAR_DEBUG, "RVC_IPC_KEY_ARM2_NOTIFY                                                     received. type = %d, data[0]= %d\n",
240                                                received_rvc_data.type,                                                                     received_rvc_data.data[0]);
241                                  memset(&g_responsed_rvc_data, 0, sizeof(struct                                                                                     rvc_data));
242                                  memcpy(&g_responsed_rvc_data, arm2_msg, ipcMSG_LENGTH);
243                          } else if (0 == strcmp(received_rvc_data.ipc_key,                                                                         RVC_IPC_KEY_ARM2_NOTIFY)) {
244                                  BACKCAR_LOG(BACKCAR_INFO, "RVC_IPC_KEY_ARM2_NOTIFY                                                             received. type = %d, data[0]= %d\n",
245                                                  received_rvc_data.type,                                                                     received_rvc_data.data[0]);
246                                  event = kzalloc(sizeof(*event), GFP_KERNEL);
247                                  if (!event) {
248                                          BACKCAR_LOG(BACKCAR_ERR, "kzalloc failed \n");
249                                          break;
250                                  }
251                                  memset(&(event->data), 0, sizeof(struct rvc_data));
252                                  memcpy(&(event->data), arm2_msg, ipcMSG_LENGTH);
253                                  mutex_lock(&g_event_manager.event_mutex);
254                                  list_add_tail(&event->list,                                                                                 &g_event_manager.notify_event_list);
255                                  mutex_unlock(&g_event_manager.event_mutex);
256                                  wake_up(&g_event_manager.event_queue_wait);
257                          } else {
258                                  BACKCAR_LOG(BACKCAR_INFO, "ipc not receive request msg \n");
259                                  break;
260                          }
261                  }
262                  msleep(1);
263          } while (!kthread_should_stop());
264  
265          BACKCAR_LOG(BACKCAR_INFO, "backcar_ipc_receive_thread leave \n");
266          return 0;
267  }
268  #endif

IPC send

102  static long ipc_send_msg(const char* msg)
103  {
104          int ret = 0;
105          if (!g_ipc_send_chan) {
106                  BACKCAR_LOG(BACKCAR_INFO, "ipc send chan is null, request chan                                                 first.\n");
107                  g_ipc_send_chan = ipc_request_chan_detailed(CORE_VEHICLE, MSGSEND,                                   g_ipc_arm1_ap, g_ipc_arm2_apm);
108                  if (!g_ipc_send_chan) {
109                          BACKCAR_LOG(BACKCAR_ERR, "ipc request send chan fail\n");
110                          return -EFAULT;
111                  }
112          }
113  
114          ret = ipc_sendmsg(g_ipc_send_chan, msg, ipcMSG_LENGTH);
115          if (ret < 0) {
116                  BACKCAR_LOG(BACKCAR_ERR, "ipc send fail %d\n", ret);
117                  return -EFAULT;
118          }
119          return 0;
120  }

 #define ipc_sendmsg(c, m, s)                                 \
173  ({                                                           \
174          int __rc = 0;                                            \
175          preempt_disable();                                       \
176          ipc_write(c, m, s);                                      \
177          __rc = ipc_send(c);                                      \
178          preempt_enable();                                        \
179          __rc;                                                    \
180  })

更新msg_free


351  ssize_t ipc_write(ipc_chan_t *chan, const void *buf, size_t nbytes)352  {
353          unsigned long flags;
354          unsigned idx = 0;
355          ssize_t n = 0;
356  
357          spin_lock_irqsave(&chan->lock, flags);
358          if (chan->msg_count == IPC_MSG_QUEUE_LEN) {
359                  spin_unlock_irqrestore(&chan->lock, flags);
360                  return 0;
361          }
362  
363          idx = chan->msg_free;
364  
365          n = nbytes < MAX_MSG_LEN ? nbytes : MAX_MSG_LEN;
366          chan->msg_data[idx].size = n;
367          chan->msg_data[idx].msg = (void *)buf;
368  
369          pr_debug("[AIPC] ipc_write %s->%s, %s, %d, %u, %u\n", chan->sender, chan-                                        >receiver,
370                          (char *)(chan->msg_data[idx].msg), chan->msg_data[idx].size,
371                          chan->msg_count, chan->msg_free);
372  
373          chan->msg_count++;
374  
375          if (idx == IPC_MSG_QUEUE_LEN - 1)
376                  chan->msg_free = 0;
377          else
378                  chan->msg_free++;
379  
380          spin_unlock_irqrestore(&chan->lock, flags);
381  
382          return n;
383  }
384  
385  EXPORT_SYMBOL_GPL(ipc_write);

 获取chan msg 发送到ipc msg

int ipc_send(ipc_chan_t *chan)
388  {
389          uint32_t n = 0;
390          uint8_t last_entry = 0;
391          ipc_chan_dev_t *dev = NULL;
392          ipc_msg_t *ipc_msg = NULL;
393          unsigned count = 0;
394          unsigned idx = 0;
395          unsigned long flags;
396  
397          if (!chan || !(chan->dev)) {
398                  pr_err("[AIPC] %s invalid chan\n", __func__);
399                  return -EINVAL;
400          }
401  
402          dev = chan->dev;
403  
404          spin_lock_irqsave(&chan->lock, flags);
405          count = chan->msg_count;
406  
407          while (count) {
408                  if (ipc_hal_originator_not_full(dev->oid, dev->rid) == 0) {
409                          pr_err("[AIPC] %s chan is full\n", __func__);
410                          spin_unlock_irqrestore(&chan->lock, flags);
411                          return -EBUSY;
412                  }
413  
414                  last_entry = ipc_hal_originator_get_last_valid(dev->oid, dev->rid);
415                  ipc_msg = (ipc_msg_t *) (dev->base_addr + last_entry * dev-                                                                                >packet_size);
416  
417                  strncpy(ipc_msg->sender, chan->sender, 8);
418                  strncpy(ipc_msg->receiver, chan->receiver, 8);
419  
420                  idx = chan->msg_free;
421                  if (idx >= count)
422                          idx -= count;
423                  else
424                          idx += IPC_MSG_QUEUE_LEN - count;
425  
426                  n = chan->msg_data[idx].size < MAX_MSG_LEN ? chan->msg_data[idx].size                             : MAX_MSG_LEN;
427                  if (chan->msg_data[idx].msg && n) {
428                          memcpy_toio(ipc_msg->msg, chan->msg_data[idx].msg, n);
429                  } else { // NULL msg
430                          n = 0;
431                  }
432  
433                  ipc_msg->size = n;
434  
435                  wmb();
436  
437                  pr_debug("[AIPC] ipc_send %s->%s, %s, %d, %u, %u\n", chan->sender,                                             chan->receiver,
438                                  (char *)(chan->msg_data[idx].msg), chan-                                                                      >msg_data[idx].size,
439                                  chan->msg_count, chan->msg_free);
440  
441                  ipc_notify(dev);
442  
443                  chan->msg_count--;
444                  count = chan->msg_count;
445          }
446  
447          spin_unlock_irqrestore(&chan->lock, flags);
448  
449          return n;
450  }
451  
452  EXPORT_SYMBOL_GPL(ipc_send);

backcar 使用backcardrv ioctl 发送ipc msg

 
284  static long backcar_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
285  {
286      void __user *argp = (void __user *)arg;
287      u_long size = 0;
288      int ret = 0;
289      unsigned gpio_value = 0;
290  	struct rvc_solution_info rvc_solution;
291  #ifndef CONFIG_BACKCAR_NO_ARM2
292          wait_queue_head_t wait_queue_head;
293          DECLARE_WAITQUEUE(cur_wait_queue, current);
294  #endif
295  
296      size = (cmd & IOCSIZE_MASK) >> IOCSIZE_SHIFT;
297  
298      if (cmd & IOC_IN) {
299          if (!access_ok(VERIFY_READ, argp, size)) {
300              BACKCAR_LOG(BACKCAR_ERR, "backcar_ioctl(): error 1, so bc_failed\n");
301              return -EFAULT;
302          }
303      }
304  
305      if (cmd & IOC_OUT) {
306          if (!access_ok(VERIFY_WRITE, argp, size)) {
307              BACKCAR_LOG(BACKCAR_ERR, "backcar_ioctl(): error 2, so bc_failed\n");
308              return -EFAULT;
309          }
310      }
311  
312  	switch(cmd){
313  		case IOCTL_FSC_NOTIFY_APP_READY:
314  			BACKCAR_LOG(BACKCAR_INFO,
315  						"execute IOCTL_FSC_NOTIFY_APP_READY ioctl\n");
316  			memset(&rvc_solution, 0, sizeof(struct rvc_solution_info));
317  			if (!videoin_get_rvc_solution_info(&rvc_solution)) {
318  				BACKCAR_LOG(BACKCAR_WARNING,
319  							"get rvc solution info from metazone fail!");
320  			}
321  			if (RVC_SOLUTION_ARM2_ONLY != rvc_solution.solution) {
322  				BACKCAR_LOG(BACKCAR_INFO, "wait arm2 exit start\n");
323  				mutex_lock(&g_ioctl_mutex);
324  				if (gArm2AlreadyExit) {
325  					BACKCAR_LOG(BACKCAR_INFO, "wait arm2 already exit done\n");
326  					mutex_unlock(&g_ioctl_mutex);
327  					break;
328  				}
329  #ifndef CONFIG_BACKCAR_NO_ARM2
330  				init_waitqueue_head(&wait_queue_head);
331  				add_wait_queue(&wait_queue_head, &cur_wait_queue);
332  				g_ioctlwaitq = &wait_queue_head;
333  				set_current_state(TASK_INTERRUPTIBLE);
334  
335  				BACKCAR_LOG(BACKCAR_INFO, "Inform Arm2, Arm1 Backcar apk is ready\n");
336  				BACKCAR_LOG(BACKCAR_INFO, "send arm1 ready to arm2 start\n");
337  				ipc_send_msg(cIpcMsgSendArm1BCReady);
338  				BACKCAR_LOG(BACKCAR_INFO, "send arm1 ready to arm2 end\n");
339  				BACKCAR_LOG(BACKCAR_INFO, "wait arm2 interrupt before schedule\n");
340  				schedule();
341  				BACKCAR_LOG(BACKCAR_INFO, "wait arm2 interrupt after schedule\n");
342  
343  				if (signal_pending(current)) {
344  					BACKCAR_LOG(BACKCAR_WARNING, "interrupted by system signal\n");
345  					ret = -ERESTARTSYS;
346  				} else {
347  					BACKCAR_LOG(BACKCAR_INFO, "wait arm2 interrupt done\n");
348  				}
349  
350  				remove_wait_queue(&wait_queue_head, &cur_wait_queue);
351  				set_current_state(TASK_RUNNING);
352  				g_ioctlwaitq = NULL;
353  				gArm2AlreadyExit = true;
354  #ifdef CONFIG_MEMBLK_RELEASE_POLICY
355  				backcar_free_viss_reserve_mem("autochips,backcar_rt");
356  				backcar_free_viss_reserve_mem("autochips,backcar_mrf");
357  #endif
358  #endif //CONFIG_BACKCAR_NO_ARM2
359  			}
360  			videoin_dma_config();
361  			BACKCAR_LOG(BACKCAR_INFO, "videoin_dma_config have successfully\n");
362  
363  			mutex_unlock(&g_ioctl_mutex);
364  			BACKCAR_LOG(BACKCAR_INFO, "wait arm2 exit done\n");
365  			break;
366          case IOCTL_BC_GPIOINIT:
367              GPIO_Init();
368              BACKCAR_LOG(BACKCAR_INFO, "init GPIO success!\n");
369              break;
370          case IOCTL_BC_DETECTGPIO:
371              gpio_value = GPIO_Get_value();
372              ret = copy_to_user(argp, &gpio_value, sizeof(gpio_value));
373              if (ret != 0) {
374                  BACKCAR_LOG(BACKCAR_ERR, "copy gpio status to userspace bc_failed\n");
375              }
376              break;
377          case IOCTL_BC_FORCE_STOP_ARM2:
378              backcar_force_stop_arm2();
379              break;
380          case IOCTL_BC_NOTIFY_VBA_EXIT:
381  #ifndef CONFIG_BACKCAR_NO_ARM2
382              BACKCAR_LOG(BACKCAR_INFO, "Send MSG_IPC %s\n", cIpcMsgSendVbaExit);
383              ret = ipc_send_msg(cIpcMsgSendVbaExit);
384              if (ret < 0) {
385                  BACKCAR_LOG(BACKCAR_ERR, "IPC Request Send failed\n");
386              }
387  #endif
388              break;
389          case IOCTL_BC_NOTIFY_AUDIO_MUTE:
390  #ifndef CONFIG_BACKCAR_NO_ARM2
391              {
392                  unsigned mute = 0;
393                  const char *muteMsg = NULL;
394                  if (get_user(mute, (unsigned __user *)arg)) {
395                      BACKCAR_LOG(BACKCAR_INFO, "get_user error\n");
396                      ret = -EFAULT;
397                      break;
398                  }
399                  muteMsg = mute ? cIpcMsgRcvArm2AudioMute : cIpcMsgRcvArm2AudioUnMute;
400                  BACKCAR_LOG(BACKCAR_INFO, "Send MSG_IPC %s\n", muteMsg);
401                  ret = ipc_send_msg(muteMsg);
402                  if (ret < 0) {
403                      BACKCAR_LOG(BACKCAR_ERR, "IPC Request Send failed\n");
404                  }
405              }
406  #endif
407              break;
408          case IOCTL_MCU_BC_START_SUCCESS:
409              if (!gpio_is_valid(backcar_mcu_gpio_num)) {
410                  BACKCAR_LOG(BACKCAR_ERR, "get backcar mcu notify gpio number bc_failed\n");
411              } else {
412                  gpio_direction_output(backcar_mcu_gpio_num, BACKCAR_NOTIFY_MCU_GPIO_HIGH);
413                  gpio_set_value_cansleep(backcar_mcu_gpio_num, BACKCAR_NOTIFY_MCU_GPIO_HIGH);
414                  BACKCAR_LOG(BACKCAR_INFO, "MCU Test: current gpio number = %d, gpio value = %d\n", backcar_mcu_gpio_num, gpio_get_value(backcar_mcu_gpio_num));
415              }
416              break;
417          case IOCTL_MCU_BC_START_STOP:
418              if (!gpio_is_valid(backcar_mcu_gpio_num)) {
419                  BACKCAR_LOG(BACKCAR_ERR, "get backcar mcu notify gpio number bc_failed\n");
420              } else {
421                  gpio_direction_output(backcar_mcu_gpio_num, BACKCAR_NOTIFY_MCU_GPIO_LOW);
422                  gpio_set_value_cansleep(backcar_mcu_gpio_num, BACKCAR_NOTIFY_MCU_GPIO_LOW);
423                  BACKCAR_LOG(BACKCAR_INFO, "MCU Test: current gpio number = %d, gpio value = %d\n", backcar_mcu_gpio_num, gpio_get_value(backcar_mcu_gpio_num));
424              }
425              break;
426  		case IOCTL_GET_RVC_DATA_FROM_ARM2:
427  		case IOCTL_SET_RVC_DATA_TO_ARM2:
428  #ifndef CONFIG_BACKCAR_NO_ARM2
429  		{
430  			struct rvc_data data;
431  			int wait_time = 0;
432  			mutex_lock(&g_ioctl_mutex);
433  			memset(&data, 0, sizeof(struct rvc_data));
434  			if (copy_from_user(&data, argp, sizeof(struct rvc_data ))) {
435  				BACKCAR_LOG(BACKCAR_ERR, "copy_from_user error\n");
436  				ret = -EFAULT;
437  				mutex_unlock(&g_ioctl_mutex);
438  				break;
439  			}
440  			if ((0 == strcmp(data.ipc_key, RVC_IPC_KEY_GET_DATA)) ||
441  				(0 == strcmp(data.ipc_key, RVC_IPC_KEY_SET_DATA))) {
442  				BACKCAR_LOG(BACKCAR_DEBUG, "ipc_key(%s), data_type(%d)\n", data.ipc_key, data.type);
443  			} else {
444  				BACKCAR_LOG(BACKCAR_ERR, "ipc_key(%s) is invalid\n", data.ipc_key);
445  				ret = -EFAULT;
446  				mutex_unlock(&g_ioctl_mutex);
447  				break;
448  			}
449  			memset(&g_responsed_rvc_data, 0, sizeof(struct rvc_data));
450  			ret = ipc_send_msg((const char *)&data);
451  			if (ret < 0) {
452  				BACKCAR_LOG(BACKCAR_ERR, "IPC Request Send failed\n");
453  				ret = -EFAULT;
454  				mutex_unlock(&g_ioctl_mutex);
455  				break;
456  			}
457  			// wait arm2 response
458  			msleep(50);
459  			while (0 != strcmp(g_responsed_rvc_data.ipc_key, RVC_IPC_KEY_ARM2_RESPOND)
460  				&& (wait_time < 500)) {
461  				msleep(20);
462  				wait_time += 20;
463  			}
464  			if (500 == wait_time) {
465  				BACKCAR_LOG(BACKCAR_ERR, "wait arm2 response time out\n");
466  				ret = -EFAULT;
467  				mutex_unlock(&g_ioctl_mutex);
468  				break;
469  			}
470  
471  			BACKCAR_LOG(BACKCAR_DEBUG, "get rvc data success:ipc_key:%s, type:%d, data[%d, %d, %d, %d]\n",
472  				g_responsed_rvc_data.ipc_key, g_responsed_rvc_data.type,
473  				g_responsed_rvc_data.data[0], g_responsed_rvc_data.data[1],
474  				g_responsed_rvc_data.data[2], g_responsed_rvc_data.data[3]);
475  			if (g_responsed_rvc_data.type != data.type) {
476  				BACKCAR_LOG(BACKCAR_ERR, "data type is not match. request(%d), receive(%d)\n",
477  					data.type, g_responsed_rvc_data.type);
478  				ret = -EFAULT;
479  				mutex_unlock(&g_ioctl_mutex);
480  				break;
481  			}
482  
483  			if (copy_to_user(argp, &g_responsed_rvc_data, sizeof(struct rvc_data))) {
484  				BACKCAR_LOG(BACKCAR_ERR, "copy_to_user error\n");
485  				ret = -EFAULT;
486  				mutex_unlock(&g_ioctl_mutex);
487  				break;
488  			}
489  			mutex_unlock(&g_ioctl_mutex);
490  		}
491  #endif
492  			break;
493  		default:
494  			BACKCAR_LOG(BACKCAR_WARNING, "this ioctl(%d) is not supported", cmd);
495  			ret = -1;
496  			break;
497  	}
498  
499  	return ret;
500  }

vendor/autochips/proprietary/hardware/backcar/backcar/src/BackcarImpl.cpp

bool BackcarImpl::waitArm2Exit()
309  {
310      BACKCAR_LOGI("enter");
311      unsigned int status = 0;
312      int ret = ::ioctl(mBackcarFd, IOCTL_FSC_NOTIFY_APP_READY, &status);
313      if (ret < 0) {
314          BACKCAR_LOGE("execute IOCTL_FSC_NOTIFY_APP_READY failed, and error message is %s",strerror(errno));
315          return false;
316      }
317      BACKCAR_LOGI("leave arm2 status is %d", status);
318  
319      return true;
320  }

RVC  hal 层

/autochips/proprietary/hardware/backcar/backcar/src/BackcarImpl.cpp

define BACKCAR_DRIVER_NAME "/dev/backcardrv"


54  BackcarImpl::BackcarImpl():
55      mBackcarFd(-1),
56      mArm2Status(ARM2_RVC_STATUS_RUNNING),
57      mBackcarEnable(0),
58      mProcessThread(nullptr),
59      mRvcDataThread(nullptr)
60  {
61      BACKCAR_LOGI("enter");
62      Mutex::Autolock _l(mLock);
        //open  backcardrv
63      mBackcarFd = ::open(BACKCAR_DRIVER_NAME, O_RDWR | O_NONBLOCK);
64      if (mBackcarFd < 0) {
65          BACKCAR_LOGE("open %s fail. %s", BACKCAR_DRIVER_NAME, strerror(errno));
66          return;
67      } else {
68          BACKCAR_LOGI("open success %d ", mBackcarFd);
69      }
70      //获取RVC的metazone的配置信息
71      mRvcSolution = getRVCSolutionType();
72      switch (mRvcSolution) {
73      case RVC_SOLUTION_ARM2_WITH_ARM1:
74          mProcessThread = new FunctionThread(std::bind(&BackcarImpl::mainThreadLoop,                                                     this));
75          mProcessThread->run("mainThreadLoop");
76          BACKCAR_LOGI("rvc solution is arm1 with arm2 rvc. run mainThreadLoop");
77          break;
78      case RVC_SOLUTION_AVM:
79          buttonInit();
80          mArm2Status = ARM2_RVC_STATUS_EXIT;
81          mProcessThread = new FunctionThread(std::bind(&BackcarImpl::mainThreadLoop,                                                     this));
82          mProcessThread->run("mainThreadLoop");
83          BACKCAR_LOGI("rvc solution is avm. run mainThreadLoop");
84          break;
85      case RVC_SOLUTION_ARM2_ONLY:
86          mRvcDataThread = new FunctionThread(std::bind(&BackcarImpl::rvcDataThreadLoop,                                                 this));
87          mRvcDataThread->run("rvcDataThreadLoop");
88          BACKCAR_LOGI("rvc solution is arm2 rvc only. run rvcDataThreadLoop");
89          break;
90      default:
91          break;
92      }
93      BACKCAR_LOGI("leave");
94  }

通过metazone 获取METAZONE_BACKCAR_VDO_SOURCE的值

734  int BackcarImpl::getRVCSolutionType()
735  {
736      unsigned int metazoneValue = 0;
737      int rvcSolution = -1;
738      if (MZ_SUCCESS == ::MetaZone_Init()) {
739          if (MZ_SUCCESS == ::MetaZone_Read(METAZONE_BACKCAR_VDO_SOURCE,                                                                  &metazoneValue)) {
740              auto source = (unsigned char *)(&metazoneValue);
741              rvcSolution = source[METAZONE_RVC_SOLUTION_BYTE_INDEX];
742          } else {
743              BACKCAR_LOGW("MetaZone_Read(METAZONE_SOURCE_MODE) fail.");
744          }
745          ::MetaZone_Deinit();
746      } else {
747          BACKCAR_LOGE("metazone init failed\n");
748      }
749  
750      BACKCAR_LOGI("get rvc solution type(%d) success", rvcSolution);
751      return rvcSolution;
752  }
753  

通过backcardrv文件节点获取msg

#define SELECT_TIMEOUT 5000 //ms
191  bool BackcarImpl::rvcDataThreadLoop()
192  {
193      int ret = 0;
194      RVCData halData;
195      struct rvc_data drvData;
196      struct timeval tv;
197      fd_set rd_set;
198  
199      do {
200          memset(&halData, 0, sizeof(RVCData));
201          memset(&drvData, 0, sizeof(struct rvc_data));
202          memset(&tv, 0, sizeof(tv));
203          tv.tv_sec = SELECT_TIMEOUT / 1000;
204          tv.tv_usec = (SELECT_TIMEOUT % 1000) * 1000;
205          FD_ZERO(&rd_set);
206          FD_SET(mBackcarFd, &rd_set);
207          if (!FD_ISSET(mBackcarFd, &rd_set)) {
208              BACKCAR_LOGE("FD_ISSET fail. error %s", strerror(errno));
209              break;
210          }
211          ret = select(mBackcarFd + 1, &rd_set, nullptr, nullptr, &tv);
212          if (ret < 0) {
213              BACKCAR_LOGE("select fail. error %s", strerror(errno));
214          } else if (ret == 0) {
215              BACKCAR_LOGD("select timeout. ");
216          } else {
217              read(mBackcarFd, (char *)&drvData, sizeof(struct rvc_data));
218              if (0 == strcmp(drvData.ipc_key, RVC_IPC_KEY_ARM2_NOTIFY)) {
219                  halData.type = (RVCDataType)drvData.type;
220                  halData.data[0] = drvData.data[0];
221                  halData.data[1] = drvData.data[1];
222                  halData.data[2] = drvData.data[2];
223                  halData.data[3] = drvData.data[3];
224                  BACKCAR_LOGI("type: %d, data: [%d, %d, %d, %d]", drvData.type,                                 drvData.data[0], drvData.data[1], drvData.data[2], drvData.data[3]);
225                  rvcDataChangeNotify(halData);
226                  if (RVC_DATA_RVC_STATUS == drvData.type) {
227                      mBackcarEnable = drvData.data[0];
228                  }
229              }
230          }
231          usleep(1000000 / 100);
232      } while (0);
233  
234      return true;
235  }

 arm 2 上的rtos 获取倒车的gpio的信息通过backcar驱动解析后将event事件挂在notify_event_list

 #ifndef CONFIG_BACKCAR_NO_ARM2
202  static int backcar_ipc_receive_thread(void *data)203  {
204          int ret = 0;
205          char arm2_msg[ipcMSG_LENGTH] = {0,};
206          struct rvc_data received_rvc_data;
207          struct arm2_rvc_event *event = NULL;
208          BACKCAR_LOG(BACKCAR_INFO, "backcar_ipc_receive_thread start\n");
209  
210          do {
211                  if (!g_ipc_receive_chan) {
212                          BACKCAR_LOG(BACKCAR_INFO, "ipc receive chan is null, request                                                     chan first.\n");
213                          g_ipc_receive_chan = ipc_request_chan_detailed(CORE_VEHICLE,                                                 MSGRECV, g_ipc_arm2_rvc, g_ipc_arm1_ap);
214                          if (!g_ipc_receive_chan) {
215                                  BACKCAR_LOG(BACKCAR_ERR, "ipc request receive chan                                                 fail\n");
216                                  continue;
217                          }
218                  }
219  
220                  memset(arm2_msg, 0, sizeof(arm2_msg));
221                  ret = ipc_receivemsg(g_ipc_receive_chan, arm2_msg, ipcMSG_LENGTH);
222                  if (ret < 0) {
223                          BACKCAR_LOG(BACKCAR_ERR, "ipc receive fail %d\n", ret);
224                          continue;
225                  }
226  
227                  BACKCAR_LOG(BACKCAR_DEBUG, "ipc receive arm2_msg %s\n", arm2_msg);
228                  if (!strncmp(cIpcMsgRcvArm2BCExit, arm2_msg, ipcMSG_LENGTH)) {
229                          BACKCAR_LOG(BACKCAR_INFO, "backcar receive msg %s success \n",                                             cIpcMsgRcvArm2BCExit);
230                          if (NULL != g_ioctlwaitq) {
231                                  wake_up(g_ioctlwaitq);
232                          } else {
233                          BACKCAR_LOG(BACKCAR_WARNING, "g_ioctl waitq has been waked.                                                 but not by arm2 msg\n");
234                          }
235                  } else {
236                          memset(&received_rvc_data, 0, sizeof(struct rvc_data));
237                          memcpy(&received_rvc_data, arm2_msg, ipcMSG_LENGTH);
238                          if (0 == strcmp(received_rvc_data.ipc_key,                                                                     RVC_IPC_KEY_ARM2_RESPOND)) {
239                                  BACKCAR_LOG(BACKCAR_DEBUG, "RVC_IPC_KEY_ARM2_NOTIFY                                             received. type = %d, data[0]= %d\n",
240                                                  received_rvc_data.type,                                                                 received_rvc_data.data[0]);
241                                  memset(&g_responsed_rvc_data, 0, sizeof(struct                                                         rvc_data));
242                                  memcpy(&g_responsed_rvc_data, arm2_msg, ipcMSG_LENGTH);
243                          } else if (0 == strcmp(received_rvc_data.ipc_key,                                                                 RVC_IPC_KEY_ARM2_NOTIFY)) {
                                     //解析小核 arm2 RTOS的 ipc msg
244                                  BACKCAR_LOG(BACKCAR_INFO, "RVC_IPC_KEY_ARM2_NOTIFY                                                         received. type = %d, data[0]= %d\n",
245                                                  received_rvc_data.type,                                                                     received_rvc_data.data[0]);
246                                  event = kzalloc(sizeof(*event), GFP_KERNEL);
247                                  if (!event) {
248                                          BACKCAR_LOG(BACKCAR_ERR, "kzalloc failed \n");
249                                          break;
250                                  }
                                     //将arm2 msg 填充event data 
251                                  memset(&(event->data), 0, sizeof(struct rvc_data));
252                                  memcpy(&(event->data), arm2_msg, ipcMSG_LENGTH);
253                                  mutex_lock(&g_event_manager.event_mutex);
                                     //将event list 挂到notify_event_list
254                                  list_add_tail(&event->list,                                                                                 &g_event_manager.notify_event_list);
255                                  mutex_unlock(&g_event_manager.event_mutex);
256                                  wake_up(&g_event_manager.event_queue_wait);
257                          } else {
258                                  BACKCAR_LOG(BACKCAR_INFO, "ipc not receive request msg \n");
259                                  break;
260                          }
261                  }
262                  msleep(1);
263          } while (!kthread_should_stop());
264  
265          BACKCAR_LOG(BACKCAR_INFO, "backcar_ipc_receive_thread leave \n");
266          return 0;
267  }
268  #endif

arm ap 侧使用驱动read的接口获取backcardrv arm2 的msg

static ssize_t backcar_read(struct file *file, char __user *buf, size_t count, loff_t *ppos)
534  {
535          int ret = 0;
536          struct arm2_rvc_event *event = NULL;
537          if (!access_ok(VERIFY_WRITE, buf, count))
538                  return -EFAULT;
539  
540          mutex_lock(&g_event_manager.event_mutex);
541          if (!list_empty(&g_event_manager.notify_event_list)) {
542                  event = list_first_entry(&g_event_manager.notify_event_list, struct                                                 arm2_rvc_event, list);
543                  if (!event) {
544                          BACKCAR_LOG(BACKCAR_ERR, "event is null.\n");
545                          mutex_unlock(&g_event_manager.event_mutex);
546                          return -EFAULT;
547                  }
548                  //获取rvc event data
549                  BACKCAR_LOG(BACKCAR_INFO, "event read: type(%d) ", event->data.type);
550                  if (copy_to_user(buf, &event->data, sizeof(struct rvc_data))) {
551                          BACKCAR_LOG(BACKCAR_ERR, "copy_to_user error\n");
552                          ret = -EFAULT;
553                  }
554                  list_del(&event->list);
555                  kfree(event);
556          }
557          mutex_unlock(&g_event_manager.event_mutex);
558  
559          return ret;
560  }

hal层rvcDataChangeNotify将回调java注册callback函数


258  void BackcarImpl::rvcDataChangeNotify(RVCData rvcData)
259  {
260      BACKCAR_LOGI("enter. type: %d, data: [%d, %d, %d, %d]",
261                  rvcData.type, rvcData.data[0], rvcData.data[1], rvcData.data[2],                             rvcData.data[3]);
262      std::map<const sp<IBackcarCallback>,std::vector<EventType>>::iterator cb_iter;
263  
264      for (cb_iter = mCallbackMap.begin(); cb_iter != mCallbackMap.end(); cb_iter++) {
265          const sp<IBackcarCallback>& callback = cb_iter->first;
266          std::vector<EventType>& evts = cb_iter->second;
267          for (std::vector<EventType>::iterator iter = evts.begin(); iter != evts.end();             iter++) {
268              if (*iter == EventType::RVC_DATA_CHANGE) {
                     //回调java层callback的rvcDataChangeNotify
269                  auto callbackRet = callback->rvcDataChangeNotify(rvcData);
270                  if (!callbackRet.isOk()) {
271                      BACKCAR_LOGE("Callback rvcDataChangeNotify error");
272                  }
273                  break;
274              }
275          }
276      }
277      BACKCAR_LOGI("leave");
278  }

 java层backcar service 注册hal 回调函数

vendor/autochips/proprietary/frameworks/base/backcar/java/com/autochips/backcar/BackCar.java

     /**
191       * Construct for RVC
192       * @param looper handler using this looper
193       */
194      public BackCar(Looper looper) {
195          Log.d(TAG, "RVC() enter");
196  
197          if (null == looper) {
198              looper = Looper.myLooper();
199              if (null == looper) {
200                  looper = Looper.getMainLooper();
201              }
202          }
203  
204          mHandler = new EventHandler(looper);
205          mCallback = new BackcarCallback();
206          mDeathRecipient = new DeathRecipient();
207  
208          try {
209              mService = IBackcar.getService();
210              mService.linkToDeath(mDeathRecipient, 0);
211          } catch (RemoteException e) {
212              Log.e(TAG, "getService() failure");
213              e.printStackTrace();
214              mService = null;
215          }
216  
217          Log.d(TAG, "RVC() leave");
218      }

/saic_cn202sr/vendor/autochips/proprietary/frameworks/base/backcar/java/com/autochips/backcar/BackCar.java
     /**
221       * Set event listener
222       * @param listener listener object, can be null
223       * @param evts all event type for listening
224       * @return true is success, false is fail.
225       */
226      public boolean setListener(Listener listener, ArrayList<Integer> evts) {
227          Log.d(TAG, "setListener() enter");
228  
229          if (null == mService) {
230              Log.e(TAG, "mService = null");
231              return false;
232          }
233  
234          mListener = listener;
235          mEvts = evts;
236          int status = Status.FAILURE;
237  
238          try {
239              if ((null != mListener) && (null != evts)){
240                  mService.registerEventCallback_V2(mCallback, evts, new                                                                IBackcar.registerEventCallback_V2Callback() {
241                          @Override
242                          public void onValues(int Status, long callbackId) {
243                              mCallbackId[0] = callbackId;
244                          }
245                      });
246              } else {
247                  status = mService.unregisterEventCallback_V2(mCallbackId[0]);
248              }
249              status = Status.SUCCESS;
250          } catch (RemoteException e) {
251              Log.e(TAG, "call registerEventCallback()/unregisterEventCallback()                                     failure");
252              e.printStackTrace();
253              status = Status.FAILURE;
254          }
255  
256          Log.d(TAG, "setListener() leave");
257          return (Status.SUCCESS == status);
258      }
259  


445  Return<void> BackcarImpl::registerEventCallback_V2(const sp<IBackcarCallback>&                     callback, const hidl_vec<EventType>& evts, registerEventCallback_V2_cb                     _hidl_cb) {
446      Mutex::Autolock _l(mLock);
447      BACKCAR_LOGI("enter callback = %p, evts.size() = %d", callback.get(),                                                                             (int)evts.size());
448  
449      if (mBackcarFd < 0) {
450          _hidl_cb(Status::FAILURE, 0);
451          return Void();
452      }
453  
454      if (nullptr == callback.get() || 0 == evts.size()) {
455          BACKCAR_LOGE("Invalid param callback = %p, evts.size() = %d", callback.get(),                                                                            (int)evts.size());
456          _hidl_cb(Status::FAILURE, 0);
457          return Void();
458      }
459  
460      mCallbackMap[callback] = evts;
461  
462      callback->linkToDeath(this, 888);
463  
464      afterRegisterRun(callback);
465  
466      BACKCAR_LOGI("leave");
467      _hidl_cb(Status::SUCCESS, (uint64_t)callback.get());
468      return Void();
469  }

344  void BackcarImpl::afterRegisterRun(const sp<IBackcarCallback>& callback)
345  {
346      BACKCAR_LOGI("enter");
347      if (ARM2_RVC_STATUS_EXIT == mArm2Status) {
348          std::vector<EventType>& evts = mCallbackMap[callback];
349          for (std::vector<EventType>::iterator iter = evts.begin(); iter != evts.end();             iter++) {
350              if (*iter == EventType::ARM2EXIT) {
351                  auto callbackRet = callback->eventNotify(EventType::ARM2EXIT, 0, 0, 0);
352                  if (!callbackRet.isOk()) {
353                      BACKCAR_LOGE("Callback eventNotify error");
354                  }
355                  break;
356              }
357          }
358      }
359  
360      switch (mRvcSolution) {
361      case RVC_SOLUTION_ARM2_WITH_ARM1:
362      case RVC_SOLUTION_AVM:
363          if (mBackcarEnable) {
364              BACKCAR_LOGI("rvc button already on");
365              std::vector<EventType>& evts = mCallbackMap[callback];
366              for (std::vector<EventType>::iterator iter = evts.begin(); iter !=                                             evts.end(); iter++) {
367                  if (*iter == EventType::BC) {
368                      auto callbackRet = callback->eventNotify(EventType::BC, 1, 0, 0);
369                      if (!callbackRet.isOk()) {
370                          BACKCAR_LOGE("Callback eventNotify error");
371                      }
372                      break;
373                  }
374              }
375          }
376          break;
377      case RVC_SOLUTION_ARM2_ONLY:
378          {
379              RVCData halData;
380              if (__getRVCDataFromArm2(RVCDataType::RVC_DATA_RVC_STATUS, halData)) {
381                  if (1 == halData.data[0]) {
382                      rvcDataChangeNotify(halData);
383                  }
384              }
385          }
386          break;
387      default:
388          break;
389      }
390  
391      BACKCAR_LOGI("leave");
392  }

backcar service  callbac函数 sendmsg EVENT_TYPE_RVC_DATA_CHANGE给app 

  private class BackcarCallback extends IBackcarCallback.Stub {
169          public void eventNotify(int evt, int param1, int param2, int param3) {
170              Log.d(TAG, "eventNotify() enter evt = " + evt + ", param1 = " + param1);
171              mHandler.sendMessage(Message.obtain(mHandler, evt, param1, param2));
172              Log.d(TAG, "eventNotify() leave");
173          }
174  
175          public void rvcDataChangeNotify(vendor.autochips.hardware.backcar.V1_0.RVCData                 hidlRVCData) {
176              Log.d(TAG, "rvcDataChangeNotify() enter rvcDataType =" + hidlRVCData.type                             + ", data = [" + hidlRVCData.data[0]
177                  + ", " + hidlRVCData.data[1] + ", " + hidlRVCData.data[2] + ", " +                                 hidlRVCData.data[3] + "]" );
178              mHandler.sendMessage(Message.obtain(mHandler, EVENT_TYPE_RVC_DATA_CHANGE,                     hidlRVCData.type, hidlRVCData.data[0]));
179              Log.d(TAG, "rvcDataChangeNotify() leave");
180          }
181      }

触发app start RVC

/vendor/autochips/proprietary/packages/apps/AtcCamera/src/com/autochips/camera/CameraService.java
public class CameraService extends Service{
38      private static final String TAG = "CameraService";
39  
40      private CameraServiceImpl mCameraServiceImpl;
41  
42      private static final String ACTION_QB_OFF = "autochips.intent.action.QB_POWEROFF";
43      private static final String ACTION_QB_ON = "autochips.intent.action.QB_POWERON";
44      private static final String ACTION_PREQB_ON =                            
        "autochips.intent.action.PREQB_POWERON";
45      private static final String ACTION_PREQB_OFF =         
        "autochips.intent.action.PREQB_POWEROFF";
46      private static final String NOTIFICATION_CHANNEL_ID_SERVICE = 
        "com.autochips.camera.CameraService";
47      private static final int NOTIFICATION_ID = 105;
48      private static final int BC_TYPE_ADDR = 
        MetazoneIndex.DwordIndex.METAZONE_BACKCAR_VDO_SOURCE;
49      private static final int ADDR_RVC_CAMERA_ID =                                   
        MetazoneIndex.DwordIndex.METAZONE_RVC_AVM_CAMERA_ID;
50      private static final int TYPE_RVC = 0;
51  
52      private BackCar mBackcar;
53      private String mCurrentBackcarCameraId;
54      private boolean mIsArm2Exited;
55      private boolean mIsQBOn = true;
56      private boolean mNeedStartBackcarAfterQBOn;
57      private boolean mHasShownTouchInputFilterView;
58      private boolean mhasEnableBackcarAudio = false;
59      private boolean mIsBackcarOn = false;
60      private boolean mIsRVCMode = false;
61      private int mCurrentUserId = UserHandle.myUserId();
62      private final Thread.UncaughtExceptionHandler mDefaultUncaughtExceptionHandler =                 Thread.getDefaultUncaughtExceptionHandler();
63      private Handler mHandler = new Handler();
64  
65      private BackCar.Listener mListenerSignal = new BackCar.Listener() {
66          public void onEvent(int event, int param1, int param2) {
67              LogUtil.d(TAG,"onSignal - event:" + event);
68              if (BackCar.EVENT_TYPE_BC == event) {
69                  if (param1 != 0) {
70                      LogUtil.i(TAG,"onSignal():BACKCAR_START");
71                      if (!mhasEnableBackcarAudio) {
72                          mCameraServiceImpl.enableBackcarAudio();
73                          mhasEnableBackcarAudio = true;
74                      }
75  
76                      if (!mIsArm2Exited && !mHasShownTouchInputFilterView) {
77                          mCameraServiceImpl.showTouchInputFilterView();
78                          mHasShownTouchInputFilterView = true;
79                          return;
80                      }
81                      if (!mIsQBOn) {
82                          mNeedStartBackcarAfterQBOn = true;
83                          LogUtil.d(TAG, "start backcar later after qb on");
84                          return;
85                      }
86                      if (mCurrentUserId == UserHandle.myUserId() &&                                                     getBackcarCameraId()) {
87                          mCameraServiceImpl.startBackcar(mCurrentBackcarCameraId);
88                      }
89                      mIsBackcarOn = true;
90                  }else {
91                      LogUtil.i(TAG,"onSignal():BACKCAR_STOP");
92                      if (mhasEnableBackcarAudio) {
93                          mCameraServiceImpl.disableBackcarAudio();
94                          mhasEnableBackcarAudio = false;
95                      }
96  
97                      if (mNeedStartBackcarAfterQBOn) {
98                          mNeedStartBackcarAfterQBOn = false;
99                          LogUtil.d(TAG, "cancel stop backcar");
100                          return;
101                      }
102                      if (mCurrentBackcarCameraId != null) {
103                          mCameraServiceImpl.stopBackcar(mCurrentBackcarCameraId);
104                      }
105                      mIsBackcarOn = false;
106                  }
107              }else if (BackCar.EVENT_TYPE_ARM2EXIT == event) {
108                  mIsArm2Exited = true;
109                  if (mHasShownTouchInputFilterView) {
110                      mCameraServiceImpl.cancelTouchInputFilterView();
111                      mHasShownTouchInputFilterView = false;
112                  }
113                  mCameraServiceImpl.notifyCameraResourceAvailable();
114  
115                  if (mhasEnableBackcarAudio) {
116                      mCameraServiceImpl.disableBackcarAudio();
117                      mhasEnableBackcarAudio = false;
118                  }
119                  LogUtil.i(TAG, "exit arm2 backcar");
                  //cemera app 接收EVENT_TYPE_RVC_DATA_CHANGE
120              } else if (BackCar.EVENT_TYPE_RVC_DATA_CHANGE == event) {
121                  LogUtil.i(TAG,"param2 =" + param2);
122                  if (param2 != 0 && mIsRVCMode) {
123                      LogUtil.i(TAG,"handle ARM2 start backcar");
124                      mCameraServiceImpl.handleARM2RVCStart(mBackcar);
125                  } else {
126                      LogUtil.i(TAG,"handle ARM2 stop backcar");
127                      mCameraServiceImpl.handleARM2RVCStop();
128                  }
129              }else {
130                  LogUtil.i(TAG, "do nothing");
131              }
132          }
133      };

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值