【SemeDrive】【X9HP】【PTG4.3】Hands-on_X9HP_Safety_fastrvc 功能使用說明

前言:以下為芯馳 X9 safety domain 的 fastrvc 快啟倒車影像 demo 的使用方法和代碼解析,以下實驗現象基於 X9HP PTG4.3。


一、VDSP(CV engine)

 

該引擎為 X9 上一顆獨立晶片,並且擁有獨立的 SRAM、CPU 以確保其性能。芯馳還為其提供了專用固件以確保該應用擁有完整疊代的能力。在使用 vdsp 進行圖像處理時,CV Engine (VDSP) 有以下部分需要先加載至對應 RAM 處:
  • vdsp.elf:固件為該引擎獨立的運行固件,由芯馳提供,PTG4.3 中位於 SDK 的 freertos_safety/res/early_app/ 下。初始化時 CPU 會將該固件加載至約定地址處,之後會啟動引擎以運行固件。
  • MappingTable.bin:映射參數表,搭載圖像處理的參數,加載到 vdsp sharing memory
以上轉載《SemiDrive_X9_EarlyAPP描述_V1.1 》,原文用於描述 fastavm,除算法部分不同外,所用圖像處理引擎 vsdp 相同。


二、代碼路徑


源碼:

freertos_safety/application/early_app/fastrvc/src/fast_rvc.c

固件資源:

freertos_safety/res/early_app/fastavm/vdsp.elf freertos_safety/res/early_app/fastavm/MappingTable.bin

倒車軌跡圖片資源:

freertos_safety/res/early_app/fastavm/bp.png freertos_safety/res/early_app/fastavm/angle_0.png freertos_safety/res/early_app/fastavm/angle_1.png freertos_safety/res/early_app/fastavm/angle_2.png

 



三、代碼解析

整個 fastrvc 功能由三個線程完成:fast_rcv_show_task,fast_rcv_detect_task,fast_rcv_lvgl_task

fast_rcv_show_task 後視攝像頭圖像顯示

  1. 初始化攝像頭,並設置顯示相關的配置。CAM_ID 要根據不同的情況設置不同的值。
  2. 初始化 g2d
  3. 判斷是否開啟 vdsp。默認開啟,初始化 VDSP(CV engine) 視覺引擎
  4. Android 未啟動或車輛處於後退狀態時,進行圖像顯示車輛處於後退狀態時,使用 g2d + vdsp(如果未開啟 vdsp,則僅使用 g2d) 對圖像進行處理再顯示。

以下為線程大致框架,篇幅有限,省略代碼保留大致流程:

