Melis4.0[D1s]:2.启动流程(GUI桌面加载部分)跟踪笔记


在阅读Melis4.0GUI加载流程,顺手做笔记,供自己查阅。

0. 控制台输出信息等级设置

为了方便跟踪代码执行流程,可以参考控制台的输出信息。控制台输出调试信息有6个等级,分别为0-5:

#define OPTION_LOG_LEVEL_CLOSE             0
#define OPTION_LOG_LEVEL_LOG               1
#define OPTION_LOG_LEVEL_ERROR             2
#define OPTION_LOG_LEVEL_WARNING           3
#define OPTION_LOG_LEVEL_INFO              4
#define OPTION_LOG_LEVEL_MESSAGE           5

在GUI源码中,有很多INFO级别的调试信息,可以打开观察学习:
在这里插入图片描述

0.1 设置log level = 4 无法正常启动

设置log level = 4,测试了一下,显示开机界面后就死机了,一直打印下面的信息,等了几分钟都没有反应:

[INF]: [riscv_cpu_handle_exception:0271]:                   ecall SYSCALL_FROM_S

只好设置为log level = 3 。可以正常使用,但是界面切换比 log level = 2会慢一点。

1.宏观启动流程

Melis启动顺序的介绍在《Melis4.0 RTOS_方案快速开发指南》,这里先上一张该文档的截图:
在这里插入图片描述

1.1 控制台入口函数finsh_thread_entry()执行《startup.sh》

这个函数在文件 《ekernel\subsys\finsh_cli\shell_entry.c》 中,在进入cli(command line interface)之前,会执行《startup.sh》文件。
在这里插入图片描述

1.2 《startup.sh》启动桌面GUI模块

1.2.1 《startup.sh》加载 desktop.mod

该文件的路径为 《projects\d1s-mq\data\UDISK\startup.sh》 ,内容如下:

echo "Execute startup script begin.............."

#insmod d:\mod\display.mod
insmod d:\mod\orange.mod
insmod d:\apps\desktop.mod
echo "...............Execute startup script end"

desktop.mod就是桌面GUI的入口app。它主要由《D1s-Melis\livedesk\beetles\mod_desktop\》目录下的文件编译链接产生。该目录下的Makefile文件:

ccflags-y           +=  -DEPDK_DEBUG_LEVEL=EPDK_DEBUG_LEVEL_LOG_ALL         \
                        -DUSED_BY_DESKTOP                                   \
                        $(SOLUTION_INCLUDE)

usrlibs-y           +=  -L$(srctree)/${elibrary-libs}/          \
                        --start-group                           \
                        -lsyscall    -lminic                    \
                        -llzma       -lcharset                  \
                        -lmediainfo                             \
                        --end-group

#-lmediainfo
MOD_NAME            := desktop
SUF_NAME            := mod
PRJ_PATH            := $(MELIS_BASE)/projects/${TARGET_BOARD}/data/UDISK/apps/
TEMP_PATH           := $(MELIS_BASE)/emodules/bin

$(MOD_NAME)-objs    += desktop_api.o
$(MOD_NAME)-objs    += mod_desktop.o
$(MOD_NAME)-objs    += magic.o
$(MOD_NAME)-objs    += built-in.o

$(MOD_NAME)-objs    += engine/
$(MOD_NAME)-objs    += framework/
$(MOD_NAME)-objs    += functions/
$(MOD_NAME)-objs    += msg_srv/
$(MOD_NAME)-objs    += util/

include $(MELIS_BASE)/scripts/Makefile.mods

1.2.2 desktop.mod加载 init.axf

mod_desktop.c 中加载GUI的函数 DESKTOP_MOpen()代码,其中的 init.axf 就是完成GUI准备工作可执行文件 :

__mp *DESKTOP_MOpen(__u32 mid, __u32 mod)
{
    
    
    __log("DESKTOP_MOpen.");
    int ret = -1, value = 0;
    desktp_data.mid  = mid;
	
	ret = esCFG_GetKeyValue("card_product", "card_product_used", (int32_t *)&value, 1);
	if (ret == -1 || value == 0)
	{
    
    
		desktp_data.init_id = esMODS_MInstall(BEETLES_APP_ROOT"apps\\init.axf", 0);
	} else if (value) {
    
    
		desktp_data.init_id = esMODS_MInstall(BEETLES_APP_ROOT"apps\\init_sd_product.axf", 0);
	}
    desktp_data.init_mp = esMODS_MOpen(desktp_data.init_id, 0);
    return (__mp *)&desktp_data;
}

1.2.3 init.axf 介绍

