飞思卡尔 I.MX6ULL 使用U-boot在屏幕上显示自定义图片

相关代码与修改飞思卡尔/恩智浦的开机logo相关,并且参考了原版显示开机logo的代码,首先请确保你的板子烧写的是飞思卡尔提供的u-boot,保证lcd驱动正常并且启动时能显示NXP字样

 

1,找到工程中logo图像的位置并替换

6UL一般是通过Makefile将git/tools/logos文件夹下的bmp图像文件链接进程序中,再由bmp_logo.c文件转换成数组形式再进行显示的,首先需要保证bmp文件是256色BMP格式,不然程序转换会导致图片显示出错。

如图,freescale.bmp就是我们要找的文件

这时候如果我们将我们想要的bmp文件重命名成freescale.bmp后再放入文件夹中进行替换之后,重新将u-boot编译并烧写至板子中即可看到NXP已经被修改了。

 

2,分析git/drivers/video/cfb_console.c文件

在此文件中我们看到了关于bmp_logo_data.h的相关引用

#ifdef	CONFIG_VIDEO_LOGO
#ifdef	CONFIG_VIDEO_BMP_LOGO
#include <bmp_logo.h>
#include <bmp_logo_data.h>
#define VIDEO_LOGO_WIDTH	BMP_LOGO_WIDTH
#define VIDEO_LOGO_HEIGHT	BMP_LOGO_HEIGHT
#define VIDEO_LOGO_LUT_OFFSET	BMP_LOGO_OFFSET
#define VIDEO_LOGO_COLORS	BMP_LOGO_COLORS

 

找到函数*video_logo

static void *video_logo(void)
{
  char info[128];
  int space, len;
  __maybe_unused int y_off = 0;
  __maybe_unused ulong addr;
  __maybe_unused char *s;

  splash_get_pos(&video_logo_xpos, &video_logo_ypos);

#ifdef CONFIG_SPLASH_SCREEN
  s = getenv("splashimage");
  if (s != NULL) {
    splash_screen_prepare();
    addr = simple_strtoul(s, NULL, 16);

    if (video_display_bitmap(addr,
          video_logo_xpos,
          video_logo_ypos) == 0) {
      video_logo_height = 0;
      return ((void *) (video_fb_address));
    }
  }
#endif /* CONFIG_SPLASH_SCREEN */

  logo_plot(video_fb_address, video_logo_xpos, video_logo_ypos);

#ifdef CONFIG_SPLASH_SCREEN_ALIGN
  /*
   * when using splashpos for video_logo, skip any info
   * output on video console if the logo is not at 0,0
   */
  if (video_logo_xpos || video_logo_ypos) {
    /*
     * video_logo_height is used in text and cursor offset
     * calculations. Since the console is below the logo,
     * we need to adjust the logo height
     */
    if (video_logo_ypos == BMP_ALIGN_CENTER)
      video_logo_height += max(0, (int)(VIDEO_VISIBLE_ROWS -
                 VIDEO_LOGO_HEIGHT) / 2);
    else if (video_logo_ypos > 0)
      video_logo_height += video_logo_ypos;

    return video_fb_address + video_logo_height * VIDEO_LINE_LEN;
  }
#endif
  if (board_cfb_skip())
    return 0;

  sprintf(info, " %s", version_string);

  space = (VIDEO_COLS - VIDEO_INFO_X) / VIDEO_FONT_WIDTH;
  len = strlen(info);

  if (len > space) {
    int xx = VIDEO_INFO_X, yy = VIDEO_INFO_Y;
    uchar *p = (uchar *) info;
    while (len) {
      if (len > space) {
        video_drawchars(xx, yy, p, space);
        len -= space;

        p = (uchar *) p + space;

        if (!y_off) {
          xx += VIDEO_FONT_WIDTH;
          space--;
        }
        yy += VIDEO_FONT_HEIGHT;

        y_off++;
      } else {
        video_drawchars(xx, yy, p, len);
        len = 0;
      }
    }
  } else
    video_drawstring(VIDEO_INFO_X, VIDEO_INFO_Y, (uchar *) info);

#ifdef CONFIG_CONSOLE_EXTRA_INFO
  {
    int i, n =
      ((video_logo_height -
        VIDEO_FONT_HEIGHT) / VIDEO_FONT_HEIGHT);

    for (i = 1; i < n; i++) {
      video_get_info_str(i, info);
      if (!*info)
        continue;

      len = strlen(info);
      if (len > space) {
        video_drawchars(VIDEO_INFO_X,
            VIDEO_INFO_Y +
            (i + y_off) *
              VIDEO_FONT_HEIGHT,
            (uchar *) info, space);
        y_off++;
        video_drawchars(VIDEO_INFO_X +
            VIDEO_FONT_WIDTH,
            VIDEO_INFO_Y +
              (i + y_off) *
              VIDEO_FONT_HEIGHT,
            (uchar *) info + space,
            len - space);
      } else {
        video_drawstring(VIDEO_INFO_X,
             VIDEO_INFO_Y +
             (i + y_off) *
              VIDEO_FONT_HEIGHT,
             (uchar *) info);
      }
    }
  }
#endif

  return (video_fb_address + video_logo_height * VIDEO_LINE_LEN);
}

 