static int fast_rcv_show_task(void *args) {
    int ret = 0;
    int frm_cnt = 0;
    u8 cam_id = 0;
    uint32_t buf_index = 0;
    uint64_t timestamp = 0;
    unsigned long cur;
    uint32_t buf_size;
    int show_index = 0;
    char payload[2] = {0, 0};
    struct sdm_buffer *bufs;
    struct sdm_post_config *post;
    fast_rvc_data_t *rvc_data = (fast_rvc_data_t *)args;

    //① 初始化攝像頭,並設置顯示相關的配置。CAM_ID 要根據不同的情況設置不同的值。
    rvc_data->cam_id = CAM_ID;
    ret = csi_entry(rvc_data->cam_id);
    ......
    disp_layer_data_init(post->bufs);
    //② 初始化 g2d
    ......
    //③ 默認開啟,初始化 VDSP(CV engine) 視覺引擎,加載 early_app/fastrvc/vdsp.elf 和 early_app/fastrvc/MappingTable.bin
    #if SUPPORT_VDSP_DIST
    rvc_vdsp_init(rvc_data);
    #endif
    ......
    //④ Android 未啟動或車輛處於後退狀態時,進行圖像顯示
    while (!android_state || rvc_data->new_car_status) {
        //⑤ 車輛處於後退狀態時,使用 g2d + vdsp(如果未開啟 vdsp,則僅使用 g2d) 對圖像進行處理再顯示
        if (rvc_data->new_car_status) {
            #if SUPPORT_VDSP_DIST
            /* g2d + vdsp + disp */
            ......
            /* L.0 - convert YUV => RGB */
            ......
            #endif

            /* L.1 - VDSP distortion */
            //看 vdsp_start_one_frame 的實現,似乎並沒有進行圖像變形,而是只是給 vdsp 發送了 show_buf 和 tmp_buf 的地址,進行了 tmp_buf 到 show_buf 數據的拷貝
            ......

            /* L.2 - to display */
            ......

            //如果不開啟 vdsp 引擎的話,則僅使用 g2d 進行圖像處理
            #else

            /* g2d + disp */
            ......

            #endif
        }
        else//車輛不處於後退狀態
        {
            if (scs_csi_get_buf(cam_id, &buf_index, &timestamp) < 0) {
                printf("<%d, %s>:wrn:\n", __LINE__, __func__);
                continue;
            }

            post = &rvc_data->post;
            bufs = rvc_data->post.bufs;
            bufs->addr[0] = (unsigned long)rvc_data->show_buf[show_index];
            bufs->src_stride[0] = DISP_W * 3;
            bufs->layer_en = 0;
            //顯示
            ret = sdm_post(rvc_data->disp_handle, post);
            show_index = !show_index;

            scs_csi_set_buf(cam_id, buf_index);
        }
    }
    //關閉釋放所有資源
    ......

    return 0;
}

 



fast_rcv_detect_task 車輛後退檢測

  1. 創建 gpio 句柄,用來檢測車輛的後退狀態
  2. 開啟這個宏則隨機模擬車輛後退狀態,否則則通過 gpio 讀取
  3. new_car_status 指示當前汽車狀態,如果狀態發生變化且車輛後退,更新 rvc_data 的狀態以通知其他線程。
    以下為線程處理流程:
        static int fast_rcv_detect_task(void *args) {
            u8 is_car_back = 0;
            char payload[2] = {0, 0};
            void *rvc_gpio_handle;
            fast_rvc_data_t *rvc_data = (fast_rvc_data_t *)args;

            //① 創建 gpio 句柄,用來檢測車輛的後退狀態
            if (!hal_dio_creat_handle(&rvc_gpio_handle, g_gpio_res.res_id[0])) {
                printf("<%d, %s>:err:\n", __LINE__, __func__);
                return -1;
            }

            while (1)
            {
                /* car angle detect */
                if (android_state == 0) {
                    mutex_acquire(&rvc_data->data_mutex);
                    rvc_data->new_angle_index = 0;
                    mutex_release(&rvc_data->data_mutex);
                }
                //② 開啟這個宏則隨機模擬車輛後退狀態,否則則通過 gpio 讀取,測試情況下建議開啟
                #if REPEAT_CAR_BACK_TEST
                unsigned int rand1 = ((unsigned int)rand()) % 100 + 400;
                unsigned int rand2 = ((unsigned int)rand()) % 100 + 400;
                //後退與非後退狀態交替出現隨機時間,建議調試圖像時 is_car_back 恆等於 1,避免閃到眼睛
                is_car_back = !is_car_back;
                if(is_car_back == 1)
                    thread_sleep(rand1);/*thread_sleep(500);*/
                else
                    thread_sleep(rand2);/*thread_sleep(500);*/
                #else
                /* car back detect, user to open */
                //is_car_back = (u8)hal_dio_read_channel(rvc_gpio_handle, RVC_DETECT_GPIO)
                #endif
                //③ new_car_status 指示當前汽車狀態,如果狀態發生變化且車輛後退,更新 rvc_data 的狀態以通知其他線程。
                if (rvc_data->new_car_status != is_car_back) {
                    //android_state 指示 ap1(Android)的啟動狀態,如果 Android 已啟動完成,則向 Android 發送當前汽車狀態。
                    if (android_state == 1) {
                        /* notify ap */
                        payload[0] = 0x01;
                        payload[1] = rvc_data->new_car_status;
                        ipcc_channel_sendto(rvc_data->ipcc_chan, 300, payload,
                            sizeof(payload), 100);
                    }

                mutex_acquire(&rvc_data->data_mutex);
                rvc_data->new_car_status = is_car_back;
                mutex_release(&rvc_data->data_mutex);
            }

            thread_sleep(100);
        }

        //ipcc_channel_stop(rvc_data->ipcc_chan);
        //ipcc_channel_destroy(rvc_data->ipcc_chan);
        //hal_dio_release_handle(&rvc_gpio_handle);
        return 0;
    }

 

