Android 9.0 Auto及m4 core倒车逻辑--基于imx8qm

新板子car版本android系统收不到m4发送的资源释放消息,屏不亮,先分析一下逻辑关系。

 

上图就是car版本AP核和M41核之间的倒车逻辑。

 

阶段1 系统启动完毕

mek_8q.mk 63: $(IMX_DEVICE_PATH)/init_car_m4.rc:$(TARGET_COPY_OUT_VENDOR)/etc/init/hw/init.car_additional.rc 68: $(IMX_DEVICE_PATH)/init_car_no_m4.rc:$(TARGET_COPY_OUT_VENDOR)/etc/init/hw/init.car_additional.rc

也就是说vendor.all.system_server.ready代表系统启动完成。

frameworks/base/packages/SystemUI/src/com/android/systemui/SystemUIApplication.java 159:

SystemProperties.set("vendor.all.system_server.ready", "1");

 

阶段2

(1)注册vehicle_rpmsg_m4驱动

init_car_m4.rc将被触发:

on property:vendor.all.system_server.ready=1 # register the vehicle_rpmsg_m4 on raw android. write /sys/devices/platform/vehicle_rpmsg_m4/register 1 # register the vehicle_rpmsg_m4 on android running in xen. write /sys/devices/platform/passthrough/passthrough\:vehicle_rpmsg_m4/register 1

 

write /sys/devices/platform/vehicle_rpmsg_m4/register 1 注册vehicle_rpmsg_driver内核驱动。

vendor/nxp-opensource/kernel_imx/drivers/mxc/vehicle/vehicle_rpmsg_m4.c:

