rk3399 u

您所在的位置:网站首页 奥迪中控开机画面设置在哪里 rk3399 u

rk3399 u

2024-03-04 10:29| 来源: 网络整理| 查看: 265

首先分析了一下uboot启动流程中的一部分代码,如下

第一部分:开机logo(下面代码分析排版有点乱,可以忽略)

1.

​ board_late_init //rk33xx.c board/rockchip/rk33xx/rk33xx.c:238: board_fbt_preboot(); board_late_init board_fbt_preboot(); //fastboot.c 1. if (gd->fdt_blob) { int node = fdt_path_offset(gd->fdt_blob, "/display-subsystem");//找到display-subsystem这个noded,在rk3399-android.dtsi中指定为有效。 if (!fdt_device_is_available(gd->fdt_blob, node) || node < 0) { #if defined(CONFIG_LCD) g_is_new_display = 0; node = fdt_path_offset(gd->fdt_blob, "/fb"); g_logo_on_state = fdtdec_get_int(gd->fdt_blob, node, "rockchip,uboot-logo-on", 0); if (g_logo_on_state != 0) { lcd_enable_logo(true); drv_lcd_init();//drv_lcd_init } #else ​

drv_lcd_init:

drv_lcd_init();//drv_lcd_init //lcd.c lcd_init(lcd_base); //lcd.c lcd_ctrl_init(lcdbase);//rockchip_fb.c rk_lcdc_init(panel_info.lcdc_id); rk_lcdc_load_screen(&panel_info); ........ vop_config_timing(vop_dev, screen);//vop h_total = hsync_len + left_margin + x_res + right_margin; v_total = vsync_len + upper_margin + y_res + lower_margin; val = V_DSP_HS_END(hsync_len) | V_DSP_HTOTAL(h_total); vop_msk_reg(vop_dev, DSP_HTOTAL_HS_END, val); val = V_DSP_HACT_END(hsync_len + left_margin + x_res) | V_DSP_HACT_ST(hsync_len + left_margin); vop_msk_reg(vop_dev, DSP_HACT_ST_END, val); if (screen->mode.vmode & FB_VMODE_INTERLACED) { /* First Field Timing */ val = V_DSP_VS_END(vsync_len) | V_DSP_VTOTAL(2 * (vsync_len + upper_margin + lower_margin) + y_res + 1); vop_msk_reg(vop_dev, DSP_VTOTAL_VS_END, val); val = V_DSP_VACT_END(vsync_len + upper_margin + y_res / 2) | V_DSP_VACT_ST(vsync_len + upper_margin); vop_msk_reg(vop_dev, DSP_VACT_ST_END, val); /* Second Field Timing */ vs_st_f1 = vsync_len + upper_margin + y_res / 2 + lower_margin; vs_end_f1 = 2 * vsync_len + upper_margin + y_res / 2 + lower_margin; val = V_DSP_VS_ST_F1(vs_st_f1) | V_DSP_VS_END_F1(vs_end_f1); vop_msk_reg(vop_dev, DSP_VS_ST_END_F1, val); vact_end_f1 = 2 * (vsync_len + upper_margin) + y_res + lower_margin + 1; vact_st_f1 = 2 * (vsync_len + upper_margin) + y_res / 2 + lower_margin + 1; val = V_DSP_VACT_END_F1(vact_end_f1) | V_DSP_VACT_ST_F1(vact_st_f1); vop_msk_reg(vop_dev, DSP_VACT_ST_END_F1, val); vop_msk_reg(vop_dev, DSP_CTRL0, V_DSP_INTERLACE(1) | V_DSP_FIELD_POL(0)); val = V_DSP_LINE_FLAG_NUM_0(lower_margin ? vact_end_f1 : vact_end_f1 - 1); val |= V_DSP_LINE_FLAG_NUM_1(lower_margin ? vact_end_f1 : vact_end_f1 - 1); vop_msk_reg(vop_dev, LINE_FLAG, val); }else ........... vop_vop_post_cfg(vop_dev, screen); ......... post_dsp_vact_st = screen->post_dsp_sty / 2 + screen->mode.vsync_len + screen->mode.upper_margin; post_dsp_vact_end = post_dsp_vact_st + screen->post_ysize / 2; ......... val = V_DSP_HACT_END_POST(post_dsp_hact_end) | V_DSP_HACT_ST_POST(post_dsp_hact_st); vop_msk_reg(vop_dev, POST_DSP_HACT_INFO, val); val = V_DSP_VACT_END_POST(post_dsp_vact_end) | V_DSP_VACT_ST_POST(post_dsp_vact_st); ........ lcd_clear(); lcd_enable();

2.