fast_rcv_lvgl_task 倒車方向邊框線顯示

  • lvgl 圖形庫初始化
  • 獲取當前活動的顯示螢幕
  • 設置螢幕的背景透明度並獲取螢幕大小。
  • 設置倒車軌跡背景圖的顯示
  • 設置倒車軌跡彎曲角度圖片的顯示
  • 創建線程,線程中根據 android_state、new_car_status、new_angle_index 來決定是否顯示倒車軌跡及倒車軌跡彎曲角度
  • 刷新顯示
  • 調用 lvgl 庫的事件處理函數
    以下為線程處理流程:
    static int fast_rcv_lvgl_task(void *args) {
        uint32_t screen_w;
        uint32_t screen_h;
        char angle_path[128] = {0};
        fast_rvc_data_t *rvc_data = (fast_rvc_data_t *)args;

        //① lvgl 圖形庫初始化
        lvgl_init();

        //thread_sleep(40);   /* wait camera showed */
        //② 獲取當前活動的顯示螢幕
        rvc_data->lvgl_screen = lv_disp_get_scr_act(get_display(LCD_ID));
        //③ 設置螢幕的背景透明度並獲取螢幕大小。
        lv_obj_set_style_local_bg_opa(rvc_data->lvgl_screen, LV_OBJ_PART_MAIN,
            LV_STATE_DEFAULT, LV_OPA_TRANSP);
        get_lvgl_screen_size(rvc_data->lvgl_screen, &screen_w, &screen_h);
        //④ 設置倒車軌跡背景圖的顯示
        rvc_data->img_bg = lv_img_create(rvc_data->lvgl_screen, NULL);
        lv_img_set_src(rvc_data->img_bg, (char *)("S:/early_app/fastrvc/bg.png"));
        lv_obj_set_pos(rvc_data->img_bg, ((LCD_W - 960)/2), ((LCD_H - 720)/2));
        lv_obj_set_hidden(rvc_data->img_bg, 0);
        //⑤ 設置倒車軌跡彎曲角度圖片的顯示
        rvc_data->img_angle = lv_img_create(rvc_data->lvgl_screen, NULL);
        memset(angle_path, 0, sizeof(angle_path));
        sprintf(angle_path, "S:/early_app/fastrvc/angle_%d.png", rvc_data->new_angle_index);
        lv_img_set_src(rvc_data->img_angle, angle_path);
        lv_obj_set_pos(rvc_data->img_angle, ((LCD_W - 960)/2), ((LCD_H - 720)/2));
        lv_obj_set_hidden(rvc_data->img_angle, 0);

        //⑥ 創建線程,線程中根據 android_state、new_car_status、new_angle_index 來決定是否顯示倒車軌跡及倒車軌跡彎曲角度
        rvc_data->lv_line_task = lv_task_create(lv_line_task_cb, 50/*ms*/,
            LV_TASK_PRIO_LOW, rvc_data);
        //⑦ 刷新顯示
        lv_set_flush_enabled_for_disp(get_display(LCD_ID), true);
        while (1) {
            //⑧ 調用 lvgl 庫的事件處理函數
            lv_task_handler();
            thread_sleep(50);
            if (0) {
                uint64_t time_cur;
                uint32_t ms, us;
                time_cur = current_time_hires();
                ms = (uint32_t)(time_cur / 1000);
                us = (uint32_t)(time_cur % 1000);
                printf("time=%d.%03d\n", ms, us);
            }
        }

        return 0;
    }