static struct rpmsg_driver vehicle_rpmsg_driver = {
        .drv.name       = "vehicle_rpmsg",
        .drv.owner      = THIS_MODULE,
        .id_table       = vehicle_rpmsg_id_table,
        .probe          = vehicle_rpmsg_probe,
        .callback       = vehicle_rpmsg_cb,
};
/*register ap to M4 once echo 1 > /sys/devices/platform/vehicle_rpmsg/register*/
static ssize_t register_store(struct device *dev,
'''省略'''
        unsigned long state_set = simple_strtoul(buf, NULL, 10);
        if (state_set == 1 && state_set != state) {
                err = register_rpmsg_driver(&vehicle_rpmsg_driver);
'''省略'''
        return size;
}

其中vehicle_rpmsg_cb为接收m4消息的callback函数,注册驱动成功后执行probe函数,vehicle_init_handler将VEHICLE_RPMSG_REGISTER消息发送给m4

static int vehicle_rpmsg_probe(struct rpmsg_device *rpdev)
{
    '''省略'''
        init_completion(&vehicle_rpmsg->cmd_complete);
        INIT_DELAYED_WORK(&vehicle_rpmsg->vehicle_register_work,
                                vehicle_init_handler);  重要
        schedule_delayed_work(&vehicle_rpmsg->vehicle_register_work, 0);

        return 0;
}
/* send register event to M4 core
 * M4 will release camera/display once register successfully. 
    将regster事件发送到M4核心,M4将在成功注册后释放摄像头/显示器。
 */
static void vehicle_init_handler(struct work_struct *work)
{       
        msg.header.cmd = VEHICLE_RPMSG_REGISTER;

        
        err = sc_rm_get_partition(ipc_handle, &os_part);   获取Android系统分区号
        if (err != SC_ERR_NONE) {
                pr_err("sc_rm_get_partition failed!\n");
                msg.partition_id = 0xff;
        } else {
                msg.partition_id = os_part;
        }
        /* need check whether ap have been unregistered before register the ap*/
        if (!vehicle_rpmsg->vehicle_client_registered) {
                while (vehicle_send_message(&msg, vehicle_rpmsg, true)) {  将VEHICLE_RPMSG_REGISTER消息发送给m4
                        msleep(REGISTER_PERIOD);
                }
        }
}

 

阶段3

m4接收到VEHICLE_RPMSG_REGISTER消息,释放资源,进入Android界面。

m4逻辑如下:

(1)Auto_register服务注册过程,主要用于监听Android的VEHICLE_RPMSG_REGISTER消息:

main(...)
APP_SRTM_Init();
    -->xTaskCreate(SRTM_MonitorTask, "SRTM monitor", 256U, NULL, APP_SRTM_MONITOR_TASK_PRIO, NULL);
        -->APP_SRTM_InitAutoService(void)
           -->SRTM_AutoService_Create(&autoAdapter); /* Create and register service */
           static struct _srtm_auto_adapter autoAdapter = {.registerEvent   = APP_SRTM_Auto_RegisterEvent,
                                                .unregisterEvent = APP_SRTM_Auto_UnregisterEvent,
                                                .control         = APP_SRTM_Auto_Control,
                                                .powerReport     = APP_SRTM_Auto_PowerReport,
                                                .getInfo         = APP_SRTM_Auto_GetInfo};
              --> APP_SRTM_Auto_RegisterEvent(...) 跟踪注册成功的registerEvent服务
                 -->stateMsg.reg.enroll = 0x01;    表示m4接收到了 VEHICLE_RPMSG_REGISTER消息,准备进入接下来的释放资源

 

以上表示m4接收到了 VEHICLE_RPMSG_REGISTER消息,准备进入接下来的释放资源。

(2)资源释放过程,主要是根据stateMsg.reg.enroll的数值,android注册成功后,置位标志位AUTO_UI_EVENT_BIT_STOP:

main(...)
xTaskCreate(vehicle_state_monitor_task, "VehicleMonitor"...)
    -->vehicle_state_monitor_task(void *pvParameters)
       case STATE_TYPE_ANDROID:
           android_registered_flag = stateMsg.reg.enroll;/* 1:registered, 0:unregistered */
           if (android_registered_flag)  
           {
               if (!shared_resource_free)
                /* camera resource is not occupied, stop display and release it*/
                    xEventGroupSetBits(g_xAutoUiEvent, AUTO_UI_EVENT_BIT_STOP);
           }

该线程监听到AUTO_UI_EVENT_BIT_STOP位置高,则释放资源。
xTaskCreate(rear_view_camera_task, "RearViewCamera",...)          
    -->rear_view_camera_task(void *pvParameters)
        if (eventBits & AUTO_UI_EVENT_BIT_STOP) 
        {
            APP_StopCamera();
            APP_DeinitDisplay();
            APP_AutoPassResource();   //释放资源
                --> SOC_AssignDisplayCamera(android_pt);
        }          

阶段4、5

(1)驱动回调函数接收到m4的释放信息,通过netlink将从m4接收的cmd指令信息以广播的方式传给evs服务,对应阶段6的uevent_kernel_multicast_recv函数,通知上层加载显示/摄像头驱动。

register_ready味着AP已经注册为客户机,并且已经准备好加载摄像头/显示模块。当它第一次得到驱动信号并且寄存器就绪为真时,它将加载相关的模块。

kernel_imx/drivers/mxc/vehicle/vehicle_rpmsg_m4.c

/*vehicle_rpmsg_cb is called once get rpmsg from M4*/
vehicle_rpmsg_cb(struct rpmsg_device *rpdev)
{
    if (msg->header.cmd == VEHICLE_RPMSG_REGISTER) 
    {
        vehicle_rpmsg->register_ready = true;
    }
    if (vehicle_rpmsg->register_ready) 
    {
         notice_evs_released(rpdev);
        vehicle_rpmsg->register_ready = false;
    }
    此函数是通过netlink将从m4接收的cmd指令信息以广播的方式传给evs服务,对应阶段6的uevent_kernel_multicast_recv函数,
    阶段6就是讲的上层完成解析过程及后续步骤。
    vehicle_hal_set_property(msg->statetype, msg->index,  msg->statevalue);
        -->send_usrmsg(buffer, stream.bytes_written);
           -->netlink_unicast(nlsk, nl_skb, user_pid, MSG_DONTWAIT);

}

阶段6

(1)设置系统属性 vendor.vehicle.register

vendor/nxp-opensource/imx/evs_service/evs_service.c

#define RPMSG_CAN_REGISTER "vendor.vehicle.register"
static void
handle_events(int uevent_fd)
{
    char msg[UEVENT_MSG_LEN+2];
    n = uevent_kernel_multicast_recv(uevent_fd, msg, UEVENT_MSG_LEN);
    cp = msg;
    ...省略...
    while (*cp) {
        if (!strncmp(cp, "STATE=VEHICLE_RPMSG_EVENT=0", strlen("STATE=VEHICLE_RPMSG_EVENT=0"))) 
        {
            if (property_set(RPMSG_CAN_EVENT, "0") < 0)
                ALOGE("%s: could not set property RPMSG_CAN_EVENT", __FUNCTION__);
        } 
        else if (!strncmp(cp, "STATE=VEHICLE_RPMSG_EVENT=1", strlen("STATE=VEHICLE_RPMSG_EVENT=1"))) {
            if (property_set(RPMSG_CAN_EVENT, "1") < 0)
                ALOGE("%s: could not set property RPMSG_CAN_EVENT", __FUNCTION__);
        } 
        else if (!strncmp(cp, "STATE=VEHICLE_RPMSG_REGISTER=0", strlen("STATE=VEHICLE_RPMSG_REGISTER=0"))) {
            if (property_set(RPMSG_CAN_REGISTER, "0") < 0)
                ALOGE("%s: could not set property RPMSG_CAN_REGISTER", __FUNCTION__);
        } 
        else if (!strncmp(cp, "STATE=VEHICLE_RPMSG_REGISTER=1", strlen("STATE=VEHICLERPMSG_REGISTER=1"))) {
            if (property_set(RPMSG_CAN_REGISTER, "1") < 0)
                ALOGE("%s: could not set property RPMSG_CAN_REGISTER", __FUNCTION__);
        }
     ...省略...

(2)启动boot_completed_core_sh(setup.core.cfg驱动)

/device/fsl/imx8q/mek_8q/init_car_m4.rc

on property:vendor.vehicle.register=1 start boot_completed_core_sh

init_car.rc

service boot_completed_core_sh /vendor/bin/init.insmod.sh /vendor/etc/setup.core.cfg vendor.all.setup_core.ready
    class main
    user root
    group root system
    disabled
    oneshot
    
 on property:vendor.all.setup_core.ready=1
    start boot_completed_main_sh
   start selinuxswitch
   
service boot_completed_main_sh /vendor/bin/init.insmod.sh /vendor/etc/setup.main.cfg vendor.all.setup_main.ready
    class main
    user root
    group root system
    disabled
    oneshot
    
on property:vendor.all.setup_main.ready=1
    # Trigger start adbd service
    start usbd
    start zygote_late

以上的意思是用init.insmod.sh脚本安装setup.core.cfg里面的模块,然后将vendor.all.setup_core.ready置为1,然后insmod setup.main.cfg中的模块,最后开启adbd服务。

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值