2. rockchip_display_init() fdt_path_offset(blob, "/display-subsystem/route"); //寻找route node. fdt_device_is_available //查看route是否是okay的 init_display_buffer //获取fb地址 fdt_for_each_subnode //依次解析route下的子节点,当前用的edp,所以只解析route_edp节点。 fdt_node_offset_by_phandle //获取connect node. find_crtc_node//获取对应的ctrl node. rockchip_get_crtc  //根据ctrl node从g_crtc数组中找到具体的元素,这里compatible是"rockchip,rk3399-vop-big",在rk3399.dtsi中定义 find_connector_node //获取对应的connector node rockchip_get_connector //根据connector node从g_connector数组中找到具体的元素,这里compatible是"rockchip,rk3399-edp",在rk3399.dtsi中定义 malloc(sizeof(*s)); //display相关信息都放在struct display_state *s中 fdt_get_string(blob, child, "logo,uboot", &s->ulogo_name); //分别获取uboot/kernel中的logo name以及模式   fdt_get_string(blob, child, "logo,kernel", &s->klogo_name);   fdt_get_string(blob, child, "logo,mode", &name);   connector_phy_init //无phy node,3368平台需要配置。 connector_panel_init -> get_panel_node //获取edp panel node rockchip_get_panel //根据panel node从g_panel数组中找到具体型号panel,因此要添加一块新panel,那么对应timing信息需要添加到此数组中 connector_pclist_parse_dt //解析电源控制节点power_ctr,即lcd的enable以及reset gpio. rockchip_panel_init -> panel->funcs->init -> panel_simple_init -> panel_simple_parse_dt -> //此函数参数解析针对mipi屏 gpio_direction_output(enable_gpio->gpio, !!(enable_gpio->flags & OF_GPIO_ACTIVE_LOW)); //初始化之前先关屏 rk_pwm_bl_config(0); //关背光

 3.