四、編譯運行

  1. 編譯

    修改 json 文件配置:
    添加 freertos config:ENABLE_FASTRVC=true SUPPORT_VDSP_DIST=true
    添加 "gen-pac" 資源打包:"safety-res":"fastrvc"

    修改 freertos_safety/application/early_app/fastrvc/src/fast_rvc.c:
    #define REPEAT_CAR_BACK_TEST 1 #define CAM_ID 0 //修改為適配的 CAM_ID,可參考啟動時 cam_serviy 的列印信息


  2. 運行 fastrvc 上電快速自啟。

 

五、調試方法

  1. safety 命令 fastrvc_new_car_status:
    通過命令修改車輛狀態,來決定是否顯示倒車影像。但由於 fast_rcv_detect_task 線程是 while 循環運行,並隊車輛狀態進行翻轉,因此命令只在該線程休眠時有效。可通過修改代碼來使命令持續有效。
  2. safety 命令 fastrvc_new_angle_index:
    通過命令修改倒車軌跡角度。但由於 lv_line_task_cb 線程是 while 循環運行,並隊倒車軌跡角度進行翻轉,因此命令只在該線程休眠時有效。可通過修改代碼來使命令持續有效。


六、客制化部分

  1. 圖像配置。

    大部分可通過 fastrvc.c 宏定義部分來配置圖像參數。
    修改圖像格式(RGB/YUV 等),需要手動修改大部分代碼邏輯,所有涉及 csi、g2d、disp init 部分、buffer size 部分及 fast_rcv_show_task 的相關邏輯。一般情況下不修改。

        /* performance test */
        #define PERF_TEST 0
        /* pressure test */
        #define REPEAT_CAR_BACK_TEST 1  
        /* fisheye distortion */
        #define SUPPORT_VDSP_DIST 1

        #define LCD_ID  INFOTAINMENT
        #define LCD_W  1920     //LCD 螢幕寬
        #define LCD_H  720      //LCD 螢幕高

        #define DISP_W  1280    //倒車影像區域的寬
        #define DISP_H  720     //倒車影像區域的高
        #define DISP_X  ((LCD_W - DISP_W)/2)    //倒車影像區域顯示起點--X 軸
        #define DISP_Y  ((LCD_H - DISP_H)/2)    //倒車影像區域顯示起點--Y 軸

        #define CAM_ID  0               //framework 層的 camera id
        #define CAM_BUF_CNT 3           //camera 圖像緩衝區個數
        #define CAM_W 1280              //圖像源寬度
        #define CAM_H 720               //圖像源高度

        /* detection gpio */
        #define RVC_DETECT_GPIO  PortConf_PIN_GPIO_A6   //此 gpio 口狀態用於判定是否發生了車輛後退

        //vdsp 固件配置,勿更改
        #define VDSP_ELF_PATH "early_app/fastrvc/vdsp.elf"
        #define MAP_TAB_PATH "early_app/fastrvc/MappingTable.bin"
        #define VDSP_FW_RUNTIME_MEM (ap2p(VDSP_MEMBASE))

     

  2. 倒車軌跡算法

    根據需要修改 fast_rcv_lvgl_task。



    總結:以上為芯馳 X9 safety domain 的 fastrvc 快啟倒車影響 demo 的使用方法和代碼解析。

★博文內容均由個人提供,與平台無關,如有違法或侵權,請與網站管理員聯繫。

★文明上網,請理性發言。內容一周內被舉報5次,發文人進小黑屋喔~

評論