请注意,这里有2个C文件名很相似:init_mod.c 和 mod_init.c 。
init.axf《livedesk\beetles\init》 目录下的源码编译链接产生。看看该目录下的Makefile部分内容:
在这里插入图片描述
主要函数INIT_MOpen()在文件 《livedesk\beetles\init\mod_init.c》 中:

__mp *INIT_MOpen(__u32 mid, __u32 mod)
{
    
    
    __inf("----------------------INIT_MOpen --------------------------\n");
    msg_emit_init();

    init_data.mid      = mid;
    init_data.init_tid = esKRNL_TCreate(application_init_process, NULL, 0x10000, KRNL_priolevel3);
    esKRNL_TaskNameSet(init_data.init_tid, "initprocess");
    if (init_data.init_tid == 0)
    {
    
    
        __err(" application_init_process main thread create error\n");
        return NULL;
    }

    return (__mp *)&init_data;
}

1.2.3.1 INIT_MOpen()调用application_init_process()启动消息死循环

application_init_process()在文件 《livedesk\beetles\init\init_mod.c》 中:

void application_init_process(void *arg)
{
    
    
	.....
	__log("%s %d before init_mainwin_create", __FUNCTION__, __LINE__);
    init_mainwin        = init_mainwin_create();
    .....
    _process_init();    
    __log("%s %d before GUI_GetMessageEx", __FUNCTION__, __LINE__);
    /* message loop*/
    while (GUI_GetMessageEx(&msg, init_mainwin))    // 消息循环
    {
    
    
#ifdef __MSG
        if (msg.id != GUI_MSG_TIMER)
        {
    
    
            __msg("msg.h_deswin=%x, msg.id=%d, msg.dwAddData1=%d,msg.dwAddData2=%d", msg.h_deswin, msg.id, msg.dwAddData1, msg.dwAddData2);
        }
#endif
        ret = GUI_DispatchMessage(&msg);        // 分发消息到回调

        if (msg.p_arg)                          // 同步消息回应
        {
    
    
            GUI_SetSyncMsgRetVal(&msg, ret);
            GUI_PostSyncSem(&msg);
        }
    }
    __log("%s %d want to shutdown_logo_show", __FUNCTION__, __LINE__);//	add by hwd00001
    .....
}

上面的代码一直停留在消息循环中,正常情况不会退出循环。我在消息循环后面加了打印log信息,一直没有看到log输出。

1.2.3.2 application_init_process()调用gscene_bgd_init()设置背景图片

逐级调用函数 所在文件
application_init_process() livedesk\beetles\init\init_mod.c
gscene_bgd_init() livedesk\beetles\init\background\gscene_backgrd.c
gscene_bgd_set_status_show() livedesk\beetles\init\background\gscene_backgrd.c
gscene_bgd_update_filename() livedesk\beetles\init\background\gscene_backgrd.c
gscene_bgd_get_default_file() livedesk\beetles\init\background\gscene_backgrd.c
get_logo_mode() livedesk\beetles\init\background\fb_lib\backlayer_lib.c

这里重点分析一下get_logo_mode()

uint32_t get_logo_mode(void)
{
    
    
    if (esCFG_GetKeyValue("backlayer", "backlayer_mode", &bk_mode, 1) != EPDK_OK)
    {
    
    
        bk_mode = 0;
        __err("get_logo_mode err!");
    }
    return bk_mode;
}

esCFG_GetKeyValue()函数是从 sys_config_nor.fex 中读取键值,这里是 backlayer_mode=0:
在这里插入图片描述
gscene_bgd_get_default_file()于是获取的图片名称为 res\bg_default0.jpg ,对应的SDK目录下的 《projects\d1s-mq\data\UDISK\res\bg_default0.jpg》 ,只要更换这个图片,使用相同的名称,就可以改变背景图片。
sys_config.fex 的读写可参考官方文档《Melis4.0_RTOS_配置(sys_config)_开发指南.pdf
gscene_bgd_get_default_file()部分源码:

static int32_t gscene_bgd_get_default_file(char *filename)
{
    
    
    int32_t     index;
    char        path[BG_MAX_CHAR_LEN] = {
    
    0};

    index   = gscene_bgd_get_default_bg_index();
    if (get_logo_mode() == JPG_MODE)
    {
    
    
        eLIBs_sprintf(path, "%sbg_default%d.jpg", BG_DEFAULT_PATH, index);
    }
    else
    {
    
    
        eLIBs_sprintf(path, "%sbg_default%d.bgd", BG_DEFAULT_PATH, index);
    }
    ......
}

1.2.3.3 application_init_process()调用_process_init()

application_init_process()_process_init()位于同一个C文件。