3. rockchip_show_logo(); list_for_each_entry(s, &rockchip_display_list, head) { s->logo.mode = s->logo_mode; if (load_bmp_logo(&s->logo, s->ulogo_name))//获取图片,提取bpp、width、height这些信息 printf("failed to display uboot logo\n"); else display_logo(s);//display_logo if (load_bmp_logo(&s->logo, s->klogo_name)) printf("failed to display kernel logo\n"); } display_logo(s);//display_logo ........ display_init(state); display_get_timing(state); printf("Using display timing dts\n"); ........ display_set_plane(state); display_enable(state);

4.

4. lcd_standby(0);//使能 if (enable == 0) { rk32_dsi_enable();

5.

5. rk_pwm_bl_config(-1);//背光

6.修改:找一张bmp格式的图片,替换kernel下的logo.bmp图片即可 

第二部分:开机动画,先看一个函数,文件位置:源码目录下\frameworks\base\cmds\bootanimation\bootanimation.cpp

bool BootAnimation::threadLoop() { bool r; //add for boot video function mStartbootanimaTime = 0; mBootVideoTime = -1; if (mVideoAnimation){ r = video(); } else { // We have no bootanimation file, so we use the stock android logo // animation. if (mZipFileName.isEmpty()) { r = android();//这个地方显示动画,其实我也不是很懂这个东西,这个是framework那一层的东西,不过我试验过后发现就是这个地方对开机动画的处理 } else { r = movie(); } } eglMakeCurrent(mDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); eglDestroyContext(mDisplay, mContext); eglDestroySurface(mDisplay, mSurface); mFlingerSurface.clear(); mFlingerSurfaceControl.clear(); eglTerminate(mDisplay); IPCThreadState::self()->stopProcess(); return r; }

接下来在该文件顶部可以看到这么一段代码

namespace android { static const char OEM_BOOTANIMATION_FILE[] = "/oem/media/bootanimation.zip"; static const char SYSTEM_BOOTANIMATION_FILE[] = "/system/media/bootanimation.zip";//经试验,上面这两个是和开机动画相关的东西 static const char SYSTEM_SHUTDOWNANIMATION_FILE[] = "/system/media/shutdownanimation.zip"; static const char SYSTEM_ENCRYPTED_BOOTANIMATION_FILE[] = "/system/media/bootanimation-encrypted.zip"; //support boot video static const char DATA_BOOTVIDEO_FILE[] = "/data/local/bootanimation.ts"; static const char SYSTEM_BOOTVIDEO_FILE[] = "/system/media/bootanimation.ts"; static const char SYSTEM_DATA_DIR_PATH[] = "/data/system"; static const char SYSTEM_TIME_DIR_NAME[] = "time"; static const char SYSTEM_TIME_DIR_PATH[] = "/data/system/time"; static const char CLOCK_FONT_ASSET[] = "images/clock_font.png"; static const char CLOCK_FONT_ZIP_NAME[] = "clock_font.png"; static const char LAST_TIME_CHANGED_FILE_NAME[] = "last_time_change"; static const char LAST_TIME_CHANGED_FILE_PATH[] = "/data/system/time/last_time_change"; static const char ACCURATE_TIME_FLAG_FILE_NAME[] = "time_is_accurate"; static const char ACCURATE_TIME_FLAG_FILE_PATH[] = "/data/system/time/time_is_accurate"; static const char TIME_FORMAT_12_HOUR_FLAG_FILE_PATH[] = "/data/system/time/time_format_12_hour"; // Java timestamp format. Don't show the clock if the date is before 2000-01-01 00:00:00. static const long long ACCURATE_TIME_EPOCH = 946684800000; static constexpr char FONT_BEGIN_CHAR = ' '; static constexpr char FONT_END_CHAR = '~' + 1; static constexpr size_t FONT_NUM_CHARS = FONT_END_CHAR - FONT_BEGIN_CHAR + 1; static constexpr size_t FONT_NUM_COLS = 16; static constexpr size_t FONT_NUM_ROWS = FONT_NUM_CHARS / FONT_NUM_COLS; static const int TEXT_CENTER_VALUE = INT_MAX; static const int TEXT_MISSING_VALUE = INT_MIN; static const char EXIT_PROP_NAME[] = "service.bootanim.exit"; static const char LOOP_COMPLETED_PROP_NAME[] = "sys.anim_loop.completed"; static const char PLAY_SOUND_PROP_NAME[] = "persist.sys.bootanim.play_sound"; static const int ANIM_ENTRY_NAME_MAX = 256; static constexpr size_t TEXT_POS_LEN_MAX = 16; static const char BOOT_COMPLETED_PROP_NAME[] = "sys.boot_completed"; static const char BOOTREASON_PROP_NAME[] = "ro.boot.bootreason"; // bootreasons list in "system/core/bootstat/bootstat.cpp". static const std::vector PLAY_SOUND_BOOTREASON_BLACKLIST { "kernel_panic", "Panic", "Watchdog", };

上面的代码里边注意这么一句:

static const char SYSTEM_BOOTANIMATION_FILE[] = "/system/media/bootanimation.zip";

这里的/system/media/bootanimation.zip就是开机动画相关的文件,下面我以bootanimation.zip这个为例,里边有几个文件夹:part0、part1........很多个文件,这里边是一个动画的每一帧对应的图片,所谓开机动画,不过就是把这些图片连续的显示出来,该文件夹下面还有一个文件很重要,desc.txt,内容如下:

​ 580 152 60//580 152 是分辨率,60是指每秒播放帧数 c 1 30 part0//c 1 30 part0 1表示part0循环一次,0表示无限循环 30是时间间隔 c 1 0 part1 c 0 0 part2 c 1 64 part3 c 1 15 part4 ​

关于这个文件可以参考一下这篇文章:https://www.cnblogs.com/lialong1st/p/8984586.html 

接下来,找一个能够被编译进系统的 .mk文件,增加一点内容:如下

PRODUCT_COPY_FILES += \ device/rockchip/rk3399/rk3399_64/ddr_config.xml:system/etc/ddr_config.xml \ device/rockchip/rk3399/rk3399_64/video_status:system/etc/video_status \ device/rockchip/rk3399/g3399/gslX680.idc:system/usr/idc/gslX680.idc \ device/rockchip/rk3399/bootanimation.zip:system/media/bootanimation.zip\ //追加的内容冒号前边是.zip的路径,.zip文件与.mk文件在同一目录下边,这里我的.mk文件就是device/rockchip/rk3399/g3399.mk device/rockchip/rk3399/g3399/libquectel-ril.so:/system/lib64/libquectel-ril.so

这里新增的内容就是把:前面的文件拷贝到后面的文件里

如此,编译好,烧写到开发板就ok,关于bootanimation就自行百度吧,上面的图片格式是有所要求的,大小不能太大,这个是试验时发现的问题,还是建议用视频开机动画,方便又省事。

开机视频这部分需要修改/device/rockchip/rk3399_mid/system.prop,如果不行的话,找一下其他文件夹里边的system.prop ,我这儿懒得验证,于是在同目录下的g3399下的system.prop下也添加了同样的内容

#enable bootvideo persist.sys.bootvideo.enable=true persist.sys.bootvideo.showtime=10

 原因:

bool BootAnimation::threadLoop() { bool r; //add for boot video function mStartbootanimaTime = 0; mBootVideoTime = -1; if (mVideoAnimation){ r = video();//播放视频 } else { // We have no bootanimation file, so we use the stock android logo // animation. if (mZipFileName.isEmpty()) { r = android(); } else { r = movie(); } } eglMakeCurrent(mDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); eglDestroyContext(mDisplay, mContext); eglDestroySurface(mDisplay, mSurface); mFlingerSurface.clear(); mFlingerSurfaceControl.clear(); eglTerminate(mDisplay); IPCThreadState::self()->stopProcess(); return r; }

video:

​ property_get("persist.sys.bootvideo.enable",decrypt, "false");//这儿就是为什么要添加上边的内容的原因 char value[PROPERTY_VALUE_MAX]; property_get("persist.sys.bootvideo.showtime", value, "-1"); if(mVideoFile != NULL && !strcmp(decrypt, "true") &&(atoi(value)!=0)) { mVideoAnimation = true; }else{ ALOGD("bootvideo:No boot video animation,EXIT_VIDEO_NAME:%s,bootvideo.showtime:%s\n",decrypt,value); } ​

 

参考文章:https://blog.csdn.net/ooonebook/article/details/53206623(uboot阶段对dts的处理 fdt_xxx_xxx等函数说明)

                  https://blog.csdn.net/kris_fei/article/details/79003925

                  http://dev.t-firefly.com/thread-185-1-1.html



【本文地址】


今日新闻


推荐新闻


    CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3