此函数就是I.MX6ULL用于显示LOGO的函数,只需要更改此函数即可达到修改LOGO的目的,首先Makefile在自动生成logo_bmp相关的信息时会生成此LOGO的相关定义头文件bmp_logo.h,如下是默认logo文件生成的头文件

/*
 * Automatically generated by "tools/bmp_logo"
 *
 * DO NOT EDIT
 *
 */


#ifndef __BMP_LOGO_H__
#define __BMP_LOGO_H__

#define BMP_LOGO_WIDTH		364
#define BMP_LOGO_HEIGHT		128
#define BMP_LOGO_COLORS		240
#define BMP_LOGO_OFFSET		16

extern unsigned short bmp_logo_palette[];
extern unsigned char bmp_logo_bitmap[];

#endif /* __BMP_LOGO_H__ */

 

其中有包含logo长度与宽度的宏定义,我们可以利用这些宏定义来进行代码的编写。

接下来我们进行对*video_logo函数的修改,在函数的定义变量后加入以下的语句

char info[128];
int space, len;
__maybe_unused int y_off = 0;
__maybe_unused ulong addr;
__maybe_unused char *s;

if(video_logo_xpos == 0 && video_logo_ypos == 0)
       { 
          video_logo_xpos = (VIDEO_VISIBLE_COLS - BMP_LOGO_WIDTH ) >> 1; 
          video_logo_ypos = (VIDEO_VISIBLE_ROWS - BMP_LOGO_HEIGHT) >> 1; 
       }

将video_logo_xpos与video_logo_ypos分别设置为(屏幕长度-图片长度)的一半

//将数据左移1就是除2。

即将图片完整的显示在中间(如果直接使用屏幕的一半的话会超过中间显示,可以自己去试)

接下来将U-boot烧进板子,可以看到LOGO图片已经显示在中间了。

非常完美的LOGO!

3,修改宏定义CONFIG_SPLASH_SCREEN_ALIGN字段

以下是*video_logo函数中对于宏定义CONFIG_SPLASH_SCREEN_ALIGN汇编定义中的一段代码

#ifdef CONFIG_SPLASH_SCREEN_ALIGN
  /*
   * when using splashpos for video_logo, skip any info
   * output on video console if the logo is not at 0,0
   */
  if (video_logo_xpos || video_logo_ypos) {
    /*
     * video_logo_height is used in text and cursor offset
     * calculations. Since the console is below the logo,
     * we need to adjust the logo height
     */
    if (video_logo_ypos == BMP_ALIGN_CENTER)
      video_logo_height += max(0, (int)(VIDEO_VISIBLE_ROWS -
                 VIDEO_LOGO_HEIGHT) / 2);
    else if (video_logo_ypos > 0)
      video_logo_height += video_logo_ypos;

    return video_fb_address + video_logo_height * VIDEO_LINE_LEN;
  }
#endif

看着注释我们就知道了这段代码的作用就是如果logo的显示位置不在(0,0)点就不显示info消息,但是如果我们依旧需要显示一些需要的信息,就不能定义这个宏了。

取消这段代码很简单,随便修改宏定义或者直接改成0,还有就是在mu6ullevk.h中注释掉这段宏定义。

甚至可以直接删光

#define CONFIG_SYS_CONSOLE_IS_IN_ENV
#define CONFIG_SPLASH_SCREEN
//#define CONFIG_SPLASH_SCREEN_ALIGN
#define CONFIG_CMD_BMP
#define CONFIG_BMP_16BPP

我们知道默认在屏幕上输出的信息是宏定义U_BOOT_VERSION_STRING,这是此宏定义在/include/version.h中的定义

#define U_BOOT_VERSION_STRING U_BOOT_VERSION " (" U_BOOT_DATE " - " \
  U_BOOT_TIME " " U_BOOT_TZ ")" CONFIG_IDENT_STRING

就是uboot相关的一些编译信息,但是我们有些时候想显示一点自定义字段怎么办。

4,修改video_drawstring函数

通过观察*video_logo函数可以找到如下语句

sprintf(info, " %s", version_string);
     ···
else
     video_drawstring(VIDEO_INFO_X, VIDEO_INFO_Y, (uchar *) info);

可以看出先通过sprintf函数将version_string[]中的字段提取到info中,看一下version_string的定义。

const char __weak version_string[] = U_BOOT_VERSION_STRING;

很明显就是宏定义U_BOOT_VERSION_STRING,那么如果我们要修改打印的字段只需要修改else后面的video_drawstring就可以了。

将原来的注释掉,并且写上新的,三个参数分别代表(左上角为零点)(x轴距离,y轴距离,字符串指针),所以在写最后的字符串时先写字符串再强制类型转换为uchar *型就行了。

5,想使用自己的logo名,不想重命名

修改git/tools/下的Makefile在200行左右关于LOGO_BMP的定义

在第三个endif后加入以下定义

LOGO_BMP= $(srctree)/$(src)/logos/“你的文件名”.bmp

 

即可完成logo文件名的更换(一定要256色的bmp文件!),之后Makefile会将指定的bmp文件转换成bmp_logo.h&bmp_logo_data.h

重新编译烧写之后就会发现logo正下方出现自定义信息了

发表评论

电子邮件地址不会被公开。 必填项已用*标注

2 × 2 =