static void _process_init(void)
{
    
    
    H_WIN                   scene_adjust;
    int32_t flag            = 2;
    char load_para[1024]    = {
    
    0};

    _framework_init();

    #if CONFIG_SUPPORT_TOUCHPANEL
    open("/dev/tpadc_rtp", O_WRONLY);
    #endif
    
    eLIBs_memcpy(load_para, &flag, 4);
    __msg("********_process_init***********");
    activity_set_load_para("root", "", load_para, sizeof(load_para));
    activity_load_app("application://app_root");
}

到此处,加载 app_root.axf,启动GUI桌面程序。

2. GUI桌面app加载

2.1 app_root.axf 介绍

app_root.axf《livedesk\beetles\sun20iw1_app\apps》 目录下的源码编译链接产生。看看该文件下的Makefile部分内容:
在这里插入图片描述

2.2 主函数 app_root_start()调用app_root_wincreate()创建根窗口

app_root_start()在文件 《livedesk\beetles\sun20iw1_app\apps\app_root\app_root.c》 中:

/**********************************************************************************************************************
插件接口实现
**********************************************************************************************************************/
static int32_t app_root_start(Activity *activity)
{
    
    
    __inf("**************app_root plugin start!**************** \n");
    __inf("****************************\n");
    
    app_root_init_res();

    root_activity       = activity;
    happ_root_manwin    = app_root_wincreate(activity);

    if (NULL == happ_root_manwin)
    {
    
    
        __inf("	 app_root_wincreate fail! \n");
        return EPDK_FAIL;
    }
    else
    {
    
    
        GUI_WinSetFocusChild(happ_root_manwin);
        __inf("	 app_root_wincreate success! \n");
        return EPDK_OK;
    }
}

E:\C_code\D1s-Melis\livedesk\beetles\sun20iw1_app\apps\app_root\app_root_scene.c

逐级调用函数 所在文件
app_root_start() livedesk\beetles\sun20iw1_app\apps\app_root\app_root_scene.c
app_root_wincreate() livedesk\beetles\sun20iw1_app\apps\app_root\app_root_scene.c
app_root_win_proc() livedesk\beetles\sun20iw1_app\apps\app_root\app_root_scene.c
app_home_create() livedesk\beetles\sun20iw1_app\apps\multi_screen_home\app_multi_screen_home.c
_home_on_create() livedesk\beetles\sun20iw1_app\apps\multi_screen_home\desktop_scene\desktop_scene.c
desktop_scene_create() livedesk\beetles\sun20iw1_app\apps\multi_screen_home\desktop_scene\desktop_scene.c

2.2 主函数 _home_on_create()调用init_multi_screen_res()初始化图片、文字资源

跟踪到这里,虽然还不知道如何显示界面的图片,不过已经明白如何替换图片了。
init_multi_screen_res()初始化主界面的8个图片(每个图片分焦点和非焦点2种),8个字符串。

static const __s32  multi_screen_uf_icon[HOME_UNFOCUS_ICON_NUM] =
{
    
    
    //固定应用
    ID_HOME_NEW_EXPLORER_UF_BMP,
    ID_HOME_NEW_MOVIE_UF_BMP,
    ID_HOME_NEW_MUSIC_UF_BMP,
    ID_HOME_NEW_PICTURE_UF_BMP,
    ID_HOME_NEW_EBOOK_UF_BMP,
    ID_HOME_NEW_FM_UF_BMP,
    ID_HOME_NEW_RECORD_UF_BMP,
    ID_HOME_NEW_SETTING_UF_BMP,
};
static const __s32  multi_screen_f_icon[HOME_FOCUS_ICON_NUM] =
{
    
    
    //固定应用选中
    ID_HOME_NEW_EXPLORER_FC_BMP,
    ID_HOME_NEW_MOVIE_FC_BMP,
    ID_HOME_NEW_MUSIC_FC_BMP,
    ID_HOME_NEW_PICTURE_FC_BMP,
    ID_HOME_NEW_EBOOK_FC_BMP,
    ID_HOME_NEW_FM_FC_BMP,
    ID_HOME_NEW_RECORD_FC_BMP,
    ID_HOME_NEW_SETTING_FC_BMP
};

