导航

    全志在线开发者论坛

    • 注册
    • 登录
    • 搜索
    • 版块
    • 话题
    • 在线文档
    • 社区主页

    cma扩充和开机logo消失问题分享

    Linux
    1
    1
    1211
    正在加载更多帖子
    • 从旧到新
    • 从新到旧
    • 最多赞同
    回复
    • 在新帖中回复
    登录后回复
    此主题已被删除。只有拥有主题管理权限的用户可以查看。
    • xiaowenge
      DOT小文哥 LV 8 最后由 xiaowenge 编辑

      在使用的是128M dram的小内存配置,播放视频需要通过ion申请较多的连续物理内存空间,所以需要扩充CMA的大小,否则会导致cma扩充和开机logo消失。

      【芯片平台】R311
      【软件版本】tina3.5.1
      【问题背景】
      使用的是128MB的ddr,对于多视频播放和旋转的场景ion的使用非常吃紧,需要想办法扩大cma的大小。
      【问题简述】
      R311更改cma大小后,出现了不进kernel,开机logo消失等问题。
      【问题处理过程】
      (1)不进kernel:
      更改cma大小为72MB后,系统无法进kernel,撤回修改,查看系统保留内存的分布:

      root@TinaLinux:/# cat /sys/kernel/debug/memblock/reserved
         0: 0x40004000..0x40007fff, size:16K
         1: 0x40020000..0x40020fff, size:4K
         2: 0x40100000..0x40b480cb, size:10528K
         3: 0x41000000..0x4100000b, size:0K
         4: 0x43500000..0x4351617f, size:88K
         5: 0x43c00000..0x47bfffff, size:65536K
         6: 0x47cc8000..0x47f65fff, size:2680K
         7: 0x47f7da00..0x47f961ff, size:98K
         8: 0x47f9621c..0x47ffefff, size:419K
         9: 0x47fff640..0x47fff67b, size:0K
        10: 0x47fff680..0x47fff6bb, size:0K
        11: 0x47fff6c0..0x47fff737, size:0K
        12: 0x47fff740..0x47fff74f, size:0K
        13: 0x47fff780..0x47fff78f, size:0K
        14: 0x47fff7c0..0x47fff7c3, size:0K
        15: 0x47fff800..0x47fff9ad, size:0K
        16: 0x47fff9c0..0x47fffb6d, size:0K
        17: 0x47fffb80..0x47fffd2d, size:0K
        18: 0x47fffd40..0x47fffd43, size:0K
        19: 0x47fffd64..0x47fffd81, size:0K
        20: 0x47fffd84..0x47fffdb8, size:0K
        21: 0x47fffdbc..0x47fffe1c, size:0K
        22: 0x47fffe20..0x47fffe70, size:0K
        23: 0x47fffe74..0x47ffff06, size:0K
        24: 0x47ffff08..0x47ffff22, size:0K
        25: 0x47ffff24..0x47ffff3e, size:0K
        26: 0x47ffff40..0x47ffff5f, size:0K
        27: 0x47ffff64..0x47ffff7e, size:0K
        28: 0x47ffff80..0x47ffff8f, size:0K
        29: 0x47ffff94..0x47ffffae, size:0K
        30: 0x47ffffb0..0x47ffffff, size:0K
      

      发现dts起始地址为0x43500000,cma的下一个保留区域起始地址为0x47cc8000,留给dts和cma的空间只有0x47cc8000-0x43500000约为71MB,cma大小设置为72MB后,超出了范围,导致不进kernel。怎么解决问题?把dts的起始地址往前挪动一下,cma的空间就可以得到扩充,如下所示,把dts的位置向前挪动0x00500000,cma足够容纳72MB的cma保留区域:

      include/configs/sunxi-base.h:
      -#define CONFIG_SUNXI_FDT_ADDR              SDRAM_OFFSET(0x03500000)
      +#define CONFIG_SUNXI_FDT_ADDR              SDRAM_OFFSET(0x03000000)
      

      修改后的保留内存的分布如下:

      root@TinaLinux:/# cat /sys/kernel/debug/memblock/reserved
         0: 0x40004000..0x40007fff, size:16K
         1: 0x40020000..0x40020fff, size:4K
         2: 0x40100000..0x40b480cb, size:10528K
         3: 0x41000000..0x4100000b, size:0K
         4: 0x43000000..0x4301617f, size:88K
         5: 0x433fffff..0x47bfffff, size:73728K
         6: 0x47cc8000..0x47f65fff, size:2680K
         7: 0x47f7da00..0x47f961ff, size:98K
         8: 0x47f9621c..0x47ffefff, size:419K
         9: 0x47fff640..0x47fff67b, size:0K
        10: 0x47fff680..0x47fff6bb, size:0K
        11: 0x47fff6c0..0x47fff737, size:0K
        12: 0x47fff740..0x47fff74f, size:0K
        13: 0x47fff780..0x47fff78f, size:0K
        14: 0x47fff7c0..0x47fff7c3, size:0K
        15: 0x47fff800..0x47fff9ad, size:0K
        16: 0x47fff9c0..0x47fffb6d, size:0K
        17: 0x47fffb80..0x47fffd2d, size:0K
        18: 0x47fffd40..0x47fffd43, size:0K
        19: 0x47fffd64..0x47fffd81, size:0K
        20: 0x47fffd84..0x47fffdb8, size:0K
        21: 0x47fffdbc..0x47fffe1c, size:0K
        22: 0x47fffe20..0x47fffe70, size:0K
        23: 0x47fffe74..0x47ffff06, size:0K
        24: 0x47ffff08..0x47ffff22, size:0K
        25: 0x47ffff24..0x47ffff3e, size:0K
        26: 0x47ffff40..0x47ffff5f, size:0K
        27: 0x47ffff64..0x47ffff7e, size:0K
        28: 0x47ffff80..0x47ffff8f, size:0K
        29: 0x47ffff94..0x47ffffae, size:0K
        30: 0x47ffffb0..0x47ffffff, size:0K
      

      (2)开机logo消失:
      开机logo是从uboot解码并显示的,找到logo解码的地方:

       compress_buf = get_decode_buffer();
               if (compress_buf == NULL) {
                       printf("bmp compress_buf empty,quit\n");
                       set_bmp_decode_flag(BMP_DECODE_FAIL);
                       goto __third_cpu_end;
               }
       buf = (unsigned char *)(SUNXI_DISPLAY_FRAME_BUFFER_ADDR + SUNXI_DISPLAY_FRAME_BUFFER_SIZE);
      
               ret = sunxi_bmp_decode_from_compress(buf, compress_buf);
      
      

      发现需要从地址compress_buf把logo的bmp格式数据解压到buf地址,buf地址为SUNXI_DISPLAY_FRAME_BUFFER_ADDR + SUNXI_DISPLAY_FRAME_BUFFER_SIZE,也就是0x47400000。compress_buf的地址如下所示:

       if (next_mode == SUNXI_STATE_NORMAL_BOOT) {
        set_decode_buffer((unsigned char *)
         (SUNXI_LOGO_COMPRESSED_LOGO_BUFF));
       } else if (next_mode == SUNXI_STATE_SHUTDOWN_CHARGE) {
      
          从这里的代码片段知道,logo的原始数据放在地址SUNXI_LOGO_COMPRESSED_LOGO_BUFF,也就是0x43000010,而现在dts的区域的保留区域是( 0x43000000..0x4301617f),刚好覆盖到了SUNXI_LOGO_COMPRESSED_LOGO_BUFF。将SUNXI_LOGO_COMPRESSED_LOGO_BUFF改为0x42000000,这样就能使logo数据不落在内存的保留区域内。
          然而编译后再验证,发现logo还是没法显示,从目前得到的信息看不到问题点,说明问题的原因还是没有全部被找到,继续跟进解码数据的过程:
      
      int lzmaBuffToBuffDecompress (unsigned char *outStream, SizeT *uncompressedSize,
                         unsigned char *inStream,  SizeT  length)
      {
      .......
          /* Read the uncompressed size */
          for (i = 0; i < 8; i++) {
              unsigned char b = inStream[LZMA_SIZE_OFFSET + i];
                  if (i < 4) {
                      outSize     += (UInt32)(b) << (i * 8);
              } else {
                      outSizeHigh += (UInt32)(b) << ((i - 4) * 8);
              }
          }
      
          outSizeFull = (SizeT)outSize;
          if (sizeof(SizeT) >= 8) {
              /*
               * SizeT is a 64 bit uint => We can manage files larger than 4GB!
               *
               */
                  outSizeFull |= (((SizeT)outSizeHigh << 16) << 16);
          } else if (outSizeHigh != 0 || (UInt32)(SizeT)outSize != outSize) {
              /*
               * SizeT is a 32 bit uint => We cannot manage files larger than
               * 4GB!  Assume however that all 0xf values is "unknown size" and
               * not actually a file of 2^64 bits.
               *
               */
              if (outSizeHigh != (SizeT)-1 || outSize != (SizeT)-1) {
                  debug ("LZMA: 64bit support not enabled.\n");
                  return SZ_ERROR_DATA;
              }
          }
      .......
      }
      

      如上面代码片段所示,检查*inStream(内存中的bmp数据)前面8位信息的时候,函数报错返回了,这里说明了内存中的bmp数据有问题。bmp数据需要先从flash里面拷贝到内存SUNXI_LOGO_COMPRESSED_LOGO_BUFF中,后面才能从SUNXI_LOGO_COMPRESSED_LOGO_BUFF解码出来 。现数据有异常,需要检查bmp数据从flash拷贝到内存的过程。查找SUNXI_LOGO_COMPRESSED_LOGO_BUFF使用的地方,arch/arm/cpu/armv7/sun8iw15p1/spl/fip_common.c里面有类似从flash拷贝logo数据到内存的代码:

      arch/arm/cpu/armv7/sun8iw15p1/spl/fip_common.c:
      int load_fip(int *use_monitor)
      {
      ......
                       } else if (strncmp(toc1_item->name, ITEM_LOGO_NAME, sizeof(ITEM_LOGO_NAME)) == 0) {
                               *(uint *)(SUNXI_LOGO_COMPRESSED_LOGO_SIZE_ADDR) = toc1_item->data_len;
                               toc1_flash_read(toc1_item->data_offset/512, (toc1_item->data_len+511)/512, (void *)SUNXI_LOGO_COMPRESSED_LOGO_BUFF);
                       } else if (strncmp(toc1_item->name, ITEM_SHUTDOWNCHARGE_LOGO_NAME, sizeof(ITEM_SHUTDOWNCHARGE_LOGO_NAME)) == 0) {
      ......
      }
      

      从这段代码中看不出来有问题,再看看发现编译uboot的时候跟本不会编译到这个文件,怎么回事,询问负责uboot模块的同事得知,这里的文件是给boot0用的,logo数据从flash拷贝到内存的动作也是在boot0的时候做的。所以更新了SUNXI_LOGO_COMPRESSED_LOGO_BUFF的地址,还需要同时编译boot0,这样对于logo数据的拷贝和解码来说,SUNXI_LOGO_COMPRESSED_LOGO_BUFF才是相同的地址。

      (文 by. shaokang)

      1 条回复 最后回复 回复 引用 分享 1
      • 1 / 1
      • First post
        Last post

      Copyright © 2024 深圳全志在线有限公司 粤ICP备2021084185号 粤公网安备44030502007680号

      行为准则 | 用户协议 | 隐私权政策