static const int32_t  multi_screen_string[MULTI_SCREEN_STRING_MAX] =
{
    
    
    STRING_HOME_EXPLORER,
    STRING_HOME_MOVIE,
    STRING_HOME_MUSIC,
    STRING_HOME_PHOTO,
    STRING_HOME_EBOOK,
    STRING_HOME_FM,
    STRING_HOME_RECORD,
    STRING_HOME_SETTING
};
int32_t init_multi_screen_res(pmulti_screen_ui_t pui, __s16 current_focus)
{
    
    
    uint32_t   i;
    //初始化unfocus ICON 资源
    for (i = HOME_UNFOCUS_ICON_START; i < HOME_UNFOCUS_ICON_NUM; i++)
    {
    
    
        if (multi_screen_uf_icon[i])
        {
    
    
            pui->bmp_uf[i] = dsk_theme_open(multi_screen_uf_icon[i]);

            if (pui->bmp_uf[i] == NULL)
            {
    
    
                __wrn("init_multi_screen_res() index:%d open fail\n", i);
            }
        }
        else
        {
    
    
            pui->bmp_uf[i] = NULL;
        }
    }

    /*focus icon*/
    pui->bmp_f[current_focus] = dsk_theme_open(multi_screen_f_icon[current_focus]);

    //初始化String 资源
    for (i = 0; i < MULTI_SCREEN_STRING_MAX; i++)
    {
    
    
        dsk_langres_get_menu_text(multi_screen_string[i], pui->lang[i], GUI_NAME_MAX);
    }

    return EPDK_OK;
}

在这里插入图片描述
以图中文件管理图标为例,说说我的理解。
文件管理的非焦点图标ID为 ID_HOME_NEW_EXPLORER_UF_BMP ,焦点图标为 ID_HOME_NEW_EXPLORER_FC_BMP,对应的资源文件:
在这里插入图片描述
详细的可以阅读《livedesk\beetles\sun20iw1_app\res\theme》目录下的文件,我现在只是一知半解。
在这里插入图片描述
《facebuildercmd》生成 theme.htheme.bin,h文件供源码使用,bin文件则嵌入到image中,在运行中使用。

2.3 dsk_theme_open() 通过ID获取图片数据

dsk_theme_open()部分源码:

int32_t init_multi_screen_res(pmulti_screen_ui_t pui, __s16 current_focus)
{
    
    
......
            pui->bmp_uf[i] = dsk_theme_open(multi_screen_uf_icon[i]);
......

    /*focus icon*/
    pui->bmp_f[current_focus] = dsk_theme_open(multi_screen_f_icon[current_focus]);
......
}    

dsk_theme_open()函数就是根据 theme.h 范围内的ID,到 theme.bin找到相应的图片数据。

3.绘制主界面

3.1 draw_multi_screen_icon_coor_rect()函数调用表格

逐级调用函数 所在文件
desktop_scene_create() livedesk\beetles\sun20iw1_app\apps\multi_screen_home\desktop_scene\desktop_scene.c
desktop_scene_frm_manager_proc() livedesk\beetles\sun20iw1_app\apps\multi_screen_home\desktop_scene\desktop_scene.c
desktop_scene_view_show_all() livedesk\beetles\sun20iw1_app\apps\multi_screen_home\desktop_scene\desktop_scene.c
draw_multi_screen_icon_coor_rect() livedesk\beetles\sun20iw1_app\apps\multi_screen_home\ui\multi_screen_ui.c

draw_multi_screen_icon_coor_rect()用来绘制界面图标,其中 uf_rect_800_480[8] 是指定图标的区域:

draw_multi_screen_icon_coor_rect(self->pui, HOME_UNFOCUS_ICON_START + i, 
								EPDK_FALSE, &uf_rect_800_480[i]);

《livedesk\beetles\sun20iw1_app\apps\multi_screen_home\desktop_scene\desktop_scene.h》部分内容:

static GUI_RECT uf_rect_800_480[MULTI_SCREEN_STRING_MAX] =
{
    
    
    {
    
    16,                                    80,     16 + 180,                                   80 + 142},
    {
    
    16 + 180 + 16,                         80,     16 + 180 + 16 + 180,                        80 + 142},
    {
    
    16 + 180 + 16 + 180 + 16,              80,     16 + 180 + 16 + 180 + 16 + 180,             80 + 142},
    {
    
    16 + 180 + 16 + 180 + 16 + 180 + 16,   80,     16 + 180 + 16 + 180 + 16 + 180 + 16 + 180,  80 + 142},

    {
    
    16,                                    80 + 50 + 142,  16 + 180,                                   80 + 142 + 50 + 142},
    {
    
    16 + 180 + 16,                         80 + 50 + 142,  16 + 180 + 16 + 180,                        80 + 142 + 50 + 142},
    {
    
    16 + 180 + 16 + 180 + 16,              80 + 50 + 142,  16 + 180 + 16 + 180 + 16 + 180,             80 + 142 + 50 + 142},
    {
    
    16 + 180 + 16 + 180 + 16 + 180 + 16,   80 + 50 + 142,  16 + 180 + 16 + 180 + 16 + 180 + 16 + 180,  80 + 142 + 50 + 142},

};

猜你喜欢

转载自blog.csdn.net/hwd00001/article/details/129137747